X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FFunction.cpp;h=7533185be1daf94e028fe0052b71e1e1a98049b2;hb=ebcba612b537f45a033ccd9a60bee0c45e2e2ded;hp=1e68289f652d657b8eeffd8cb9706c2766e42cdf;hpb=d511898b581826694e6c651e23343b1e1ba5ba64;p=oota-llvm.git diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 1e68289f652..7533185be1d 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -2,26 +2,29 @@ // // 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. // //===----------------------------------------------------------------------===// // -// This file implements the Function & GlobalVariable classes for the VMCore -// library. +// This file implements the Function class for the VMCore library. // //===----------------------------------------------------------------------===// #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "llvm/IntrinsicInst.h" +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/LeakDetector.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; @@ -32,7 +35,7 @@ iplist &ilist_traits::getList(Function *F) { } Argument *ilist_traits::createSentinel() { - Argument *Ret = new Argument(Type::IntTy); + Argument *Ret = new Argument(Type::Int32Ty); // This should not be garbage monitored. LeakDetector::removeGarbageObject(Ret); return Ret; @@ -44,15 +47,15 @@ iplist &ilist_traits::getList(Function *F) { // Explicit instantiations of SymbolTableListTraits since some of the methods // are not in the public header file... -template class SymbolTableListTraits; -template class SymbolTableListTraits; +template class SymbolTableListTraits; +template class SymbolTableListTraits; //===----------------------------------------------------------------------===// // Argument Implementation //===----------------------------------------------------------------------===// Argument::Argument(const Type *Ty, const std::string &Name, Function *Par) - : Value(Ty, Value::ArgumentVal, Name) { + : Value(Ty, Value::ArgumentVal) { Parent = 0; // Make sure that we get added to a function @@ -60,6 +63,7 @@ Argument::Argument(const Type *Ty, const std::string &Name, Function *Par) if (Par) Par->getArgumentList().push_back(this); + setName(Name); } void Argument::setParent(Function *parent) { @@ -70,35 +74,108 @@ 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()->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)); +} + + + +//===----------------------------------------------------------------------===// +// Helper Methods in Function +//===----------------------------------------------------------------------===// + +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); +} + //===----------------------------------------------------------------------===// // Function Implementation //===----------------------------------------------------------------------===// Function::Function(const FunctionType *Ty, LinkageTypes Linkage, const std::string &name, Module *ParentModule) - : GlobalValue(PointerType::get(Ty), Value::FunctionVal, 0, 0, Linkage, name) { - CallingConvention = 0; - BasicBlocks.setItemParent(this); - BasicBlocks.setParent(this); - ArgumentList.setItemParent(this); - ArgumentList.setParent(this); - SymTab = new SymbolTable(); - - assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy) - && "LLVM functions cannot return aggregate values!"); + : GlobalValue(PointerType::getUnqual(Ty), + Value::FunctionVal, 0, 0, Linkage, name) { + SymTab = new ValueSymbolTable(); - // 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))); - } + 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. + // 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() { @@ -106,8 +183,30 @@ Function::~Function() { // Delete all of the method arguments and unlink from symbol table... ArgumentList.clear(); - ArgumentList.setParent(0); delete SymTab; + + // Remove the function from the on-the-side collector table. + clearCollector(); +} + +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) { @@ -118,78 +217,83 @@ void Function::setParent(Module *parent) { LeakDetector::removeGarbageObject(this); } -const FunctionType *Function::getFunctionType() const { - return cast(getType()->getElementType()); +// 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... } -bool Function::isVarArg() const { - return getFunctionType()->isVarArg(); +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); } -const Type *Function::getReturnType() const { - return getFunctionType()->getReturnType(); +void Function::addParamAttr(unsigned i, ParameterAttributes attr) { + PAListPtr PAL = getParamAttrs(); + PAL = PAL.addAttr(i, attr); + setParamAttrs(PAL); } -void Function::removeFromParent() { - getParent()->getFunctionList().remove(this); +// 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); } -void Function::eraseFromParent() { - getParent()->getFunctionList().erase(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); +} -/// renameLocalSymbols - This method goes through the Function's symbol table -/// and renames any symbols that conflict with symbols at global scope. This is -/// required before printing out to a textual form, to ensure that there is no -/// ambiguity when parsing. -void Function::renameLocalSymbols() { - SymbolTable &LST = getSymbolTable(); // Local Symtab - SymbolTable &GST = getParent()->getSymbolTable(); // Global Symtab - - for (SymbolTable::plane_iterator LPI = LST.plane_begin(), E = LST.plane_end(); - LPI != E; ++LPI) - // All global symbols are of pointer type, ignore any non-pointer planes. - if (const PointerType *CurTy = dyn_cast(LPI->first)) { - // Only check if the global plane has any symbols of this type. - SymbolTable::plane_iterator GPI = GST.find(LPI->first); - if (GPI != GST.plane_end()) { - SymbolTable::ValueMap &LVM = LPI->second; - const SymbolTable::ValueMap &GVM = GPI->second; - - // Loop over all local symbols, renaming those that are in the global - // symbol table already. - for (SymbolTable::value_iterator VI = LVM.begin(), E = LVM.end(); - VI != E;) { - Value *V = VI->second; - const std::string &Name = VI->first; - ++VI; - if (GVM.count(Name)) { - static unsigned UniqueNum = 0; - // Find a name that does not conflict! - while (GVM.count(Name + "_" + utostr(++UniqueNum)) || - LVM.count(Name + "_" + utostr(UniqueNum))) - /* scan for UniqueNum that works */; - V->setName(Name + "_" + utostr(UniqueNum)); - } - } +void Function::clearCollector() { + if (CollectorNames) { + CollectorNames->erase(this); + if (CollectorNames->empty()) { + delete CollectorNames; + CollectorNames = 0; + if (CollectorNamePool->empty()) { + delete CollectorNamePool; + CollectorNamePool = 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->hasCollector()) + setCollector(SrcF->getCollector()); } /// getIntrinsicID - This method returns the ID number of the specified @@ -199,99 +303,77 @@ void Function::dropAllReferences() { /// particular intrinsic functions which correspond to this value are defined in /// llvm/Intrinsics.h. /// -unsigned Function::getIntrinsicID() const { - if (getName().size() < 5 || getName()[4] != '.' || getName()[0] != 'l' || - getName()[1] != 'l' || getName()[2] != 'v' || getName()[3] != 'm') +unsigned Function::getIntrinsicID(bool noAssert) const { + const ValueName *ValName = this->getValueName(); + if (!ValName) + return 0; + unsigned Len = ValName->getKeyLength(); + const char *Name = ValName->getKeyData(); + + if (Len < 5 || Name[4] != '.' || Name[0] != 'l' || Name[1] != 'l' + || Name[2] != 'v' || Name[3] != 'm') return 0; // All intrinsics start with 'llvm.' - assert(getName().size() != 5 && "'llvm.' is an invalid intrinsic name!"); - - switch (getName()[5]) { - case 'c': - if (getName() == "llvm.ctpop") return Intrinsic::ctpop; - if (getName() == "llvm.cttz") return Intrinsic::cttz; - if (getName() == "llvm.ctlz") return Intrinsic::ctlz; - break; - case 'd': - if (getName() == "llvm.dbg.stoppoint") return Intrinsic::dbg_stoppoint; - if (getName() == "llvm.dbg.region.start")return Intrinsic::dbg_region_start; - if (getName() == "llvm.dbg.region.end") return Intrinsic::dbg_region_end; - if (getName() == "llvm.dbg.func.start") return Intrinsic::dbg_func_start; - if (getName() == "llvm.dbg.declare") return Intrinsic::dbg_declare; - break; - case 'f': - if (getName() == "llvm.frameaddress") return Intrinsic::frameaddress; - break; - case 'g': - if (getName() == "llvm.gcwrite") return Intrinsic::gcwrite; - if (getName() == "llvm.gcread") return Intrinsic::gcread; - if (getName() == "llvm.gcroot") return Intrinsic::gcroot; - break; - case 'i': - if (getName() == "llvm.isunordered") return Intrinsic::isunordered; - break; - case 'l': - if (getName() == "llvm.longjmp") return Intrinsic::longjmp; - break; - case 'm': - if (getName() == "llvm.memcpy") return Intrinsic::memcpy; - if (getName() == "llvm.memmove") return Intrinsic::memmove; - if (getName() == "llvm.memset") return Intrinsic::memset; - break; - case 'p': - if (getName() == "llvm.prefetch") return Intrinsic::prefetch; - if (getName() == "llvm.pcmarker") return Intrinsic::pcmarker; - break; - case 'r': - if (getName() == "llvm.returnaddress") return Intrinsic::returnaddress; - if (getName() == "llvm.readport") return Intrinsic::readport; - if (getName() == "llvm.readio") return Intrinsic::readio; - break; - case 's': - if (getName() == "llvm.setjmp") return Intrinsic::setjmp; - if (getName() == "llvm.sigsetjmp") return Intrinsic::sigsetjmp; - if (getName() == "llvm.siglongjmp") return Intrinsic::siglongjmp; - if (getName() == "llvm.sqrt") return Intrinsic::sqrt; - break; - case 'v': - if (getName() == "llvm.va_copy") return Intrinsic::vacopy; - if (getName() == "llvm.va_end") return Intrinsic::vaend; - if (getName() == "llvm.va_start") return Intrinsic::vastart; - case 'w': - if (getName() == "llvm.writeport") return Intrinsic::writeport; - if (getName() == "llvm.writeio") return Intrinsic::writeio; - break; - } - // The "llvm." namespace is reserved! - assert(0 && "Unknown LLVM intrinsic function!"); + 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; } -Value *IntrinsicInst::StripPointerCasts(Value *Ptr) { - if (ConstantExpr *CE = dyn_cast(Ptr)) { - if (CE->getOpcode() == Instruction::Cast) { - 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; - } +std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) { + assert(id < num_intrinsics && "Invalid intrinsic ID!"); + const char * const Table[] = { + "not_intrinsic", +#define GET_INTRINSIC_NAME_TABLE +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_NAME_TABLE + }; + if (numTys == 0) + return Table[id]; + std::string Result(Table[id]); + for (unsigned i = 0; i < numTys; ++i) + if (Tys[i]) + Result += "." + MVT::getMVT(Tys[i]).getMVTString(); + return Result; +} - if (CastInst *CI = dyn_cast(Ptr)) { - if (isa(CI->getOperand(0)->getType())) - return StripPointerCasts(CI->getOperand(0)); - } else if (GetElementPtrInst *GEP = dyn_cast(Ptr)) { - for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i) - if (!isa(GEP->getOperand(i)) || - !cast(GEP->getOperand(i))->isNullValue()) - return Ptr; - return StripPointerCasts(GEP->getOperand(0)); - } - return Ptr; +const FunctionType *Intrinsic::getType(ID id, const Type **Tys, + unsigned numTys) { + const Type *ResultTy = NULL; + std::vector ArgTys; + bool IsVarArg = false; + +#define GET_INTRINSIC_GENERATOR +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_GENERATOR + + 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))); } // vim: sw=2 ai