X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FFunction.cpp;h=3582b321504f1e19ef94639817116d3195d6c5b7;hb=2cda9399deed8a50e95848716212b500c5b2d396;hp=438fce38ec62d7736c596e8ca5e35ce436248f51;hpb=59bcce5ae52afff2ba4840bfa630b20e8ff4ddb2;p=oota-llvm.git diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 438fce38ec6..3582b321504 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -7,15 +7,17 @@ // //===----------------------------------------------------------------------===// // -// 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/ParameterAttributes.h" #include "llvm/IntrinsicInst.h" +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/LeakDetector.h" +#include "llvm/Support/ManagedStatic.h" #include "SymbolTableListTraitsImpl.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; @@ -32,7 +34,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 +46,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 +62,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,6 +73,77 @@ void Argument::setParent(Function *parent) { LeakDetector::removeGarbageObject(this); } +//===----------------------------------------------------------------------===// +// ParamAttrsList Implementation +//===----------------------------------------------------------------------===// + +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 "; + if (Attrs & ParamAttr::Nest) + Result += "nest "; + return Result; +} + +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); + } +} + +static ManagedStatic > ParamAttrsLists; + +ParamAttrsList * +ParamAttrsList::get(const ParamAttrsVector &attrVec) { + assert(!attrVec.empty() && "Illegal to create empty ParamAttrsList"); +#ifndef NDEBUG + for (unsigned i = 1, e = attrVec.size(); i < e; ++i) + assert(attrVec[i-1].index < attrVec[i].index && "Misordered ParamAttrsList!"); +#endif + 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; +} + +ParamAttrsList::~ParamAttrsList() { + ParamAttrsLists->RemoveNode(this); +} + //===----------------------------------------------------------------------===// // Function Implementation //===----------------------------------------------------------------------===// @@ -77,23 +151,16 @@ void Argument::setParent(Function *parent) { 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(); + ParamAttrs = 0; + SymTab = new ValueSymbolTable(); assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy) && "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); @@ -106,8 +173,31 @@ Function::~Function() { // Delete all of the method arguments and unlink from symbol table... ArgumentList.clear(); - ArgumentList.setParent(0); delete SymTab; + + // Drop our reference to the parameter attributes, if any. + if (ParamAttrs) + ParamAttrs->dropRef(); +} + +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,6 +208,16 @@ void Function::setParent(Module *parent) { LeakDetector::removeGarbageObject(this); } +void Function::setParamAttrs(ParamAttrsList *attrs) { + if (ParamAttrs) + ParamAttrs->dropRef(); + + if (attrs) + attrs->addRef(); + + ParamAttrs = attrs; +} + const FunctionType *Function::getFunctionType() const { return cast(getType()->getElementType()); } @@ -138,46 +238,6 @@ void Function::eraseFromParent() { getParent()->getFunctionList().erase(this); } - -/// 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)); - } - } - } - } -} - - // 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 @@ -199,96 +259,67 @@ void Function::dropAllReferences() { /// particular intrinsic functions which correspond to this value are defined in /// llvm/Intrinsics.h. /// -unsigned Function::getIntrinsicID() const { - const std::string& Name = this->getName(); - if (Name.size() < 5 || Name[4] != '.' || Name[0] != 'l' || Name[1] != 'l' +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(Name.size() != 5 && "'llvm.' is an invalid intrinsic name!"); - - switch (Name[5]) { - case 'b': - if (Name == "llvm.bswap.i16") return Intrinsic::bswap_i16; - if (Name == "llvm.bswap.i32") return Intrinsic::bswap_i32; - if (Name == "llvm.bswap.i64") return Intrinsic::bswap_i64; - break; - case 'c': - if (Name == "llvm.ctpop.i8") return Intrinsic::ctpop_i8; - if (Name == "llvm.ctpop.i16") return Intrinsic::ctpop_i16; - if (Name == "llvm.ctpop.i32") return Intrinsic::ctpop_i32; - if (Name == "llvm.ctpop.i64") return Intrinsic::ctpop_i64; - if (Name == "llvm.cttz.i8") return Intrinsic::cttz_i8; - if (Name == "llvm.cttz.i16") return Intrinsic::cttz_i16; - if (Name == "llvm.cttz.i32") return Intrinsic::cttz_i32; - if (Name == "llvm.cttz.i64") return Intrinsic::cttz_i64; - if (Name == "llvm.ctlz.i8") return Intrinsic::ctlz_i8; - if (Name == "llvm.ctlz.i16") return Intrinsic::ctlz_i16; - if (Name == "llvm.ctlz.i32") return Intrinsic::ctlz_i32; - if (Name == "llvm.ctlz.i64") return Intrinsic::ctlz_i64; - break; - case 'd': - if (Name == "llvm.dbg.stoppoint") return Intrinsic::dbg_stoppoint; - if (Name == "llvm.dbg.region.start")return Intrinsic::dbg_region_start; - if (Name == "llvm.dbg.region.end") return Intrinsic::dbg_region_end; - if (Name == "llvm.dbg.func.start") return Intrinsic::dbg_func_start; - break; - case 'f': - if (Name == "llvm.frameaddress") return Intrinsic::frameaddress; - break; - case 'g': - if (Name == "llvm.gcwrite") return Intrinsic::gcwrite; - if (Name == "llvm.gcread") return Intrinsic::gcread; - if (Name == "llvm.gcroot") return Intrinsic::gcroot; - break; - case 'i': - if (Name == "llvm.isunordered.f32") - return Intrinsic::isunordered_f32; - if (Name == "llvm.isunordered.f64") - return Intrinsic::isunordered_f64; - break; - case 'l': - if (Name == "llvm.longjmp") return Intrinsic::longjmp; - break; - case 'm': - if (Name == "llvm.memcpy.i32") return Intrinsic::memcpy_i32; - if (Name == "llvm.memcpy.i64") return Intrinsic::memcpy_i64; - if (Name == "llvm.memmove.i32") return Intrinsic::memmove_i32; - if (Name == "llvm.memmove.i64") return Intrinsic::memmove_i64; - if (Name == "llvm.memset.i32") return Intrinsic::memset_i32; - if (Name == "llvm.memset.i64") return Intrinsic::memset_i64; - break; - case 'p': - if (Name == "llvm.prefetch") return Intrinsic::prefetch; - if (Name == "llvm.pcmarker") return Intrinsic::pcmarker; - break; - case 'r': - if (Name == "llvm.returnaddress") return Intrinsic::returnaddress; - if (Name == "llvm.readcyclecounter") return Intrinsic::readcyclecounter; - break; - case 's': - if (Name == "llvm.setjmp") return Intrinsic::setjmp; - if (Name == "llvm.sigsetjmp") return Intrinsic::sigsetjmp; - if (Name == "llvm.siglongjmp") return Intrinsic::siglongjmp; - if (Name == "llvm.stackrestore") return Intrinsic::stackrestore; - if (Name == "llvm.stacksave") return Intrinsic::stacksave; - if (Name == "llvm.sqrt.f32") return Intrinsic::sqrt_f32; - if (Name == "llvm.sqrt.f64") return Intrinsic::sqrt_f64; - break; - case 'v': - if (Name == "llvm.va_copy") return Intrinsic::vacopy; - if (Name == "llvm.va_end") return Intrinsic::vaend; - if (Name == "llvm.va_start") return Intrinsic::vastart; - break; - } - // The "llvm." namespace is reserved! - assert(!"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; } +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::getValueTypeString(MVT::getValueType(Tys[i])); + return Result; +} + +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); +} + +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::Cast) { + if (CE->getOpcode() == Instruction::BitCast) { if (isa(CE->getOperand(0)->getType())) return StripPointerCasts(CE->getOperand(0)); } else if (CE->getOpcode() == Instruction::GetElementPtr) { @@ -300,15 +331,12 @@ Value *IntrinsicInst::StripPointerCasts(Value *Ptr) { return Ptr; } - if (CastInst *CI = dyn_cast(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)) { - 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)); + if (GEP->hasAllZeroIndices()) + return StripPointerCasts(GEP->getOperand(0)); } return Ptr; }