X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FFunction.cpp;h=c1a96de0a7738cf90a7ea0071c841768d5ea9fbc;hb=5eca075b74d62c621b160aa216b4cd50829a2cc7;hp=dd781964a9174ad28bb215a4a1132fab8cf9352f;hpb=9445e9aaa0240a897baf464ff89255acdcc7fbc9;p=oota-llvm.git diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index dd781964a91..c1a96de0a77 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -13,16 +13,18 @@ #include "llvm/Module.h" #include "llvm/DerivedTypes.h" -#include "llvm/ParameterAttributes.h" #include "llvm/IntrinsicInst.h" +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/LeakDetector.h" -#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/StringPool.h" #include "SymbolTableListTraitsImpl.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; BasicBlock *ilist_traits::createSentinel() { - BasicBlock *Ret = new BasicBlock(); + BasicBlock *Ret = BasicBlock::Create(); // This should not be garbage monitored. LeakDetector::removeGarbageObject(Ret); return Ret; @@ -72,69 +74,76 @@ void Argument::setParent(Function *parent) { LeakDetector::removeGarbageObject(this); } +/// getArgNo - Return the index of this formal argument in its containing +/// function. For example in "void foo(int a, float b)" a is 0 and b is 1. +unsigned Argument::getArgNo() const { + const Function *F = getParent(); + assert(F && "Argument is not in a function"); + + Function::const_arg_iterator AI = F->arg_begin(); + unsigned ArgIdx = 0; + for (; &*AI != this; ++AI) + ++ArgIdx; + + return ArgIdx; +} + +/// hasByValAttr - Return true if this argument has the byval attribute on it +/// in its containing function. +bool Argument::hasByValAttr() const { + if (!isa(getType())) return false; + return getParent()->paramHasAttr(getArgNo()+1, ParamAttr::ByVal); +} + +/// hasNoAliasAttr - Return true if this argument has the noalias attribute on +/// it in its containing function. +bool Argument::hasNoAliasAttr() const { + if (!isa(getType())) return false; + return getParent()->paramHasAttr(getArgNo()+1, ParamAttr::NoAlias); +} + +/// hasSRetAttr - Return true if this argument has the sret attribute on +/// it in its containing function. +bool Argument::hasStructRetAttr() const { + if (!isa(getType())) return false; + if (this != getParent()->arg_begin()) + return false; // StructRet param must be first param + return getParent()->paramHasAttr(1, ParamAttr::StructRet); +} + +/// addAttr - Add a ParamAttr to an argument +void Argument::addAttr(ParameterAttributes attr) { + getParent()->addParamAttr(getArgNo() + 1, attr); +} + +/// removeAttr - Remove a ParamAttr from an argument +void Argument::removeAttr(ParameterAttributes attr) { + getParent()->removeParamAttr(getArgNo() + 1, attr); +} + + //===----------------------------------------------------------------------===// -// ParamAttrsList Implementation +// Helper Methods in Function //===----------------------------------------------------------------------===// -uint16_t -ParamAttrsList::getParamAttrs(uint16_t Index) const { - unsigned limit = attrs.size(); - for (unsigned i = 0; i < limit; ++i) - if (attrs[i].index == Index) - return attrs[i].attrs; - return ParamAttr::None; -} - - -std::string -ParamAttrsList::getParamAttrsText(uint16_t Attrs) { - std::string Result; - if (Attrs & ParamAttr::ZExt) - Result += "zeroext "; - if (Attrs & ParamAttr::SExt) - Result += "signext "; - if (Attrs & ParamAttr::NoReturn) - Result += "noreturn "; - if (Attrs & ParamAttr::NoUnwind) - Result += "nounwind "; - if (Attrs & ParamAttr::InReg) - Result += "inreg "; - if (Attrs & ParamAttr::NoAlias) - Result += "noalias "; - if (Attrs & ParamAttr::StructRet) - Result += "sret "; - if (Attrs & ParamAttr::ByVal) - Result += "byval "; - return Result; +const FunctionType *Function::getFunctionType() const { + return cast(getType()->getElementType()); } -void -ParamAttrsList::Profile(FoldingSetNodeID &ID) const { - for (unsigned i = 0; i < attrs.size(); ++i) { - unsigned val = attrs[i].attrs << 16 | attrs[i].index; - ID.AddInteger(val); - } +bool Function::isVarArg() const { + return getFunctionType()->isVarArg(); } -static ManagedStatic > ParamAttrsLists; +const Type *Function::getReturnType() const { + return getFunctionType()->getReturnType(); +} -ParamAttrsList * -ParamAttrsList::get(const ParamAttrsVector &attrVec) { - assert(!attrVec.empty() && "Illegal to create empty ParamAttrsList"); - ParamAttrsList key(attrVec); - FoldingSetNodeID ID; - key.Profile(ID); - void *InsertPos; - ParamAttrsList* PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos); - if (!PAL) { - PAL = new ParamAttrsList(attrVec); - ParamAttrsLists->InsertNode(PAL, InsertPos); - } - return PAL; +void Function::removeFromParent() { + getParent()->getFunctionList().remove(this); } -ParamAttrsList::~ParamAttrsList() { - ParamAttrsLists->RemoveNode(this); +void Function::eraseFromParent() { + getParent()->getFunctionList().erase(this); } //===----------------------------------------------------------------------===// @@ -143,25 +152,27 @@ ParamAttrsList::~ParamAttrsList() { Function::Function(const FunctionType *Ty, LinkageTypes Linkage, const std::string &name, Module *ParentModule) - : GlobalValue(PointerType::get(Ty), Value::FunctionVal, 0, 0, Linkage, name) { - ParamAttrs = 0; + : GlobalValue(PointerType::getUnqual(Ty), + Value::FunctionVal, 0, 0, Linkage, name) { SymTab = new ValueSymbolTable(); - assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy) + assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy + || isa(getReturnType())) && "LLVM functions cannot return aggregate values!"); - // Create the arguments vector, all arguments start out unnamed. - for (unsigned i = 0, e = Ty->getNumParams(); i != e; ++i) { - assert(Ty->getParamType(i) != Type::VoidTy && - "Cannot have void typed arguments!"); - ArgumentList.push_back(new Argument(Ty->getParamType(i))); - } - + // If the function has arguments, mark them as lazily built. + if (Ty->getNumParams()) + SubclassData = 1; // Set the "has lazy arguments" bit. + // Make sure that we get added to a function LeakDetector::addGarbageObject(this); if (ParentModule) ParentModule->getFunctionList().push_back(this); + + // Ensure intrinsics have the right parameter attributes. + if (unsigned IID = getIntrinsicID(true)) + setParamAttrs(Intrinsic::getParamAttrs(Intrinsic::ID(IID))); } Function::~Function() { @@ -171,9 +182,28 @@ Function::~Function() { ArgumentList.clear(); delete SymTab; - // Drop our reference to the parameter attributes, if any. - if (ParamAttrs) - ParamAttrs->dropRef(); + // Remove the function from the on-the-side GC table. + clearGC(); +} + +void Function::BuildLazyArguments() const { + // Create the arguments vector, all arguments start out unnamed. + const FunctionType *FT = getFunctionType(); + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { + assert(FT->getParamType(i) != Type::VoidTy && + "Cannot have void typed arguments!"); + ArgumentList.push_back(new Argument(FT->getParamType(i))); + } + + // Clear the lazy arguments bit. + const_cast(this)->SubclassData &= ~1; +} + +size_t Function::arg_size() const { + return getFunctionType()->getNumParams(); +} +bool Function::arg_empty() const { + return getFunctionType()->getNumParams() == 0; } void Function::setParent(Module *parent) { @@ -184,48 +214,82 @@ void Function::setParent(Module *parent) { LeakDetector::removeGarbageObject(this); } -void Function::setParamAttrs(ParamAttrsList *attrs) { - if (ParamAttrs) - ParamAttrs->dropRef(); - - if (attrs) - attrs->addRef(); +// dropAllReferences() - This function causes all the subinstructions to "let +// go" of all references that they are maintaining. This allows one to +// 'delete' a whole class at a time, even though there may be circular +// references... first all references are dropped, and all use counts go to +// zero. Then everything is deleted for real. Note that no operations are +// valid on an object that has "dropped all references", except operator +// delete. +// +void Function::dropAllReferences() { + for (iterator I = begin(), E = end(); I != E; ++I) + I->dropAllReferences(); + BasicBlocks.clear(); // Delete all basic blocks... +} - ParamAttrs = attrs; +void Function::addParamAttr(unsigned i, ParameterAttributes attr) { + PAListPtr PAL = getParamAttrs(); + PAL = PAL.addAttr(i, attr); + setParamAttrs(PAL); } -const FunctionType *Function::getFunctionType() const { - return cast(getType()->getElementType()); +void Function::removeParamAttr(unsigned i, ParameterAttributes attr) { + PAListPtr PAL = getParamAttrs(); + PAL = PAL.removeAttr(i, attr); + setParamAttrs(PAL); } -bool Function::isVarArg() const { - return getFunctionType()->isVarArg(); +// Maintain the GC name for each function in an on-the-side table. This saves +// allocating an additional word in Function for programs which do not use GC +// (i.e., most programs) at the cost of increased overhead for clients which do +// use GC. +static DenseMap *GCNames; +static StringPool *GCNamePool; + +bool Function::hasGC() const { + return GCNames && GCNames->count(this); } -const Type *Function::getReturnType() const { - return getFunctionType()->getReturnType(); +const char *Function::getGC() const { + assert(hasGC() && "Function has no collector"); + return *(*GCNames)[this]; } -void Function::removeFromParent() { - getParent()->getFunctionList().remove(this); +void Function::setGC(const char *Str) { + if (!GCNamePool) + GCNamePool = new StringPool(); + if (!GCNames) + GCNames = new DenseMap(); + (*GCNames)[this] = GCNamePool->intern(Str); } -void Function::eraseFromParent() { - getParent()->getFunctionList().erase(this); +void Function::clearGC() { + if (GCNames) { + GCNames->erase(this); + if (GCNames->empty()) { + delete GCNames; + GCNames = 0; + if (GCNamePool->empty()) { + delete GCNamePool; + GCNamePool = 0; + } + } + } } -// dropAllReferences() - This function causes all the subinstructions to "let -// go" of all references that they are maintaining. This allows one to -// 'delete' a whole class at a time, even though there may be circular -// references... first all references are dropped, and all use counts go to -// zero. Then everything is deleted for real. Note that no operations are -// valid on an object that has "dropped all references", except operator -// delete. -// -void Function::dropAllReferences() { - for (iterator I = begin(), E = end(); I != E; ++I) - I->dropAllReferences(); - BasicBlocks.clear(); // Delete all basic blocks... +/// copyAttributesFrom - copy all additional attributes (those not needed to +/// create a Function) from the Function Src to this one. +void Function::copyAttributesFrom(const GlobalValue *Src) { + assert(isa(Src) && "Expected a Function!"); + GlobalValue::copyAttributesFrom(Src); + const Function *SrcF = cast(Src); + setCallingConv(SrcF->getCallingConv()); + setParamAttrs(SrcF->getParamAttrs()); + if (SrcF->hasGC()) + setGC(SrcF->getGC()); + else + clearGC(); } /// getIntrinsicID - This method returns the ID number of the specified @@ -266,9 +330,14 @@ std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) { if (numTys == 0) return Table[id]; std::string Result(Table[id]); - for (unsigned i = 0; i < numTys; ++i) - if (Tys[i]) - Result += "." + Tys[i]->getDescription(); + for (unsigned i = 0; i < numTys; ++i) { + if (const PointerType* PTyp = dyn_cast(Tys[i])) { + Result += ".p" + llvm::utostr(PTyp->getAddressSpace()) + + MVT::getMVT(PTyp->getElementType()).getMVTString(); + } + else if (Tys[i]) + Result += "." + MVT::getMVT(Tys[i]).getMVTString(); + } return Result; } @@ -285,36 +354,27 @@ const FunctionType *Intrinsic::getType(ID id, const Type **Tys, return FunctionType::get(ResultTy, ArgTys, IsVarArg); } +PAListPtr Intrinsic::getParamAttrs(ID id) { + ParameterAttributes Attr = ParamAttr::None; + +#define GET_INTRINSIC_ATTRIBUTES +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_ATTRIBUTES + + // Intrinsics cannot throw exceptions. + Attr |= ParamAttr::NoUnwind; + + ParamAttrsWithIndex PAWI = ParamAttrsWithIndex::get(0, Attr); + return PAListPtr::get(&PAWI, 1); +} + Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys, unsigned numTys) { -// There can never be multiple globals with the same name of different types, -// because intrinsics must be a specific type. - return cast(M->getOrInsertFunction(getName(id, Tys, numTys), - getType(id, Tys, numTys))); -} - -Value *IntrinsicInst::StripPointerCasts(Value *Ptr) { - if (ConstantExpr *CE = dyn_cast(Ptr)) { - if (CE->getOpcode() == Instruction::BitCast) { - if (isa(CE->getOperand(0)->getType())) - return StripPointerCasts(CE->getOperand(0)); - } else if (CE->getOpcode() == Instruction::GetElementPtr) { - for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i) - if (!CE->getOperand(i)->isNullValue()) - return Ptr; - return StripPointerCasts(CE->getOperand(0)); - } - return Ptr; - } - - if (BitCastInst *CI = dyn_cast(Ptr)) { - if (isa(CI->getOperand(0)->getType())) - return StripPointerCasts(CI->getOperand(0)); - } else if (GetElementPtrInst *GEP = dyn_cast(Ptr)) { - if (GEP->hasAllZeroIndices()) - return StripPointerCasts(GEP->getOperand(0)); - } - return Ptr; + // There can never be multiple globals with the same name of different types, + // because intrinsics must be a specific type. + return + cast(M->getOrInsertFunction(getName(id, Tys, numTys), + getType(id, Tys, numTys))); } // vim: sw=2 ai