X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FFunction.cpp;h=7533185be1daf94e028fe0052b71e1e1a98049b2;hb=ebcba612b537f45a033ccd9a60bee0c45e2e2ded;hp=8e6570a62721b96274946852b214572f5573525e;hpb=50cffa01076a2364dc593ebbfeacf8c5bd4d3f42;p=oota-llvm.git diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 8e6570a6272..7533185be1d 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -14,7 +14,6 @@ #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "llvm/IntrinsicInst.h" -#include "llvm/ParameterAttributes.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/LeakDetector.h" #include "llvm/Support/StringPool.h" @@ -25,7 +24,7 @@ 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; @@ -75,6 +74,57 @@ 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 //===----------------------------------------------------------------------===// @@ -99,36 +149,6 @@ void Function::eraseFromParent() { getParent()->getFunctionList().erase(this); } -/// @brief Determine whether the function has the given attribute. -bool Function::paramHasAttr(uint16_t i, unsigned attr) const { - return ParamAttrs && ParamAttrs->paramHasAttr(i, (ParameterAttributes)attr); -} - -/// @brief Determine if the function cannot return. -bool Function::doesNotReturn() const { - return paramHasAttr(0, ParamAttr::NoReturn); -} - -/// @brief Determine if the function cannot unwind. -bool Function::doesNotThrow() const { - return paramHasAttr(0, ParamAttr::NoUnwind); -} - -/// @brief Determine if the function does not access memory. -bool Function::doesNotAccessMemory() const { - return paramHasAttr(0, ParamAttr::ReadNone); -} - -/// @brief Determine if the function does not access or only reads memory. -bool Function::onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); -} - -/// @brief Determine if the function returns a structure. -bool Function::isStructReturn() const { - return paramHasAttr(1, ParamAttr::StructRet); -} - //===----------------------------------------------------------------------===// // Function Implementation //===----------------------------------------------------------------------===// @@ -136,11 +156,11 @@ bool Function::isStructReturn() const { Function::Function(const FunctionType *Ty, LinkageTypes Linkage, const std::string &name, Module *ParentModule) : GlobalValue(PointerType::getUnqual(Ty), - Value::FunctionVal, 0, 0, Linkage, name), - ParamAttrs(0) { + Value::FunctionVal, 0, 0, Linkage, name) { SymTab = new ValueSymbolTable(); - assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy) + assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy + || isa(getReturnType())) && "LLVM functions cannot return aggregate values!"); // If the function has arguments, mark them as lazily built. @@ -152,6 +172,10 @@ Function::Function(const FunctionType *Ty, LinkageTypes Linkage, 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() { @@ -161,10 +185,6 @@ 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 collector table. clearCollector(); } @@ -197,24 +217,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; -} - // 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 @@ -229,6 +231,21 @@ void Function::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); +} + +void Function::addParamAttr(unsigned i, ParameterAttributes attr) { + PAListPtr PAL = getParamAttrs(); + PAL = PAL.addAttr(i, attr); + 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 @@ -267,6 +284,18 @@ void Function::clearCollector() { } } +/// 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 /// 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 @@ -307,7 +336,7 @@ std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) { std::string Result(Table[id]); for (unsigned i = 0; i < numTys; ++i) if (Tys[i]) - Result += "." + MVT::getValueTypeString(MVT::getValueType(Tys[i])); + Result += "." + MVT::getMVT(Tys[i]).getMVTString(); return Result; } @@ -324,9 +353,8 @@ const FunctionType *Intrinsic::getType(ID id, const Type **Tys, return FunctionType::get(ResultTy, ArgTys, IsVarArg); } -const ParamAttrsList *Intrinsic::getParamAttrs(ID id) { - ParamAttrsVector Attrs; - uint16_t Attr = ParamAttr::None; +PAListPtr Intrinsic::getParamAttrs(ID id) { + ParameterAttributes Attr = ParamAttr::None; #define GET_INTRINSIC_ATTRIBUTES #include "llvm/Intrinsics.gen" @@ -335,43 +363,17 @@ const ParamAttrsList *Intrinsic::getParamAttrs(ID id) { // Intrinsics cannot throw exceptions. Attr |= ParamAttr::NoUnwind; - Attrs.push_back(ParamAttrsWithIndex::get(0, Attr)); - return ParamAttrsList::get(Attrs); + 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. - 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; - } - - 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)); - } - return Ptr; } // vim: sw=2 ai