X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FFunction.cpp;h=bb8f62ac295346ab440f2679201a4b561c219cae;hb=c3e48c38bf87ad081904eccf16e4ddd99c36d070;hp=546cadb0f3b1abcac744acb8ca3872f8ef11d4ae;hpb=b04adddd50dfa4c3fbdad3b15d601402254c1ff5;p=oota-llvm.git diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 546cadb0f3b..bb8f62ac295 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -14,47 +14,32 @@ #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/InstIterator.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/STLExtras.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; -BasicBlock *ilist_traits::createSentinel() { - BasicBlock *Ret = BasicBlock::Create(); - // 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(Type *Ty, const Twine &Name, Function *Par) : Value(Ty, Value::ArgumentVal) { Parent = 0; @@ -91,44 +76,66 @@ unsigned Argument::getArgNo() const { /// 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); + if (!getType()->isPointerTy()) return false; + return getParent()->paramHasAttr(getArgNo()+1, Attribute::ByVal); +} + +unsigned Argument::getParamAlignment() const { + assert(getType()->isPointerTy() && "Only pointers have alignments"); + return getParent()->getParamAlignment(getArgNo()+1); + +} + +/// 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); } /// 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); + if (!getType()->isPointerTy()) return false; + return getParent()->paramHasAttr(getArgNo()+1, Attribute::NoAlias); +} + +/// 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); } /// 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); + if (!getType()->isPointerTy()) return false; + if (this != getParent()->arg_begin()) + return false; // StructRet param must be first param + return getParent()->paramHasAttr(1, Attribute::StructRet); } -/// addAttr - Add a ParamAttr to an argument -void Argument::addAttr(ParameterAttributes attr) { - getParent()->setParamAttrs( - getParent()->getParamAttrs().addAttr(getArgNo() + 1, attr)); -} - -/// removeAttr - Remove a ParamAttr from an argument -void Argument::removeAttr(ParameterAttributes attr) { - getParent()->setParamAttrs( - getParent()->getParamAttrs().removeAttr(getArgNo() + 1, attr)); +/// 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 //===----------------------------------------------------------------------===// -const FunctionType *Function::getFunctionType() const { +LLVMContext &Function::getContext() const { + return getType()->getContext(); +} + +FunctionType *Function::getFunctionType() const { return cast(getType()->getElementType()); } @@ -136,7 +143,7 @@ bool Function::isVarArg() const { return getFunctionType()->isVarArg(); } -const Type *Function::getReturnType() const { +Type *Function::getReturnType() const { return getFunctionType()->getReturnType(); } @@ -152,19 +159,17 @@ void Function::eraseFromParent() { // Function Implementation //===----------------------------------------------------------------------===// -Function::Function(const FunctionType *Ty, LinkageTypes Linkage, - const std::string &name, Module *ParentModule) +Function::Function(FunctionType *Ty, LinkageTypes Linkage, + const Twine &name, Module *ParentModule) : GlobalValue(PointerType::getUnqual(Ty), Value::FunctionVal, 0, 0, Linkage, name) { + assert(FunctionType::isValidReturnType(getReturnType()) && + "invalid return type"); SymTab = new ValueSymbolTable(); - assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy - || isa(getReturnType())) - && "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); @@ -173,8 +178,9 @@ Function::Function(const FunctionType *Ty, LinkageTypes Linkage, ParentModule->getFunctionList().push_back(this); // Ensure intrinsics have the right parameter attributes. - if (unsigned IID = getIntrinsicID(true)) - setParamAttrs(Intrinsic::getParamAttrs(Intrinsic::ID(IID))); + if (unsigned IID = getIntrinsicID()) + setAttributes(Intrinsic::getAttributes(Intrinsic::ID(IID))); + } Function::~Function() { @@ -184,21 +190,22 @@ Function::~Function() { ArgumentList.clear(); delete SymTab; - // Remove the function from the on-the-side collector table. - clearCollector(); + // 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(); + 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 { @@ -227,56 +234,82 @@ void Function::setParent(Module *parent) { void Function::dropAllReferences() { for (iterator I = begin(), E = end(); I != E; ++I) I->dropAllReferences(); - BasicBlocks.clear(); // Delete all basic blocks... -} - -void Function::setDoesNotThrow(bool doesNotThrow) { - PAListPtr PAL = getParamAttrs(); - if (doesNotThrow) - PAL = PAL.addAttr(0, ParamAttr::NoUnwind); - else - PAL = PAL.removeAttr(0, ParamAttr::NoUnwind); - setParamAttrs(PAL); -} - -// Maintain the collector 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 *CollectorNames; -static StringPool *CollectorNamePool; - -bool Function::hasCollector() const { - return CollectorNames && CollectorNames->count(this); -} - -const char *Function::getCollector() const { - assert(hasCollector() && "Function has no collector"); - return *(*CollectorNames)[this]; -} - -void Function::setCollector(const char *Str) { - if (!CollectorNamePool) - CollectorNamePool = new StringPool(); - if (!CollectorNames) - CollectorNames = new DenseMap(); - (*CollectorNames)[this] = CollectorNamePool->intern(Str); -} - -void Function::clearCollector() { - if (CollectorNames) { - CollectorNames->erase(this); - if (CollectorNames->empty()) { - delete CollectorNames; - CollectorNames = 0; - if (CollectorNamePool->empty()) { - delete CollectorNamePool; - CollectorNamePool = 0; + + // 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 /// function, or Intrinsic::not_intrinsic if the function is not an /// intrinsic, or if the pointer is null. This value is always defined to be @@ -284,7 +317,7 @@ void Function::clearCollector() { /// 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; @@ -295,36 +328,38 @@ 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; } -std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) { +std::string Intrinsic::getName(ID id, ArrayRef Tys) { assert(id < num_intrinsics && "Invalid intrinsic ID!"); - const char * const Table[] = { + static const char * const Table[] = { "not_intrinsic", #define GET_INTRINSIC_NAME_TABLE #include "llvm/Intrinsics.gen" #undef GET_INTRINSIC_NAME_TABLE }; - if (numTys == 0) + if (Tys.empty()) 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 < Tys.size(); ++i) { + if (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, - unsigned numTys) { - const Type *ResultTy = NULL; - std::vector ArgTys; +FunctionType *Intrinsic::getType(LLVMContext &Context, + ID id, ArrayRef Tys) { + Type *ResultTy = NULL; + SmallVector ArgTys; bool IsVarArg = false; #define GET_INTRINSIC_GENERATOR @@ -334,27 +369,76 @@ const FunctionType *Intrinsic::getType(ID id, const Type **Tys, return FunctionType::get(ResultTy, ArgTys, IsVarArg); } -PAListPtr Intrinsic::getParamAttrs(ID id) { - ParameterAttributes Attr = ParamAttr::None; +bool Intrinsic::isOverloaded(ID id) { + static 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; - - ParamAttrsWithIndex PAWI = ParamAttrsWithIndex::get(0, Attr); - return PAListPtr::get(&PAWI, 1); -} - -Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys, - unsigned numTys) { +Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef Tys) { // 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))); + cast(M->getOrInsertFunction(getName(id, Tys), + getType(M->getContext(), id, Tys))); +} + +// 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; + // FIXME: Check for blockaddress, which does not take the address. + 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 false; +} + +bool Function::isDefTriviallyDead() const { + // Check the linkage + if (!hasLinkOnceLinkage() && !hasLocalLinkage() && + !hasAvailableExternallyLinkage()) + return false; + + // Check if the function is used by anything other than a blockaddress. + for (Value::const_use_iterator I = use_begin(), E = use_end(); I != E; ++I) + if (!isa(*I)) + return false; + + return true; +} + +/// callsFunctionThatReturnsTwice - Return true if the function has a call to +/// setjmp or other function that gcc recognizes as "returning twice". +bool Function::callsFunctionThatReturnsTwice() const { + for (const_inst_iterator + I = inst_begin(this), E = inst_end(this); I != E; ++I) { + const CallInst* callInst = dyn_cast(&*I); + if (!callInst) + continue; + if (callInst->canReturnTwice()) + return true; + } + + return false; } // vim: sw=2 ai