diff options
author | Devang Patel <dpatel@apple.com> | 2008-09-26 22:53:05 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2008-09-26 22:53:05 +0000 |
commit | 19c874638d9478a5d5028854817a5ee72293bb2b (patch) | |
tree | 748636424f3d1005b6c8713365639fb969466c37 | |
parent | d5d8191b202c0f96f33c826c93d9796451ff7fca (diff) | |
download | external_llvm-19c874638d9478a5d5028854817a5ee72293bb2b.zip external_llvm-19c874638d9478a5d5028854817a5ee72293bb2b.tar.gz external_llvm-19c874638d9478a5d5028854817a5ee72293bb2b.tar.bz2 |
Now Attributes are divided in three groups
- return attributes - inreg, zext and sext
- parameter attributes
- function attributes - nounwind, readonly, readnone, noreturn
Return attributes use 0 as the index.
Function attributes use ~0U as the index.
This patch requires corresponding changes in llvm-gcc and clang.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56704 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Attributes.h | 26 | ||||
-rw-r--r-- | include/llvm/Function.h | 24 | ||||
-rw-r--r-- | include/llvm/Instructions.h | 46 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y | 74 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y.cvs | 74 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 49 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.h | 8 | ||||
-rw-r--r-- | lib/Transforms/IPO/AddReadAttrs.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/IPO/ArgumentPromotion.cpp | 18 | ||||
-rw-r--r-- | lib/Transforms/IPO/DeadArgumentElimination.cpp | 23 | ||||
-rw-r--r-- | lib/Transforms/IPO/PruneEH.cpp | 2 | ||||
-rw-r--r-- | lib/Transforms/IPO/StructRetPromotion.cpp | 16 | ||||
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 26 | ||||
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 28 | ||||
-rw-r--r-- | lib/VMCore/Attributes.cpp | 6 | ||||
-rw-r--r-- | lib/VMCore/Function.cpp | 2 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 2 |
17 files changed, 325 insertions, 103 deletions
diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h index 3adbf25..bc76280 100644 --- a/include/llvm/Attributes.h +++ b/include/llvm/Attributes.h @@ -146,10 +146,23 @@ public: //===--------------------------------------------------------------------===// // Attribute List Accessors //===--------------------------------------------------------------------===// - - /// getAttributes - The attributes for the specified index are - /// returned. Attributes for the result are denoted with Idx = 0. - Attributes getAttributes(unsigned Idx) const; + /// getParamAttributes - The attributes for the specified index are + /// returned. + Attributes getParamAttributes(unsigned Idx) const { + assert (Idx && Idx != ~0U && "Invalid parameter index!"); + return getAttributes(Idx); + } + + /// getRetAttributes - The attributes for the ret value are + /// returned. + Attributes getRetAttributes() const { + return getAttributes(0); + } + + /// getFnAttributes - The function attributes are returned. + Attributes getFnAttributes() const { + return getAttributes(~0); + } /// paramHasAttr - Return true if the specified parameter index has the /// specified attribute set. @@ -204,6 +217,11 @@ public: private: explicit AttrListPtr(AttributeListImpl *L); + + /// getAttributes - The attributes for the specified index are + /// returned. Attributes for the result are denoted with Idx = 0. + Attributes getAttributes(unsigned Idx) const; + }; } // End llvm namespace diff --git a/include/llvm/Function.h b/include/llvm/Function.h index 82871bb..19ff2bf 100644 --- a/include/llvm/Function.h +++ b/include/llvm/Function.h @@ -187,38 +187,38 @@ public: /// @brief Determine if the function does not access memory. bool doesNotAccessMemory() const { - return paramHasAttr(0, Attribute::ReadNone); + return paramHasAttr(~0, Attribute::ReadNone); } void setDoesNotAccessMemory(bool DoesNotAccessMemory = true) { - if (DoesNotAccessMemory) addAttribute(0, Attribute::ReadNone); - else removeAttribute(0, Attribute::ReadNone); + if (DoesNotAccessMemory) addAttribute(~0, Attribute::ReadNone); + else removeAttribute(~0, Attribute::ReadNone); } /// @brief Determine if the function does not access or only reads memory. bool onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(0, Attribute::ReadOnly); + return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); } void setOnlyReadsMemory(bool OnlyReadsMemory = true) { - if (OnlyReadsMemory) addAttribute(0, Attribute::ReadOnly); - else removeAttribute(0, Attribute::ReadOnly | Attribute::ReadNone); + if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); + else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); } /// @brief Determine if the function cannot return. bool doesNotReturn() const { - return paramHasAttr(0, Attribute::NoReturn); + return paramHasAttr(~0, Attribute::NoReturn); } void setDoesNotReturn(bool DoesNotReturn = true) { - if (DoesNotReturn) addAttribute(0, Attribute::NoReturn); - else removeAttribute(0, Attribute::NoReturn); + if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); + else removeAttribute(~0, Attribute::NoReturn); } /// @brief Determine if the function cannot unwind. bool doesNotThrow() const { - return paramHasAttr(0, Attribute::NoUnwind); + return paramHasAttr(~0, Attribute::NoUnwind); } void setDoesNotThrow(bool DoesNotThrow = true) { - if (DoesNotThrow) addAttribute(0, Attribute::NoUnwind); - else removeAttribute(0, Attribute::NoUnwind); + if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); + else removeAttribute(~0, Attribute::NoUnwind); } /// @brief Determine if the function returns a structure through first diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index a614573..2278757 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -1097,38 +1097,38 @@ public: /// @brief Determine if the call does not access memory. bool doesNotAccessMemory() const { - return paramHasAttr(0, Attribute::ReadNone); + return paramHasAttr(~0, Attribute::ReadNone); } void setDoesNotAccessMemory(bool NotAccessMemory = true) { - if (NotAccessMemory) addAttribute(0, Attribute::ReadNone); - else removeAttribute(0, Attribute::ReadNone); + if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); + else removeAttribute(~0, Attribute::ReadNone); } /// @brief Determine if the call does not access or only reads memory. bool onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(0, Attribute::ReadOnly); + return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); } void setOnlyReadsMemory(bool OnlyReadsMemory = true) { - if (OnlyReadsMemory) addAttribute(0, Attribute::ReadOnly); - else removeAttribute(0, Attribute::ReadOnly | Attribute::ReadNone); + if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); + else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); } /// @brief Determine if the call cannot return. bool doesNotReturn() const { - return paramHasAttr(0, Attribute::NoReturn); + return paramHasAttr(~0, Attribute::NoReturn); } void setDoesNotReturn(bool DoesNotReturn = true) { - if (DoesNotReturn) addAttribute(0, Attribute::NoReturn); - else removeAttribute(0, Attribute::NoReturn); + if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); + else removeAttribute(~0, Attribute::NoReturn); } /// @brief Determine if the call cannot unwind. bool doesNotThrow() const { - return paramHasAttr(0, Attribute::NoUnwind); + return paramHasAttr(~0, Attribute::NoUnwind); } void setDoesNotThrow(bool DoesNotThrow = true) { - if (DoesNotThrow) addAttribute(0, Attribute::NoUnwind); - else removeAttribute(0, Attribute::NoUnwind); + if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); + else removeAttribute(~0, Attribute::NoUnwind); } /// @brief Determine if the call returns a structure through first @@ -2459,35 +2459,35 @@ public: return paramHasAttr(0, Attribute::ReadNone); } void setDoesNotAccessMemory(bool NotAccessMemory = true) { - if (NotAccessMemory) addAttribute(0, Attribute::ReadNone); - else removeAttribute(0, Attribute::ReadNone); + if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); + else removeAttribute(~0, Attribute::ReadNone); } /// @brief Determine if the call does not access or only reads memory. bool onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(0, Attribute::ReadOnly); + return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); } void setOnlyReadsMemory(bool OnlyReadsMemory = true) { - if (OnlyReadsMemory) addAttribute(0, Attribute::ReadOnly); - else removeAttribute(0, Attribute::ReadOnly | Attribute::ReadNone); + if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); + else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); } /// @brief Determine if the call cannot return. bool doesNotReturn() const { - return paramHasAttr(0, Attribute::NoReturn); + return paramHasAttr(~0, Attribute::NoReturn); } void setDoesNotReturn(bool DoesNotReturn = true) { - if (DoesNotReturn) addAttribute(0, Attribute::NoReturn); - else removeAttribute(0, Attribute::NoReturn); + if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); + else removeAttribute(~0, Attribute::NoReturn); } /// @brief Determine if the call cannot unwind. bool doesNotThrow() const { - return paramHasAttr(0, Attribute::NoUnwind); + return paramHasAttr(~0, Attribute::NoUnwind); } void setDoesNotThrow(bool DoesNotThrow = true) { - if (DoesNotThrow) addAttribute(0, Attribute::NoUnwind); - else removeAttribute(0, Attribute::NoUnwind); + if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); + else removeAttribute(~0, Attribute::NoUnwind); } /// @brief Determine if the call returns a structure through first diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 0ea2ee0..fa62b47 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -2346,8 +2346,25 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')' std::vector<const Type*> ParamTypeList; SmallVector<AttributeWithIndex, 8> Attrs; - if ($7 != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(0, $7)); + //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function + //attributes. + Attributes RetAttrs = 0; + if ($7 != Attribute::None) { + if ($7 & Attribute::ZExt) { + RetAttrs = RetAttrs | Attribute::ZExt; + $7 = $7 ^ Attribute::ZExt; + } + if ($7 & Attribute::SExt) { + RetAttrs = RetAttrs | Attribute::SExt; + $7 = $7 ^ Attribute::SExt; + } + if ($7 & Attribute::InReg) { + RetAttrs = RetAttrs | Attribute::InReg; + $7 = $7 ^ Attribute::InReg; + } + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + } if ($5) { // If there are arguments... unsigned index = 1; for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I, ++index) { @@ -2359,6 +2376,8 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')' Attrs.push_back(AttributeWithIndex::get(index, I->Attrs)); } } + if ($7 != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, $7)); bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy; if (isVarArg) ParamTypeList.pop_back(); @@ -2860,9 +2879,26 @@ BBTerminatorInst : CHECK_FOR_ERROR SmallVector<AttributeWithIndex, 8> Attrs; - if ($8 != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(0, $8)); - + //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function + //attributes. + Attributes RetAttrs = 0; + if ($8 != Attribute::None) { + if ($8 & Attribute::ZExt) { + RetAttrs = RetAttrs | Attribute::ZExt; + $8 = $8 ^ Attribute::ZExt; + } + if ($8 & Attribute::SExt) { + RetAttrs = RetAttrs | Attribute::SExt; + $8 = $8 ^ Attribute::SExt; + } + if ($8 & Attribute::InReg) { + RetAttrs = RetAttrs | Attribute::InReg; + $8 = $8 ^ Attribute::InReg; + } + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + } + // Check the arguments ValueList Args; if ($6->empty()) { // Has no arguments? @@ -2897,7 +2933,8 @@ BBTerminatorInst : } else if (I != E || ArgI != ArgE) GEN_ERROR("Invalid number of parameters detected"); } - + if ($8 != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, $8)); AttrListPtr PAL; if (!Attrs.empty()) PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); @@ -3258,8 +3295,27 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { // Set up the Attributes for the function SmallVector<AttributeWithIndex, 8> Attrs; - if ($8 != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(0, $8)); + //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function + //attributes. + Attributes RetAttrs = 0; + Attributes TmpAttr = $8; + if ($8 != Attribute::None) { + if ($8 & Attribute::ZExt) { + RetAttrs = RetAttrs | Attribute::ZExt; + $8 = $8 ^ Attribute::ZExt; + } + if ($8 & Attribute::SExt) { + RetAttrs = RetAttrs | Attribute::SExt; + $8 = $8 ^ Attribute::SExt; + } + if ($8 & Attribute::InReg) { + RetAttrs = RetAttrs | Attribute::InReg; + $8 = $8 ^ Attribute::InReg; + } + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + } + // Check the arguments ValueList Args; if ($6->empty()) { // Has no arguments? @@ -3293,6 +3349,8 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { } else if (I != E || ArgI != ArgE) GEN_ERROR("Invalid number of parameters detected"); } + if ($8 != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, $8)); // Finish off the Attributes and check them AttrListPtr PAL; diff --git a/lib/AsmParser/llvmAsmParser.y.cvs b/lib/AsmParser/llvmAsmParser.y.cvs index 0ea2ee0..fa62b47 100644 --- a/lib/AsmParser/llvmAsmParser.y.cvs +++ b/lib/AsmParser/llvmAsmParser.y.cvs @@ -2346,8 +2346,25 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')' std::vector<const Type*> ParamTypeList; SmallVector<AttributeWithIndex, 8> Attrs; - if ($7 != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(0, $7)); + //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function + //attributes. + Attributes RetAttrs = 0; + if ($7 != Attribute::None) { + if ($7 & Attribute::ZExt) { + RetAttrs = RetAttrs | Attribute::ZExt; + $7 = $7 ^ Attribute::ZExt; + } + if ($7 & Attribute::SExt) { + RetAttrs = RetAttrs | Attribute::SExt; + $7 = $7 ^ Attribute::SExt; + } + if ($7 & Attribute::InReg) { + RetAttrs = RetAttrs | Attribute::InReg; + $7 = $7 ^ Attribute::InReg; + } + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + } if ($5) { // If there are arguments... unsigned index = 1; for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I, ++index) { @@ -2359,6 +2376,8 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')' Attrs.push_back(AttributeWithIndex::get(index, I->Attrs)); } } + if ($7 != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, $7)); bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy; if (isVarArg) ParamTypeList.pop_back(); @@ -2860,9 +2879,26 @@ BBTerminatorInst : CHECK_FOR_ERROR SmallVector<AttributeWithIndex, 8> Attrs; - if ($8 != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(0, $8)); - + //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function + //attributes. + Attributes RetAttrs = 0; + if ($8 != Attribute::None) { + if ($8 & Attribute::ZExt) { + RetAttrs = RetAttrs | Attribute::ZExt; + $8 = $8 ^ Attribute::ZExt; + } + if ($8 & Attribute::SExt) { + RetAttrs = RetAttrs | Attribute::SExt; + $8 = $8 ^ Attribute::SExt; + } + if ($8 & Attribute::InReg) { + RetAttrs = RetAttrs | Attribute::InReg; + $8 = $8 ^ Attribute::InReg; + } + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + } + // Check the arguments ValueList Args; if ($6->empty()) { // Has no arguments? @@ -2897,7 +2933,8 @@ BBTerminatorInst : } else if (I != E || ArgI != ArgE) GEN_ERROR("Invalid number of parameters detected"); } - + if ($8 != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, $8)); AttrListPtr PAL; if (!Attrs.empty()) PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); @@ -3258,8 +3295,27 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { // Set up the Attributes for the function SmallVector<AttributeWithIndex, 8> Attrs; - if ($8 != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(0, $8)); + //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function + //attributes. + Attributes RetAttrs = 0; + Attributes TmpAttr = $8; + if ($8 != Attribute::None) { + if ($8 & Attribute::ZExt) { + RetAttrs = RetAttrs | Attribute::ZExt; + $8 = $8 ^ Attribute::ZExt; + } + if ($8 & Attribute::SExt) { + RetAttrs = RetAttrs | Attribute::SExt; + $8 = $8 ^ Attribute::SExt; + } + if ($8 & Attribute::InReg) { + RetAttrs = RetAttrs | Attribute::InReg; + $8 = $8 ^ Attribute::InReg; + } + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + } + // Check the arguments ValueList Args; if ($6->empty()) { // Has no arguments? @@ -3293,6 +3349,8 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { } else if (I != E || ArgI != ArgE) GEN_ERROR("Invalid number of parameters detected"); } + if ($8 != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, $8)); // Finish off the Attributes and check them AttrListPtr PAL; diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 205650d..23fbe1d 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -32,7 +32,7 @@ void BitcodeReader::FreeState() { std::vector<PATypeHolder>().swap(TypeList); ValueList.clear(); - std::vector<AttrListPtr>().swap(Attributes); + std::vector<AttrListPtr>().swap(MAttributes); std::vector<BasicBlock*>().swap(FunctionBBs); std::vector<Function*>().swap(FunctionsWithBodies); DeferredFunctionInfo.clear(); @@ -317,7 +317,7 @@ bool BitcodeReader::ParseAttributeBlock() { if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID)) return Error("Malformed block record"); - if (!Attributes.empty()) + if (!MAttributes.empty()) return Error("Multiple PARAMATTR blocks found!"); SmallVector<uint64_t, 64> Record; @@ -355,12 +355,53 @@ bool BitcodeReader::ParseAttributeBlock() { if (Record.size() & 1) return Error("Invalid ENTRY record"); + // FIXME : Remove this backword compatibility one day. + // If Function attributes are using index 0 then transfer them + // to index ~0. Index 0 is strictly used for return value + // attributes. + Attributes RetAttribute = Attribute::None; + Attributes FnAttribute = Attribute::None; for (unsigned i = 0, e = Record.size(); i != e; i += 2) { - if (Record[i+1] != Attribute::None) + if (Record[i] == 0) + RetAttribute = Record[i+1]; + else if (Record[i] == ~0U) + FnAttribute = Record[i+1]; + } + bool useUpdatedAttrs = false; + if (FnAttribute == Attribute::None && RetAttribute != Attribute::None) { + if (RetAttribute & Attribute::NoUnwind) { + FnAttribute = FnAttribute | Attribute::NoUnwind; + RetAttribute = RetAttribute ^ Attribute::NoUnwind; + useUpdatedAttrs = true; + } + if (RetAttribute & Attribute::NoReturn) { + FnAttribute = FnAttribute | Attribute::NoReturn; + RetAttribute = RetAttribute ^ Attribute::NoReturn; + useUpdatedAttrs = true; + } + if (RetAttribute & Attribute::ReadOnly) { + FnAttribute = FnAttribute | Attribute::ReadOnly; + RetAttribute = RetAttribute ^ Attribute::ReadOnly; + useUpdatedAttrs = true; + } + if (RetAttribute & Attribute::ReadNone) { + FnAttribute = FnAttribute | Attribute::ReadNone; + RetAttribute = RetAttribute ^ Attribute::ReadNone; + useUpdatedAttrs = true; + } + } + + for (unsigned i = 0, e = Record.size(); i != e; i += 2) { + if (useUpdatedAttrs && Record[i] == 0 + && RetAttribute != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttribute)); + else if (Record[i+1] != Attribute::None) Attrs.push_back(AttributeWithIndex::get(Record[i], Record[i+1])); } + if (useUpdatedAttrs && FnAttribute != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, FnAttribute)); - Attributes.push_back(AttrListPtr::get(Attrs.begin(), Attrs.end())); + MAttributes.push_back(AttrListPtr::get(Attrs.begin(), Attrs.end())); Attrs.clear(); break; } diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h index e8ad1dd..0b72b34 100644 --- a/lib/Bitcode/Reader/BitcodeReader.h +++ b/lib/Bitcode/Reader/BitcodeReader.h @@ -136,10 +136,10 @@ class BitcodeReader : public ModuleProvider { std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits; std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits; - /// Attributes - The set of parameter attributes by index. Index zero in the + /// MAttributes - The set of attributes by index. Index zero in the /// file is for null, and is thus not represented here. As such all indices /// are off by one. - std::vector<AttrListPtr> Attributes; + std::vector<AttrListPtr> MAttributes; /// FunctionBBs - While parsing a function body, this is a list of the basic /// blocks for the function. @@ -204,8 +204,8 @@ private: return FunctionBBs[ID]; } AttrListPtr getAttributes(unsigned i) const { - if (i-1 < Attributes.size()) - return Attributes[i-1]; + if (i-1 < MAttributes.size()) + return MAttributes[i-1]; return AttrListPtr(); } diff --git a/lib/Transforms/IPO/AddReadAttrs.cpp b/lib/Transforms/IPO/AddReadAttrs.cpp index 4e0677b..897548b 100644 --- a/lib/Transforms/IPO/AddReadAttrs.cpp +++ b/lib/Transforms/IPO/AddReadAttrs.cpp @@ -105,10 +105,10 @@ bool AddReadAttrs::runOnSCC(const std::vector<CallGraphNode *> &SCC) { MadeChange = true; // Clear out any existing attributes. - F->removeAttribute(0, Attribute::ReadOnly | Attribute::ReadNone); + F->removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); // Add in the new attribute. - F->addAttribute(0, ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone); + F->addAttribute(~0, ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone); if (ReadsMemory) NumReadOnly++; diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index fe6583e..d66e2c4 100644 --- a/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -508,7 +508,7 @@ Function *ArgPromotion::DoPromotion(Function *F, const AttrListPtr &PAL = F->getAttributes(); // Add any return attributes. - if (Attributes attrs = PAL.getAttributes(0)) + if (Attributes attrs = PAL.getRetAttributes()) AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); // First, determine the new argument list @@ -525,7 +525,7 @@ Function *ArgPromotion::DoPromotion(Function *F, } else if (!ArgsToPromote.count(I)) { // Unchanged argument Params.push_back(I->getType()); - if (Attributes attrs = PAL.getAttributes(ArgIndex)) + if (Attributes attrs = PAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Params.size(), attrs)); } else if (I->use_empty()) { // Dead argument (which are always marked as promotable) @@ -578,6 +578,10 @@ Function *ArgPromotion::DoPromotion(Function *F, } } + // Add any function attributes. + if (Attributes attrs = PAL.getFnAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); + const Type *RetTy = FTy->getReturnType(); // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which @@ -621,7 +625,7 @@ Function *ArgPromotion::DoPromotion(Function *F, const AttrListPtr &CallPAL = CS.getAttributes(); // Add any return attributes. - if (Attributes attrs = CallPAL.getAttributes(0)) + if (Attributes attrs = CallPAL.getRetAttributes()) AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); // Loop over the operands, inserting GEP and loads in the caller as @@ -633,7 +637,7 @@ Function *ArgPromotion::DoPromotion(Function *F, if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) { Args.push_back(*AI); // Unmodified argument - if (Attributes Attrs = CallPAL.getAttributes(ArgIndex)) + if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } else if (ByValArgsToTransform.count(I)) { @@ -688,10 +692,14 @@ Function *ArgPromotion::DoPromotion(Function *F, // Push any varargs arguments on the list for (; AI != CS.arg_end(); ++AI, ++ArgIndex) { Args.push_back(*AI); - if (Attributes Attrs = CallPAL.getAttributes(ArgIndex)) + if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } + // Add any function attributes. + if (Attributes attrs = CallPAL.getFnAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); + Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index eef326b..8f0c4c4 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -229,6 +229,8 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { SmallVector<AttributeWithIndex, 8> AttributesVec; for (unsigned i = 0; PAL.getSlot(i).Index <= NumArgs; ++i) AttributesVec.push_back(PAL.getSlot(i)); + if (Attributes FnAttrs = PAL.getFnAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); PAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); } @@ -593,8 +595,8 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { const AttrListPtr &PAL = F->getAttributes(); // The existing function return attributes. - Attributes RAttrs = PAL.getAttributes(0); - + Attributes RAttrs = PAL.getRetAttributes(); + Attributes FnAttrs = PAL.getFnAttributes(); // Find out the new return value. @@ -678,7 +680,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { // Get the original parameter attributes (skipping the first one, that is // for the return value. - if (Attributes Attrs = PAL.getAttributes(i + 1)) + if (Attributes Attrs = PAL.getParamAttributes(i + 1)) AttributesVec.push_back(AttributeWithIndex::get(Params.size(), Attrs)); } else { ++NumArgumentsEliminated; @@ -687,6 +689,9 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { } } + if (FnAttrs != Attribute::None) + AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); + // Reconstruct the AttributesList based on the vector we constructed. AttrListPtr NewPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); @@ -730,7 +735,8 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { const AttrListPtr &CallPAL = CS.getAttributes(); // The call return attributes. - Attributes RAttrs = CallPAL.getAttributes(0); + Attributes RAttrs = CallPAL.getRetAttributes(); + Attributes FnAttrs = CallPAL.getFnAttributes(); // Adjust in case the function was changed to return void. RAttrs &= ~Attribute::typeIncompatible(NF->getReturnType()); if (RAttrs) @@ -746,7 +752,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { if (ArgAlive[i]) { Args.push_back(*I); // Get original parameter attributes, but skip return attributes. - if (Attributes Attrs = CallPAL.getAttributes(i + 1)) + if (Attributes Attrs = CallPAL.getParamAttributes(i + 1)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } @@ -756,13 +762,16 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { // Push any varargs arguments on the list. Don't forget their attributes. for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { Args.push_back(*I); - if (Attributes Attrs = CallPAL.getAttributes(i + 1)) + if (Attributes Attrs = CallPAL.getParamAttributes(i + 1)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } + if (FnAttrs != Attribute::None) + AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); + // Reconstruct the AttributesList based on the vector we constructed. AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(), - AttributesVec.end()); + AttributesVec.end()); Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { diff --git a/lib/Transforms/IPO/PruneEH.cpp b/lib/Transforms/IPO/PruneEH.cpp index 821e7d5..6221844 100644 --- a/lib/Transforms/IPO/PruneEH.cpp +++ b/lib/Transforms/IPO/PruneEH.cpp @@ -133,7 +133,7 @@ bool PruneEH::runOnSCC(const std::vector<CallGraphNode *> &SCC) { NewAttributes |= Attribute::NoReturn; const AttrListPtr &PAL = SCC[i]->getFunction()->getAttributes(); - const AttrListPtr &NPAL = PAL.addAttr(0, NewAttributes); + const AttrListPtr &NPAL = PAL.addAttr(~0, NewAttributes); if (PAL != NPAL) { MadeChange = true; SCC[i]->getFunction()->setAttributes(NPAL); diff --git a/lib/Transforms/IPO/StructRetPromotion.cpp b/lib/Transforms/IPO/StructRetPromotion.cpp index 07b9e50..96ef66c 100644 --- a/lib/Transforms/IPO/StructRetPromotion.cpp +++ b/lib/Transforms/IPO/StructRetPromotion.cpp @@ -210,7 +210,7 @@ Function *SRETPromotion::cloneFunctionBody(Function *F, const AttrListPtr &PAL = F->getAttributes(); // Add any return attributes. - if (Attributes attrs = PAL.getAttributes(0)) + if (Attributes attrs = PAL.getRetAttributes()) AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); // Skip first argument. @@ -221,12 +221,17 @@ Function *SRETPromotion::cloneFunctionBody(Function *F, unsigned ParamIndex = 2; while (I != E) { Params.push_back(I->getType()); - if (Attributes Attrs = PAL.getAttributes(ParamIndex)) + if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); ++I; ++ParamIndex; } + // Add any fn attributes. + if (Attributes attrs = PAL.getFnAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); + + FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg()); Function *NF = Function::Create(NFTy, F->getLinkage()); NF->takeName(F); @@ -264,7 +269,7 @@ void SRETPromotion::updateCallSites(Function *F, Function *NF) { const AttrListPtr &PAL = F->getAttributes(); // Add any return attributes. - if (Attributes attrs = PAL.getAttributes(0)) + if (Attributes attrs = PAL.getRetAttributes()) ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs)); // Copy arguments, however skip first one. @@ -276,12 +281,15 @@ void SRETPromotion::updateCallSites(Function *F, Function *NF) { unsigned ParamIndex = 2; while (AI != AE) { Args.push_back(*AI); - if (Attributes Attrs = PAL.getAttributes(ParamIndex)) + if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); ++ParamIndex; ++AI; } + // Add any function attributes. + if (Attributes attrs = PAL.getFnAttributes()) + ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs)); AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end()); diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 1decf2d..9023db7 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -9127,7 +9127,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { return false; // Cannot transform this return value. if (!CallerPAL.isEmpty() && !Caller->use_empty()) { - Attributes RAttrs = CallerPAL.getAttributes(0); + Attributes RAttrs = CallerPAL.getRetAttributes(); if (RAttrs & Attribute::typeIncompatible(NewRetTy)) return false; // Attribute not compatible with transformed value. } @@ -9157,7 +9157,8 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { if (!CastInst::isCastable(ActTy, ParamTy)) return false; // Cannot transform this parameter value. - if (CallerPAL.getAttributes(i + 1) & Attribute::typeIncompatible(ParamTy)) + if (CallerPAL.getParamAttributes(i + 1) + & Attribute::typeIncompatible(ParamTy)) return false; // Attribute not compatible with transformed value. // Converting from one pointer type to another or between a pointer and an @@ -9193,7 +9194,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { attrVec.reserve(NumCommonArgs); // Get any return attributes. - Attributes RAttrs = CallerPAL.getAttributes(0); + Attributes RAttrs = CallerPAL.getRetAttributes(); // If the return value is not being used, the type may not be compatible // with the existing attributes. Wipe out any problematic attributes. @@ -9216,7 +9217,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { } // Add any parameter attributes. - if (Attributes PAttrs = CallerPAL.getAttributes(i + 1)) + if (Attributes PAttrs = CallerPAL.getParamAttributes(i + 1)) attrVec.push_back(AttributeWithIndex::get(i + 1, PAttrs)); } @@ -9246,12 +9247,15 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { } // Add any parameter attributes. - if (Attributes PAttrs = CallerPAL.getAttributes(i + 1)) + if (Attributes PAttrs = CallerPAL.getParamAttributes(i + 1)) attrVec.push_back(AttributeWithIndex::get(i + 1, PAttrs)); } } } + if (Attributes FnAttrs = CallerPAL.getFnAttributes()) + attrVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); + if (NewRetTy == Type::VoidTy) Caller->setName(""); // Void type should not have a name. @@ -9337,7 +9341,7 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) { if (NestAttrs.paramHasAttr(NestIdx, Attribute::Nest)) { // Record the parameter type and any other attributes. NestTy = *I; - NestAttr = NestAttrs.getAttributes(NestIdx); + NestAttr = NestAttrs.getParamAttributes(NestIdx); break; } @@ -9352,8 +9356,8 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) { // Insert the nest argument into the call argument list, which may // mean appending it. Likewise for attributes. - // Add any function result attributes. - if (Attributes Attr = Attrs.getAttributes(0)) + // Add any result attributes. + if (Attributes Attr = Attrs.getRetAttributes()) NewAttrs.push_back(AttributeWithIndex::get(0, Attr)); { @@ -9374,7 +9378,7 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) { // Add the original argument and attributes. NewArgs.push_back(*I); - if (Attributes Attr = Attrs.getAttributes(Idx)) + if (Attributes Attr = Attrs.getParamAttributes(Idx)) NewAttrs.push_back (AttributeWithIndex::get(Idx + (Idx >= NestIdx), Attr)); @@ -9382,6 +9386,10 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) { } while (1); } + // Add any function attributes. + if (Attributes Attr = Attrs.getFnAttributes()) + NewAttrs.push_back(AttributeWithIndex::get(~0, Attr)); + // The trampoline may have been bitcast to a bogus type (FTy). // Handle this by synthesizing a new function type, equal to FTy // with the chain parameter inserted. diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index b1ce257..e186985 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1374,7 +1374,7 @@ void AssemblyWriter::printFunction(const Function *F) { I != E; ++I) { // Insert commas as we go... the first arg doesn't get a comma if (I != F->arg_begin()) Out << ", "; - printArgument(I, Attrs.getAttributes(Idx)); + printArgument(I, Attrs.getParamAttributes(Idx)); Idx++; } } else { @@ -1386,7 +1386,7 @@ void AssemblyWriter::printFunction(const Function *F) { // Output type... printType(FT->getParamType(i)); - Attributes ArgAttrs = Attrs.getAttributes(i+1); + Attributes ArgAttrs = Attrs.getParamAttributes(i+1); if (ArgAttrs != Attribute::None) Out << ' ' << Attribute::getAsString(ArgAttrs); } @@ -1398,9 +1398,12 @@ void AssemblyWriter::printFunction(const Function *F) { Out << "..."; // Output varargs portion of signature! } Out << ')'; - Attributes RetAttrs = Attrs.getAttributes(0); + Attributes RetAttrs = Attrs.getRetAttributes(); if (RetAttrs != Attribute::None) - Out << ' ' << Attribute::getAsString(Attrs.getAttributes(0)); + Out << ' ' << Attribute::getAsString(Attrs.getRetAttributes()); + Attributes FnAttrs = Attrs.getFnAttributes(); + if (FnAttrs != Attribute::None) + Out << ' ' << Attribute::getAsString(Attrs.getFnAttributes()); if (F->hasSection()) Out << " section \"" << F->getSection() << '"'; if (F->getAlignment()) @@ -1660,11 +1663,13 @@ void AssemblyWriter::printInstruction(const Instruction &I) { for (unsigned op = 1, Eop = I.getNumOperands(); op < Eop; ++op) { if (op > 1) Out << ", "; - writeParamOperand(I.getOperand(op), PAL.getAttributes(op)); + writeParamOperand(I.getOperand(op), PAL.getParamAttributes(op)); } Out << ')'; - if (PAL.getAttributes(0) != Attribute::None) - Out << ' ' << Attribute::getAsString(PAL.getAttributes(0)); + if (PAL.getRetAttributes() != Attribute::None) + Out << ' ' << Attribute::getAsString(PAL.getRetAttributes()); + if (PAL.getFnAttributes() != Attribute::None) + Out << ' ' << Attribute::getAsString(PAL.getFnAttributes()); } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) { const PointerType *PTy = cast<PointerType>(Operand->getType()); const FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); @@ -1699,12 +1704,15 @@ void AssemblyWriter::printInstruction(const Instruction &I) { for (unsigned op = 3, Eop = I.getNumOperands(); op < Eop; ++op) { if (op > 3) Out << ", "; - writeParamOperand(I.getOperand(op), PAL.getAttributes(op-2)); + writeParamOperand(I.getOperand(op), PAL.getParamAttributes(op-2)); } Out << ')'; - if (PAL.getAttributes(0) != Attribute::None) - Out << ' ' << Attribute::getAsString(PAL.getAttributes(0)); + if (PAL.getRetAttributes() != Attribute::None) + Out << ' ' << Attribute::getAsString(PAL.getRetAttributes()); + if (PAL.getFnAttributes() != Attribute::None) + Out << ' ' << Attribute::getAsString(PAL.getFnAttributes()); + Out << "\n\t\t\tto "; writeOperand(II->getNormalDest(), true); Out << " unwind "; diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index b2f2150..433b79d 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -47,6 +47,12 @@ std::string Attribute::getAsString(Attributes Attrs) { Result += "readnone "; if (Attrs & Attribute::ReadOnly) Result += "readonly "; + if (Attrs & Attribute::OptimizeForSize) + Result += "optsize "; + if (Attrs & Attribute::NoInline) + Result += "noinline "; + if (Attrs & Attribute::AlwaysInline) + Result += "alwaysinline "; if (Attrs & Attribute::Alignment) { Result += "align "; Result += utostr((Attrs & Attribute::Alignment) >> 16); diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index f16042b..ddc6ace 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -365,7 +365,7 @@ AttrListPtr Intrinsic::getAttributes(ID id) { // Intrinsics cannot throw exceptions. Attr |= Attribute::NoUnwind; - AttributeWithIndex PAWI = AttributeWithIndex::get(0, Attr); + AttributeWithIndex PAWI = AttributeWithIndex::get(~0, Attr); return AttrListPtr::get(&PAWI, 1); } diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 3f950be..42d76ef 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -975,7 +975,7 @@ void Verifier::VerifyCallSite(CallSite CS) { if (FTy->isVarArg()) // Check attributes on the varargs part. for (unsigned Idx = 1 + FTy->getNumParams(); Idx <= CS.arg_size(); ++Idx) { - Attributes Attr = Attrs.getAttributes(Idx); + Attributes Attr = Attrs.getParamAttributes(Idx); VerifyAttrs(Attr, CS.getArgument(Idx-1)->getType(), false, I); |