X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FFunction.cpp;h=1f59bf9716708d876a586cf07a5eee6806cf023b;hb=3be654f8082dcbdff011a6716a7c90486e28fc9e;hp=a2593350163ac5e286c28698f7c13869299accd3;hpb=07cf79ef537caff6d39145f190a28a336e629b6f;p=oota-llvm.git diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index a2593350163..1f59bf97167 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -14,28 +14,31 @@ #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/System/RWMutex.h" -#include "llvm/System/Threading.h" +#include "llvm/Support/RWMutex.h" +#include "llvm/Support/Threading.h" #include "SymbolTableListTraitsImpl.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; // 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; @@ -72,28 +75,41 @@ 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; + 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; + 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 (!isa(getType())) return false; + 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 (!getType()->isPointerTy()) return false; if (this != getParent()->arg_begin()) return false; // StructRet param must be first param return getParent()->paramHasAttr(1, Attribute::StructRet); @@ -114,13 +130,11 @@ void Argument::removeAttr(Attributes attr) { // Helper Methods in Function //===----------------------------------------------------------------------===// -LLVMContext *Function::getContext() const { - const Module* M = getParent(); - if (M) return &M->getContext(); - return 0; +LLVMContext &Function::getContext() const { + return getType()->getContext(); } -const FunctionType *Function::getFunctionType() const { +FunctionType *Function::getFunctionType() const { return cast(getType()->getElementType()); } @@ -128,7 +142,7 @@ bool Function::isVarArg() const { return getFunctionType()->isVarArg(); } -const Type *Function::getReturnType() const { +Type *Function::getReturnType() const { return getFunctionType()->getReturnType(); } @@ -144,17 +158,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()) && - !isa(getReturnType()) && "invalid return type"); + "invalid return type"); SymTab = new ValueSymbolTable(); // 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); @@ -181,15 +195,16 @@ Function::~Function() { 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 { @@ -218,7 +233,11 @@ 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... + + // 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) { @@ -242,18 +261,18 @@ static StringPool *GCNamePool; static ManagedStatic > GCLock; bool Function::hasGC() const { - sys::SmartScopedReader Reader(&*GCLock); + sys::SmartScopedReader Reader(*GCLock); return GCNames && GCNames->count(this); } const char *Function::getGC() const { assert(hasGC() && "Function has no collector"); - sys::SmartScopedReader Reader(&*GCLock); + sys::SmartScopedReader Reader(*GCLock); return *(*GCNames)[this]; } void Function::setGC(const char *Str) { - sys::SmartScopedWriter Writer(&*GCLock); + sys::SmartScopedWriter Writer(*GCLock); if (!GCNamePool) GCNamePool = new StringPool(); if (!GCNames) @@ -262,7 +281,7 @@ void Function::setGC(const char *Str) { } void Function::clearGC() { - sys::SmartScopedWriter Writer(&*GCLock); + sys::SmartScopedWriter Writer(*GCLock); if (GCNames) { GCNames->erase(this); if (GCNames->empty()) { @@ -314,32 +333,32 @@ unsigned Function::getIntrinsicID() const { 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 (const PointerType* PTyp = dyn_cast(Tys[i])) { + for (unsigned i = 0; i < Tys.size(); ++i) { + if (PointerType* PTyp = dyn_cast(Tys[i])) { Result += ".p" + llvm::utostr(PTyp->getAddressSpace()) + - MVT::getMVT(PTyp->getElementType()).getMVTString(); + EVT::getEVT(PTyp->getElementType()).getEVTString(); } else if (Tys[i]) - Result += "." + MVT::getMVT(Tys[i]).getMVTString(); + 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; + std::vector ArgTys; bool IsVarArg = false; #define GET_INTRINSIC_GENERATOR @@ -350,7 +369,7 @@ const FunctionType *Intrinsic::getType(ID id, const Type **Tys, } bool Intrinsic::isOverloaded(ID id) { - const bool OTable[] = { + static const bool OTable[] = { false, #define GET_INTRINSIC_OVERLOAD_TABLE #include "llvm/Intrinsics.gen" @@ -364,13 +383,12 @@ bool Intrinsic::isOverloaded(ID id) { #include "llvm/Intrinsics.gen" #undef GET_INTRINSIC_ATTRIBUTES -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. @@ -378,15 +396,50 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys, #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 { - for (Value::use_const_iterator I = use_begin(), E = use_end(); I != E; ++I) { - if (I.getOperandNo() != 0 || - (!isa(*I) && !isa(*I))) - return true; +/// 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 false; } +/// callsFunctionThatReturnsTwice - Return true if the function has a call to +/// setjmp or other function that gcc recognizes as "returning twice". +/// +/// FIXME: Remove after is fixed. +/// FIXME: Is the above FIXME valid? +bool Function::callsFunctionThatReturnsTwice() const { + const Module *M = this->getParent(); + static const char *ReturnsTwiceFns[] = { + "_setjmp", + "setjmp", + "sigsetjmp", + "setjmp_syscall", + "savectx", + "qsetjmp", + "vfork", + "getcontext" + }; + + for (unsigned I = 0; I < array_lengthof(ReturnsTwiceFns); ++I) + if (const Function *Callee = M->getFunction(ReturnsTwiceFns[I])) { + if (!Callee->use_empty()) + for (Value::const_use_iterator + I = Callee->use_begin(), E = Callee->use_end(); + I != E; ++I) + if (const CallInst *CI = dyn_cast(*I)) + if (CI->getParent()->getParent() == this) + return true; + } + + return false; +} + // vim: sw=2 ai