X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FFunction.cpp;h=00d1d7873247736ca734b950449f53b38ebf9f10;hb=6c3541d5597033bdb2f26f5ade811b482c32a39a;hp=04db3aa06c31fadba07a20f1939663fd7d7e488a;hpb=afba8fe662d65b25b4baf46bb26cc18e1f9cc0a5;p=oota-llvm.git diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 04db3aa06c3..00d1d787324 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. // //===----------------------------------------------------------------------===// // @@ -14,46 +14,30 @@ #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/LeakDetector.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/StringPool.h" +#include "llvm/Support/RWMutex.h" +#include "llvm/Support/Threading.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(); - // This should not be garbage monitored. - LeakDetector::removeGarbageObject(Ret); - return Ret; -} - -iplist &ilist_traits::getList(Function *F) { - return F->getBasicBlockList(); -} - -Argument *ilist_traits::createSentinel() { - Argument *Ret = new Argument(Type::Int32Ty); - // This should not be garbage monitored. - LeakDetector::removeGarbageObject(Ret); - return Ret; -} - -iplist &ilist_traits::getList(Function *F) { - return F->getArgumentList(); -} // Explicit instantiations of SymbolTableListTraits since some of the methods // are not in the public header file... -template class SymbolTableListTraits; -template class SymbolTableListTraits; +template class llvm::SymbolTableListTraits; +template class llvm::SymbolTableListTraits; //===----------------------------------------------------------------------===// // Argument Implementation //===----------------------------------------------------------------------===// -Argument::Argument(const Type *Ty, const std::string &Name, Function *Par) +Argument::Argument(const Type *Ty, const Twine &Name, Function *Par) : Value(Ty, Value::ArgumentVal) { Parent = 0; @@ -73,194 +57,94 @@ void Argument::setParent(Function *parent) { LeakDetector::removeGarbageObject(this); } -//===----------------------------------------------------------------------===// -// ParamAttrsList Implementation -//===----------------------------------------------------------------------===// +/// 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; -uint16_t -ParamAttrsList::getParamAttrs(uint16_t Index) const { - unsigned limit = attrs.size(); - for (unsigned i = 0; i < limit && attrs[i].index <= Index; ++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 "; - if (Attrs & ParamAttr::Nest) - Result += "nest "; - if (Attrs & ParamAttr::ReadNone) - Result += "readnone "; - if (Attrs & ParamAttr::ReadOnly) - Result += "readonly "; - return Result; + return ArgIdx; } -/// onlyInformative - Returns whether only informative attributes are set. -static inline bool onlyInformative(uint16_t attrs) { - return !(attrs & ~ParamAttr::Informative); -} - -bool -ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){ - if (A == B) - return true; - unsigned ASize = A ? A->size() : 0; - unsigned BSize = B ? B->size() : 0; - unsigned AIndex = 0; - unsigned BIndex = 0; - - while (AIndex < ASize && BIndex < BSize) { - uint16_t AIdx = A->getParamIndex(AIndex); - uint16_t BIdx = B->getParamIndex(BIndex); - uint16_t AAttrs = A->getParamAttrsAtIndex(AIndex); - uint16_t BAttrs = B->getParamAttrsAtIndex(AIndex); - - if (AIdx < BIdx) { - if (!onlyInformative(AAttrs)) - return false; - ++AIndex; - } else if (BIdx < AIdx) { - if (!onlyInformative(BAttrs)) - return false; - ++BIndex; - } else { - if (!onlyInformative(AAttrs ^ BAttrs)) - return false; - ++AIndex; - ++BIndex; - } - } - for (; AIndex < ASize; ++AIndex) - if (!onlyInformative(A->getParamAttrsAtIndex(AIndex))) - return false; - for (; BIndex < BSize; ++BIndex) - if (!onlyInformative(B->getParamAttrsAtIndex(AIndex))) - return false; - return true; -} - -void -ParamAttrsList::Profile(FoldingSetNodeID &ID) const { - for (unsigned i = 0; i < attrs.size(); ++i) { - uint32_t val = uint32_t(attrs[i].attrs) << 16 | attrs[i].index; - ID.AddInteger(val); - } +/// hasByValAttr - Return true if this argument has the byval attribute on it +/// in its containing function. +bool Argument::hasByValAttr() const { + if (!getType()->isPointerTy()) return false; + return getParent()->paramHasAttr(getArgNo()+1, Attribute::ByVal); } -static ManagedStatic > ParamAttrsLists; +/// hasNestAttr - Return true if this argument has the nest attribute on +/// it in its containing function. +bool Argument::hasNestAttr() const { + if (!getType()->isPointerTy()) return false; + return getParent()->paramHasAttr(getArgNo()+1, Attribute::Nest); +} -const ParamAttrsList * -ParamAttrsList::get(const ParamAttrsVector &attrVec) { - // If there are no attributes then return a null ParamAttrsList pointer. - if (attrVec.empty()) - return 0; +/// hasNoAliasAttr - Return true if this argument has the noalias attribute on +/// it in its containing function. +bool Argument::hasNoAliasAttr() const { + if (!getType()->isPointerTy()) return false; + return getParent()->paramHasAttr(getArgNo()+1, Attribute::NoAlias); +} -#ifndef NDEBUG - for (unsigned i = 0, e = attrVec.size(); i < e; ++i) { - assert(attrVec[i].attrs != ParamAttr::None - && "Pointless parameter attribute!"); - assert((!i || attrVec[i-1].index < attrVec[i].index) - && "Misordered ParamAttrsList!"); - } -#endif - - // Otherwise, build a key to look up the existing attributes. - ParamAttrsList key(attrVec); - FoldingSetNodeID ID; - key.Profile(ID); - void *InsertPos; - ParamAttrsList* PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos); - - // If we didn't find any existing attributes of the same shape then - // create a new one and insert it. - if (!PAL) { - PAL = new ParamAttrsList(attrVec); - ParamAttrsLists->InsertNode(PAL, InsertPos); - } +/// hasNoCaptureAttr - Return true if this argument has the nocapture attribute +/// on it in its containing function. +bool Argument::hasNoCaptureAttr() const { + if (!getType()->isPointerTy()) return false; + return getParent()->paramHasAttr(getArgNo()+1, Attribute::NoCapture); +} - // Return the ParamAttrsList that we found or created. - return PAL; -} - -const ParamAttrsList * -ParamAttrsList::getModified(const ParamAttrsList *PAL, - const ParamAttrsVector &modVec) { - if (modVec.empty()) - return PAL; - -#ifndef NDEBUG - for (unsigned i = 0, e = modVec.size(); i < e; ++i) - assert((!i || modVec[i-1].index < modVec[i].index) - && "Misordered ParamAttrsList!"); -#endif - - if (!PAL) { - // Strip any instances of ParamAttr::None from modVec before calling 'get'. - ParamAttrsVector newVec; - for (unsigned i = 0, e = modVec.size(); i < e; ++i) - if (modVec[i].attrs != ParamAttr::None) - newVec.push_back(modVec[i]); - return get(newVec); - } +/// hasSRetAttr - Return true if this argument has the sret attribute on +/// it in its containing function. +bool Argument::hasStructRetAttr() const { + if (!getType()->isPointerTy()) return false; + if (this != getParent()->arg_begin()) + return false; // StructRet param must be first param + return getParent()->paramHasAttr(1, Attribute::StructRet); +} - const ParamAttrsVector &oldVec = PAL->attrs; - - ParamAttrsVector newVec; - unsigned oldI = 0; - unsigned modI = 0; - unsigned oldE = oldVec.size(); - unsigned modE = modVec.size(); - - while (oldI < oldE && modI < modE) { - uint16_t oldIndex = oldVec[oldI].index; - uint16_t modIndex = modVec[modI].index; - - if (oldIndex < modIndex) { - newVec.push_back(oldVec[oldI]); - ++oldI; - } else if (modIndex < oldIndex) { - if (modVec[modI].attrs != ParamAttr::None) - newVec.push_back(modVec[modI]); - ++modI; - } else { - // Same index - overwrite or delete existing attributes. - if (modVec[modI].attrs != ParamAttr::None) - newVec.push_back(modVec[modI]); - ++oldI; - ++modI; - } - } +/// addAttr - Add a Attribute to an argument +void Argument::addAttr(Attributes attr) { + getParent()->addAttribute(getArgNo() + 1, attr); +} + +/// removeAttr - Remove a Attribute from an argument +void Argument::removeAttr(Attributes attr) { + getParent()->removeAttribute(getArgNo() + 1, attr); +} + + +//===----------------------------------------------------------------------===// +// Helper Methods in Function +//===----------------------------------------------------------------------===// + +LLVMContext &Function::getContext() const { + return getType()->getContext(); +} + +const FunctionType *Function::getFunctionType() const { + return cast(getType()->getElementType()); +} + +bool Function::isVarArg() const { + return getFunctionType()->isVarArg(); +} - for (; oldI < oldE; ++oldI) - newVec.push_back(oldVec[oldI]); - for (; modI < modE; ++modI) - if (modVec[modI].attrs != ParamAttr::None) - newVec.push_back(modVec[modI]); +const Type *Function::getReturnType() const { + return getFunctionType()->getReturnType(); +} - return get(newVec); +void Function::removeFromParent() { + getParent()->getFunctionList().remove(this); } -ParamAttrsList::~ParamAttrsList() { - ParamAttrsLists->RemoveNode(this); +void Function::eraseFromParent() { + getParent()->getFunctionList().erase(this); } //===----------------------------------------------------------------------===// @@ -268,23 +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) { + const Twine &name, Module *ParentModule) + : GlobalValue(PointerType::getUnqual(Ty), + Value::FunctionVal, 0, 0, Linkage, name) { + assert(FunctionType::isValidReturnType(getReturnType()) && + !getReturnType()->isOpaqueTy() && "invalid return type"); SymTab = new ValueSymbolTable(); - assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy) - && "LLVM functions cannot return aggregate values!"); - // If the function has arguments, mark them as lazily built. if (Ty->getNumParams()) - SubclassData = 1; // Set the "has lazy arguments" bit. + setValueSubclassData(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()) + setAttributes(Intrinsic::getAttributes(Intrinsic::ID(IID))); + } Function::~Function() { @@ -294,22 +182,22 @@ 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 && + assert(!FT->getParamType(i)->isVoidTy() && "Cannot have void typed arguments!"); ArgumentList.push_back(new Argument(FT->getParamType(i))); } // Clear the lazy arguments bit. - const_cast(this)->SubclassData &= ~1; + unsigned SDC = getSubclassDataFromValue(); + const_cast(this)->setValueSubclassData(SDC &= ~1); } size_t Function::arg_size() const { @@ -327,44 +215,6 @@ void Function::setParent(Module *parent) { LeakDetector::removeGarbageObject(this); } -void Function::setParamAttrs(const ParamAttrsList *attrs) { - // Avoid deleting the ParamAttrsList if they are setting the - // attributes to the same list. - if (ParamAttrs == attrs) - return; - - // Drop reference on the old ParamAttrsList - if (ParamAttrs) - ParamAttrs->dropRef(); - - // Add reference to the new ParamAttrsList - if (attrs) - attrs->addRef(); - - // Set the new ParamAttrsList. - ParamAttrs = attrs; -} - -const FunctionType *Function::getFunctionType() const { - return cast(getType()->getElementType()); -} - -bool Function::isVarArg() const { - return getFunctionType()->isVarArg(); -} - -const Type *Function::getReturnType() const { - return getFunctionType()->getReturnType(); -} - -void Function::removeFromParent() { - getParent()->getFunctionList().remove(this); -} - -void Function::eraseFromParent() { - getParent()->getFunctionList().erase(this); -} - // 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 @@ -376,7 +226,80 @@ void Function::eraseFromParent() { void Function::dropAllReferences() { for (iterator I = begin(), E = end(); I != E; ++I) I->dropAllReferences(); - BasicBlocks.clear(); // Delete all basic blocks... + + // Delete all basic blocks. They are now unused, except possibly by + // blockaddresses, but BasicBlock's destructor takes care of those. + while (!BasicBlocks.empty()) + BasicBlocks.begin()->eraseFromParent(); +} + +void Function::addAttribute(unsigned i, Attributes attr) { + AttrListPtr PAL = getAttributes(); + PAL = PAL.addAttr(i, attr); + setAttributes(PAL); +} + +void Function::removeAttribute(unsigned i, Attributes attr) { + AttrListPtr PAL = getAttributes(); + PAL = PAL.removeAttr(i, attr); + setAttributes(PAL); +} + +// 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; +static ManagedStatic > GCLock; + +bool Function::hasGC() const { + sys::SmartScopedReader Reader(*GCLock); + return GCNames && GCNames->count(this); +} + +const char *Function::getGC() const { + assert(hasGC() && "Function has no collector"); + sys::SmartScopedReader Reader(*GCLock); + return *(*GCNames)[this]; +} + +void Function::setGC(const char *Str) { + sys::SmartScopedWriter Writer(*GCLock); + if (!GCNamePool) + GCNamePool = new StringPool(); + if (!GCNames) + GCNames = new DenseMap(); + (*GCNames)[this] = GCNamePool->intern(Str); +} + +void Function::clearGC() { + sys::SmartScopedWriter Writer(*GCLock); + if (GCNames) { + GCNames->erase(this); + if (GCNames->empty()) { + delete GCNames; + GCNames = 0; + if (GCNamePool->empty()) { + delete GCNamePool; + GCNamePool = 0; + } + } + } +} + +/// 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()); + setAttributes(SrcF->getAttributes()); + if (SrcF->hasGC()) + setGC(SrcF->getGC()); + else + clearGC(); } /// getIntrinsicID - This method returns the ID number of the specified @@ -386,7 +309,7 @@ void Function::dropAllReferences() { /// particular intrinsic functions which correspond to this value are defined in /// llvm/Intrinsics.h. /// -unsigned Function::getIntrinsicID(bool noAssert) const { +unsigned Function::getIntrinsicID() const { const ValueName *ValName = this->getValueName(); if (!ValName) return 0; @@ -397,12 +320,9 @@ unsigned Function::getIntrinsicID(bool noAssert) const { || Name[2] != 'v' || Name[3] != 'm') return 0; // All intrinsics start with 'llvm.' - assert((Len != 5 || noAssert) && "'llvm.' is an invalid intrinsic name!"); - #define GET_FUNCTION_RECOGNIZER #include "llvm/Intrinsics.gen" #undef GET_FUNCTION_RECOGNIZER - assert(noAssert && "Invalid LLVM intrinsic name"); return 0; } @@ -417,13 +337,19 @@ 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 += "." + MVT::getValueTypeString(MVT::getValueType(Tys[i])); + for (unsigned i = 0; i < numTys; ++i) { + if (const PointerType* PTyp = dyn_cast(Tys[i])) { + Result += ".p" + llvm::utostr(PTyp->getAddressSpace()) + + EVT::getEVT(PTyp->getElementType()).getEVTString(); + } + else if (Tys[i]) + Result += "." + EVT::getEVT(Tys[i]).getEVTString(); + } return Result; } -const FunctionType *Intrinsic::getType(ID id, const Type **Tys, +const FunctionType *Intrinsic::getType(LLVMContext &Context, + ID id, const Type **Tys, unsigned numTys) { const Type *ResultTy = NULL; std::vector ArgTys; @@ -436,60 +362,48 @@ const FunctionType *Intrinsic::getType(ID id, const Type **Tys, return FunctionType::get(ResultTy, ArgTys, IsVarArg); } -const ParamAttrsList *Intrinsic::getParamAttrs(ID id) { - static const ParamAttrsList *IntrinsicAttributes[Intrinsic::num_intrinsics]; - - if (IntrinsicAttributes[id]) - return IntrinsicAttributes[id]; - - ParamAttrsVector Attrs; - uint16_t Attr = ParamAttr::None; +bool Intrinsic::isOverloaded(ID id) { + const bool OTable[] = { + false, +#define GET_INTRINSIC_OVERLOAD_TABLE +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_OVERLOAD_TABLE + }; + return OTable[id]; +} +/// This defines the "Intrinsic::getAttributes(ID id)" method. #define GET_INTRINSIC_ATTRIBUTES #include "llvm/Intrinsics.gen" #undef GET_INTRINSIC_ATTRIBUTES - // Intrinsics cannot throw exceptions. - Attr |= ParamAttr::NoUnwind; - - Attrs.push_back(ParamAttrsWithIndex::get(0, Attr)); - IntrinsicAttributes[id] = ParamAttrsList::get(Attrs); - return IntrinsicAttributes[id]; -} - 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. - Function *F = + return cast(M->getOrInsertFunction(getName(id, Tys, numTys), - getType(id, Tys, numTys))); - F->setParamAttrs(getParamAttrs(id)); - return F; -} - -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; - } + getType(M->getContext(), + id, Tys, numTys))); +} - 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)); +// This defines the "Intrinsic::getIntrinsicForGCCBuiltin()" method. +#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN +#include "llvm/Intrinsics.gen" +#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN + +/// hasAddressTaken - returns true if there are any uses of this function +/// other than direct calls or invokes to it. +bool Function::hasAddressTaken(const User* *PutOffender) const { + for (Value::const_use_iterator I = use_begin(), E = use_end(); I != E; ++I) { + const User *U = *I; + if (!isa(U) && !isa(U)) + return PutOffender ? (*PutOffender = U, true) : true; + ImmutableCallSite CS(cast(U)); + if (!CS.isCallee(I)) + return PutOffender ? (*PutOffender = U, true) : true; } - return Ptr; + return false; } // vim: sw=2 ai