From 164b86b4399559e45fab7846f1e3e09119cab4e2 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Fri, 20 Jan 2012 17:56:17 +0000 Subject: [PATCH] Extend Attributes to 64 bits Problem: LLVM needs more function attributes than currently available (32 bits). One such proposed attribute is "address_safety", which shows that a function is being checked for address safety (by AddressSanitizer, SAFECode, etc). Solution: - extend the Attributes from 32 bits to 64-bits - wrap the object into a class so that unsigned is never erroneously used instead - change "unsigned" to "Attributes" throughout the code, including one place in clang. - the class has no "operator uint64 ()", but it has "uint64_t Raw() " to support packing/unpacking. - the class has "safe operator bool()" to support the common idiom: if (Attributes attr = getAttrs()) useAttrs(attr); - The CTOR from uint64_t is marked explicit, so I had to add a few explicit CTOR calls - Add the new attribute "address_safety". Doing it in the same commit to check that attributes beyond first 32 bits actually work. - Some of the functions from the Attribute namespace are worth moving inside the class, but I'd prefer to have it as a separate commit. Tested: "make check" on Linux (32-bit and 64-bit) and Mac (10.6) built/run spec CPU 2006 on Linux with clang -O2. This change will break clang build in lib/CodeGen/CGCall.cpp. The following patch will fix it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148553 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LangRef.html | 4 + include/llvm-c/Core.h | 3 +- include/llvm/Attributes.h | 117 ++++++++++++++++-------- lib/AsmParser/LLLexer.cpp | 1 + lib/AsmParser/LLParser.cpp | 20 ++-- lib/AsmParser/LLParser.h | 11 ++- lib/AsmParser/LLToken.h | 1 + lib/Bitcode/Reader/BitcodeReader.cpp | 24 ++--- lib/Bitcode/Writer/BitcodeWriter.cpp | 7 +- lib/CodeGen/Analysis.cpp | 4 +- lib/Transforms/InstCombine/InstCombineCalls.cpp | 3 +- lib/Transforms/Scalar/CodeGenPrepare.cpp | 4 +- lib/VMCore/Attributes.cpp | 8 +- lib/VMCore/Core.cpp | 17 ++-- lib/VMCore/Verifier.cpp | 4 +- utils/llvm.grm | 1 + 16 files changed, 144 insertions(+), 85 deletions(-) diff --git a/docs/LangRef.html b/docs/LangRef.html index 1172b7cb938..e214c5fd555 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -1143,6 +1143,10 @@ define void @f() optsize { ... }
+
address_safety
+
This attribute indicates that the address safety analysis + is enabled for this function.
+
alignstack(<n>)
This attribute indicates that, when emitting the prologue and epilogue, the backend should forcibly align the stack pointer. Specify the diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 63d6fd41e22..de60f77ddbd 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -118,7 +118,8 @@ typedef enum { LLVMStackAlignment = 7<<26, LLVMReturnsTwice = 1 << 29, LLVMUWTable = 1 << 30, - LLVMNonLazyBind = 1 << 31 + LLVMNonLazyBind = 1U << 31, + LLVMAddressSafety = 1ULL << 32, } LLVMAttribute; typedef enum { diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h index 2d7b33b29bc..6082cf05c81 100644 --- a/include/llvm/Attributes.h +++ b/include/llvm/Attributes.h @@ -23,7 +23,47 @@ namespace llvm { class Type; /// Attributes - A bitset of attributes. -typedef unsigned Attributes; +class Attributes { + public: + Attributes() : Bits(0) { } + explicit Attributes(uint64_t Val) : Bits(Val) { } + Attributes(const Attributes &Attrs) : Bits(Attrs.Bits) { } + // This is a "safe bool() operator". + operator const void *() const { return Bits ? this : 0; } + bool isEmptyOrSingleton() const { return (Bits & (Bits - 1)) == 0; } + Attributes &operator = (const Attributes &Attrs) { + Bits = Attrs.Bits; + return *this; + } + bool operator == (const Attributes &Attrs) const { + return Bits == Attrs.Bits; + } + bool operator != (const Attributes &Attrs) const { + return Bits != Attrs.Bits; + } + Attributes operator | (const Attributes &Attrs) const { + return Attributes(Bits | Attrs.Bits); + } + Attributes operator & (const Attributes &Attrs) const { + return Attributes(Bits & Attrs.Bits); + } + Attributes operator ^ (const Attributes &Attrs) const { + return Attributes(Bits ^ Attrs.Bits); + } + Attributes &operator |= (const Attributes &Attrs) { + Bits |= Attrs.Bits; + return *this; + } + Attributes &operator &= (const Attributes &Attrs) { + Bits &= Attrs.Bits; + return *this; + } + Attributes operator ~ () const { return Attributes(~Bits); } + uint64_t Raw() const { return Bits; } + private: + // Currently, we need less than 64 bits. + uint64_t Bits; +}; namespace Attribute { @@ -33,44 +73,45 @@ namespace Attribute { /// results or the function itself. /// @brief Function attributes. -const Attributes None = 0; ///< No attributes have been set -const Attributes ZExt = 1<<0; ///< Zero extended before/after call -const Attributes SExt = 1<<1; ///< Sign extended before/after call -const Attributes NoReturn = 1<<2; ///< Mark the function as not returning -const Attributes InReg = 1<<3; ///< Force argument to be passed in register -const Attributes StructRet = 1<<4; ///< Hidden pointer to structure to return -const Attributes NoUnwind = 1<<5; ///< Function doesn't unwind stack -const Attributes NoAlias = 1<<6; ///< Considered to not alias after call -const Attributes ByVal = 1<<7; ///< Pass structure by value -const Attributes Nest = 1<<8; ///< Nested function static chain -const Attributes ReadNone = 1<<9; ///< Function does not access memory -const Attributes ReadOnly = 1<<10; ///< Function only reads from memory -const Attributes NoInline = 1<<11; ///< inline=never -const Attributes AlwaysInline = 1<<12; ///< inline=always -const Attributes OptimizeForSize = 1<<13; ///< opt_size -const Attributes StackProtect = 1<<14; ///< Stack protection. -const Attributes StackProtectReq = 1<<15; ///< Stack protection required. -const Attributes Alignment = 31<<16; ///< Alignment of parameter (5 bits) +const Attributes None (0); ///< No attributes have been set +const Attributes ZExt (1<<0); ///< Zero extended before/after call +const Attributes SExt (1<<1); ///< Sign extended before/after call +const Attributes NoReturn (1<<2); ///< Mark the function as not returning +const Attributes InReg (1<<3); ///< Force argument to be passed in register +const Attributes StructRet (1<<4); ///< Hidden pointer to structure to return +const Attributes NoUnwind (1<<5); ///< Function doesn't unwind stack +const Attributes NoAlias (1<<6); ///< Considered to not alias after call +const Attributes ByVal (1<<7); ///< Pass structure by value +const Attributes Nest (1<<8); ///< Nested function static chain +const Attributes ReadNone (1<<9); ///< Function does not access memory +const Attributes ReadOnly (1<<10); ///< Function only reads from memory +const Attributes NoInline (1<<11); ///< inline=never +const Attributes AlwaysInline (1<<12); ///< inline=always +const Attributes OptimizeForSize (1<<13); ///< opt_size +const Attributes StackProtect (1<<14); ///< Stack protection. +const Attributes StackProtectReq (1<<15); ///< Stack protection required. +const Attributes Alignment (31<<16); ///< Alignment of parameter (5 bits) // stored as log2 of alignment with +1 bias // 0 means unaligned different from align 1 -const Attributes NoCapture = 1<<21; ///< Function creates no aliases of pointer -const Attributes NoRedZone = 1<<22; /// disable redzone -const Attributes NoImplicitFloat = 1<<23; /// disable implicit floating point +const Attributes NoCapture (1<<21); ///< Function creates no aliases of pointer +const Attributes NoRedZone (1<<22); /// disable redzone +const Attributes NoImplicitFloat (1<<23); /// disable implicit floating point /// instructions. -const Attributes Naked = 1<<24; ///< Naked function -const Attributes InlineHint = 1<<25; ///< source said inlining was +const Attributes Naked (1<<24); ///< Naked function +const Attributes InlineHint (1<<25); ///< source said inlining was ///desirable -const Attributes StackAlignment = 7<<26; ///< Alignment of stack for +const Attributes StackAlignment (7<<26); ///< Alignment of stack for ///function (3 bits) stored as log2 ///of alignment with +1 bias ///0 means unaligned (different from ///alignstack(1)) -const Attributes ReturnsTwice = 1<<29; ///< Function can return twice -const Attributes UWTable = 1<<30; ///< Function must be in a unwind +const Attributes ReturnsTwice (1<<29); ///< Function can return twice +const Attributes UWTable (1<<30); ///< Function must be in a unwind ///table -const Attributes NonLazyBind = 1U<<31; ///< Function is called early and/or +const Attributes NonLazyBind (1U<<31); ///< Function is called early and/or /// often, so lazy binding isn't /// worthwhile. +const Attributes AddressSafety(1ULL<<32); ///< Address safety checking is on. /// Note that uwtable is about the ABI or the user mandating an entry in the /// unwind table. The nounwind attribute is about an exception passing by the @@ -92,7 +133,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment | - UWTable | NonLazyBind | ReturnsTwice; + UWTable | NonLazyBind | ReturnsTwice | AddressSafety; /// @brief Parameter attributes that do not apply to vararg call arguments. const Attributes VarArgsIncompatible = StructRet; @@ -113,20 +154,20 @@ Attributes typeIncompatible(Type *Ty); inline Attributes constructAlignmentFromInt(unsigned i) { // Default alignment, allow the target to define how to align it. if (i == 0) - return 0; + return None; assert(isPowerOf2_32(i) && "Alignment must be a power of two."); assert(i <= 0x40000000 && "Alignment too large."); - return (Log2_32(i)+1) << 16; + return Attributes((Log2_32(i)+1) << 16); } /// This returns the alignment field of an attribute as a byte alignment value. inline unsigned getAlignmentFromAttrs(Attributes A) { Attributes Align = A & Attribute::Alignment; - if (Align == 0) + if (!Align) return 0; - return 1U << ((Align >> 16) - 1); + return 1U << ((Align.Raw() >> 16) - 1); } /// This turns an int stack alignment (which must be a power of 2) into @@ -134,21 +175,21 @@ inline unsigned getAlignmentFromAttrs(Attributes A) { inline Attributes constructStackAlignmentFromInt(unsigned i) { // Default alignment, allow the target to define how to align it. if (i == 0) - return 0; + return None; assert(isPowerOf2_32(i) && "Alignment must be a power of two."); assert(i <= 0x100 && "Alignment too large."); - return (Log2_32(i)+1) << 26; + return Attributes((Log2_32(i)+1) << 26); } /// This returns the stack alignment field of an attribute as a byte alignment /// value. inline unsigned getStackAlignmentFromAttrs(Attributes A) { Attributes StackAlign = A & Attribute::StackAlignment; - if (StackAlign == 0) + if (!StackAlign) return 0; - return 1U << ((StackAlign >> 26) - 1); + return 1U << ((StackAlign.Raw() >> 26) - 1); } @@ -242,7 +283,7 @@ public: /// paramHasAttr - Return true if the specified parameter index has the /// specified attribute set. bool paramHasAttr(unsigned Idx, Attributes Attr) const { - return (getAttributes(Idx) & Attr) != 0; + return getAttributes(Idx) & Attr; } /// getParamAlignment - Return the alignment for the specified function diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index d93108fc476..982ea48325f 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -548,6 +548,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(noimplicitfloat); KEYWORD(naked); KEYWORD(nonlazybind); + KEYWORD(address_safety); KEYWORD(type); KEYWORD(opaque); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index bab4f9d3282..e056f69cd70 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -874,7 +874,7 @@ bool LLParser::ParseOptionalAddrSpace(unsigned &AddrSpace) { /// ParseOptionalAttrs - Parse a potentially empty attribute list. AttrKind /// indicates what kind of attribute list this is: 0: function arg, 1: result, /// 2: function attr. -bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { +bool LLParser::ParseOptionalAttrs(Attributes &Attrs, unsigned AttrKind) { Attrs = Attribute::None; LocTy AttrLoc = Lex.getLoc(); @@ -919,6 +919,7 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break; case lltok::kw_naked: Attrs |= Attribute::Naked; break; case lltok::kw_nonlazybind: Attrs |= Attribute::NonLazyBind; break; + case lltok::kw_address_safety: Attrs |= Attribute::AddressSafety; break; case lltok::kw_alignstack: { unsigned Alignment; @@ -1353,8 +1354,8 @@ bool LLParser::ParseParameterList(SmallVectorImpl &ArgList, // Parse the argument. LocTy ArgLoc; Type *ArgTy = 0; - unsigned ArgAttrs1 = Attribute::None; - unsigned ArgAttrs2 = Attribute::None; + Attributes ArgAttrs1; + Attributes ArgAttrs2; Value *V; if (ParseType(ArgTy, ArgLoc)) return true; @@ -1394,7 +1395,7 @@ bool LLParser::ParseArgumentList(SmallVectorImpl &ArgList, } else { LocTy TypeLoc = Lex.getLoc(); Type *ArgTy = 0; - unsigned Attrs; + Attributes Attrs; std::string Name; if (ParseType(ArgTy) || @@ -1461,7 +1462,7 @@ bool LLParser::ParseFunctionType(Type *&Result) { for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { if (!ArgList[i].Name.empty()) return Error(ArgList[i].Loc, "argument name invalid in function type"); - if (ArgList[i].Attrs != 0) + if (ArgList[i].Attrs) return Error(ArgList[i].Loc, "argument attributes invalid in function type"); } @@ -2586,7 +2587,8 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { LocTy LinkageLoc = Lex.getLoc(); unsigned Linkage; - unsigned Visibility, RetAttrs; + unsigned Visibility; + Attributes RetAttrs; CallingConv::ID CC; Type *RetType = 0; LocTy RetTypeLoc = Lex.getLoc(); @@ -2650,7 +2652,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { SmallVector ArgList; bool isVarArg; - unsigned FuncAttrs; + Attributes FuncAttrs; std::string Section; unsigned Alignment; std::string GC; @@ -3162,7 +3164,7 @@ bool LLParser::ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS) { /// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { LocTy CallLoc = Lex.getLoc(); - unsigned RetAttrs, FnAttrs; + Attributes RetAttrs, FnAttrs; CallingConv::ID CC; Type *RetType = 0; LocTy RetTypeLoc; @@ -3561,7 +3563,7 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { /// ParameterList OptionalAttrs bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, bool isTail) { - unsigned RetAttrs, FnAttrs; + Attributes RetAttrs, FnAttrs; CallingConv::ID CC; Type *RetType = 0; LocTy RetTypeLoc; diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index c2537d7bda7..dda88083811 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -15,6 +15,7 @@ #define LLVM_ASMPARSER_LLPARSER_H #include "LLLexer.h" +#include "llvm/Attributes.h" #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Type.h" @@ -171,7 +172,7 @@ namespace llvm { return ParseUInt32(Val); } bool ParseOptionalAddrSpace(unsigned &AddrSpace); - bool ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind); + bool ParseOptionalAttrs(Attributes &Attrs, unsigned AttrKind); bool ParseOptionalLinkage(unsigned &Linkage, bool &HasLinkage); bool ParseOptionalLinkage(unsigned &Linkage) { bool HasLinkage; return ParseOptionalLinkage(Linkage, HasLinkage); @@ -304,8 +305,8 @@ namespace llvm { struct ParamInfo { LocTy Loc; Value *V; - unsigned Attrs; - ParamInfo(LocTy loc, Value *v, unsigned attrs) + Attributes Attrs; + ParamInfo(LocTy loc, Value *v, Attributes attrs) : Loc(loc), V(v), Attrs(attrs) {} }; bool ParseParameterList(SmallVectorImpl &ArgList, @@ -325,9 +326,9 @@ namespace llvm { struct ArgInfo { LocTy Loc; Type *Ty; - unsigned Attrs; + Attributes Attrs; std::string Name; - ArgInfo(LocTy L, Type *ty, unsigned Attr, const std::string &N) + ArgInfo(LocTy L, Type *ty, Attributes Attr, const std::string &N) : Loc(L), Ty(ty), Attrs(Attr), Name(N) {} }; bool ParseArgumentList(SmallVectorImpl &ArgList, bool &isVarArg); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 8f167725ed5..78564dbe849 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -102,6 +102,7 @@ namespace lltok { kw_noimplicitfloat, kw_naked, kw_nonlazybind, + kw_address_safety, kw_type, kw_opaque, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 9d10498943e..bddcde8242f 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -461,8 +461,8 @@ bool BitcodeReader::ParseAttributeBlock() { // If Function attributes are using index 0 then transfer them // to index ~0. Index 0 is used for return value attributes but used to be // used for function attributes. - Attributes RetAttribute = Attribute::None; - Attributes FnAttribute = Attribute::None; + Attributes RetAttribute; + Attributes FnAttribute; for (unsigned i = 0, e = Record.size(); i != e; i += 2) { // FIXME: remove in LLVM 3.0 // The alignment is stored as a 16-bit raw value from bits 31--16. @@ -472,23 +472,24 @@ bool BitcodeReader::ParseAttributeBlock() { if (Alignment && !isPowerOf2_32(Alignment)) return Error("Alignment is not a power of two."); - Attributes ReconstitutedAttr = Record[i+1] & 0xffff; + Attributes ReconstitutedAttr(Record[i+1] & 0xffff); if (Alignment) ReconstitutedAttr |= Attribute::constructAlignmentFromInt(Alignment); - ReconstitutedAttr |= (Record[i+1] & (0xffffull << 32)) >> 11; - Record[i+1] = ReconstitutedAttr; + ReconstitutedAttr |= + Attributes((Record[i+1] & (0xffffull << 32)) >> 11); + Record[i+1] = ReconstitutedAttr.Raw(); if (Record[i] == 0) - RetAttribute = Record[i+1]; + RetAttribute = ReconstitutedAttr; else if (Record[i] == ~0U) - FnAttribute = Record[i+1]; + FnAttribute = ReconstitutedAttr; } - unsigned OldRetAttrs = (Attribute::NoUnwind|Attribute::NoReturn| + Attributes OldRetAttrs = (Attribute::NoUnwind|Attribute::NoReturn| Attribute::ReadOnly|Attribute::ReadNone); if (FnAttribute == Attribute::None && RetAttribute != Attribute::None && - (RetAttribute & OldRetAttrs) != 0) { + (RetAttribute & OldRetAttrs)) { if (FnAttribute == Attribute::None) { // add a slot so they get added. Record.push_back(~0U); Record.push_back(0); @@ -505,8 +506,9 @@ bool BitcodeReader::ParseAttributeBlock() { } else if (Record[i] == ~0U) { if (FnAttribute != Attribute::None) Attrs.push_back(AttributeWithIndex::get(~0U, FnAttribute)); - } else if (Record[i+1] != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(Record[i], Record[i+1])); + } else if (Attributes(Record[i+1]) != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(Record[i], + Attributes(Record[i+1]))); } MAttributes.push_back(AttrListPtr::get(Attrs.begin(), Attrs.end())); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index b6da85e2957..7fb57eab375 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -179,10 +179,11 @@ static void WriteAttributeTable(const ValueEnumerator &VE, // Store the alignment in the bitcode as a 16-bit raw value instead of a // 5-bit log2 encoded value. Shift the bits above the alignment up by // 11 bits. - uint64_t FauxAttr = PAWI.Attrs & 0xffff; + uint64_t FauxAttr = PAWI.Attrs.Raw() & 0xffff; if (PAWI.Attrs & Attribute::Alignment) - FauxAttr |= (1ull<<16)<<(((PAWI.Attrs & Attribute::Alignment)-1) >> 16); - FauxAttr |= (PAWI.Attrs & (0x3FFull << 21)) << 11; + FauxAttr |= (1ull<<16)<< + (((PAWI.Attrs & Attribute::Alignment).Raw()-1) >> 16); + FauxAttr |= (PAWI.Attrs.Raw() & (0x3FFull << 21)) << 11; Record.push_back(FauxAttr); } diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp index 0c84be5faba..6980e7d8d34 100644 --- a/lib/CodeGen/Analysis.cpp +++ b/lib/CodeGen/Analysis.cpp @@ -259,7 +259,7 @@ bool llvm::isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, // Conservatively require the attributes of the call to match those of // the return. Ignore noalias because it doesn't affect the call sequence. const Function *F = ExitBB->getParent(); - unsigned CallerRetAttr = F->getAttributes().getRetAttributes(); + Attributes CallerRetAttr = F->getAttributes().getRetAttributes(); if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) return false; @@ -299,7 +299,7 @@ bool llvm::isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, // Conservatively require the attributes of the call to match those of // the return. Ignore noalias because it doesn't affect the call sequence. - unsigned CallerRetAttr = F->getAttributes().getRetAttributes(); + Attributes CallerRetAttr = F->getAttributes().getRetAttributes(); if (CallerRetAttr & ~Attribute::NoAlias) return false; diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 27c7c54a9c8..db31e9144a8 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1063,7 +1063,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { if (!CastInst::isCastable(ActTy, ParamTy)) return false; // Cannot transform this parameter value. - unsigned Attrs = CallerPAL.getParamAttributes(i + 1); + Attributes Attrs = CallerPAL.getParamAttributes(i + 1); if (Attrs & Attribute::typeIncompatible(ParamTy)) return false; // Attribute not compatible with transformed value. @@ -1392,4 +1392,3 @@ InstCombiner::transformCallThroughTrampoline(CallSite CS, CS.setCalledFunction(NewCallee); return CS.getInstruction(); } - diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index f9abfe9802c..5ca5e47cd05 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -619,7 +619,7 @@ bool CodeGenPrepare::DupRetToEnableTailCallOpts(ReturnInst *RI) { // It's not safe to eliminate the sign / zero extension of the return value. // See llvm::isInTailCallPosition(). const Function *F = BB->getParent(); - unsigned CallerRetAttr = F->getAttributes().getRetAttributes(); + Attributes CallerRetAttr = F->getAttributes().getRetAttributes(); if ((CallerRetAttr & Attribute::ZExt) || (CallerRetAttr & Attribute::SExt)) return false; @@ -674,7 +674,7 @@ bool CodeGenPrepare::DupRetToEnableTailCallOpts(ReturnInst *RI) { // Conservatively require the attributes of the call to match those of the // return. Ignore noalias because it doesn't affect the call sequence. - unsigned CalleeRetAttr = CS.getAttributes().getRetAttributes(); + Attributes CalleeRetAttr = CS.getAttributes().getRetAttributes(); if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) continue; diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index 485be75d1b1..c05132be5a4 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -76,6 +76,8 @@ std::string Attribute::getAsString(Attributes Attrs) { Result += "naked "; if (Attrs & Attribute::NonLazyBind) Result += "nonlazybind "; + if (Attrs & Attribute::AddressSafety) + Result += "address_safety "; if (Attrs & Attribute::StackAlignment) { Result += "alignstack("; Result += utostr(Attribute::getStackAlignmentFromAttrs(Attrs)); @@ -152,8 +154,10 @@ public: } static void Profile(FoldingSetNodeID &ID, const AttributeWithIndex *Attr, unsigned NumAttrs) { - for (unsigned i = 0; i != NumAttrs; ++i) - ID.AddInteger(uint64_t(Attr[i].Attrs) << 32 | unsigned(Attr[i].Index)); + for (unsigned i = 0; i != NumAttrs; ++i) { + ID.AddInteger(Attr[i].Attrs.Raw()); + ID.AddInteger(Attr[i].Index); + } } }; } diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index 7f86baab114..ddc2604461e 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm-c/Core.h" +#include "llvm/Attributes.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -1350,14 +1351,14 @@ void LLVMSetGC(LLVMValueRef Fn, const char *GC) { void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA) { Function *Func = unwrap(Fn); const AttrListPtr PAL = Func->getAttributes(); - const AttrListPtr PALnew = PAL.addAttr(~0U, PA); + const AttrListPtr PALnew = PAL.addAttr(~0U, Attributes(PA)); Func->setAttributes(PALnew); } void LLVMRemoveFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA) { Function *Func = unwrap(Fn); const AttrListPtr PAL = Func->getAttributes(); - const AttrListPtr PALnew = PAL.removeAttr(~0U, PA); + const AttrListPtr PALnew = PAL.removeAttr(~0U, Attributes(PA)); Func->setAttributes(PALnew); } @@ -1365,7 +1366,7 @@ LLVMAttribute LLVMGetFunctionAttr(LLVMValueRef Fn) { Function *Func = unwrap(Fn); const AttrListPtr PAL = Func->getAttributes(); Attributes attr = PAL.getFnAttributes(); - return (LLVMAttribute)attr; + return (LLVMAttribute)attr.Raw(); } /*--.. Operations on parameters ............................................--*/ @@ -1427,18 +1428,18 @@ LLVMValueRef LLVMGetPreviousParam(LLVMValueRef Arg) { } void LLVMAddAttribute(LLVMValueRef Arg, LLVMAttribute PA) { - unwrap(Arg)->addAttr(PA); + unwrap(Arg)->addAttr(Attributes(PA)); } void LLVMRemoveAttribute(LLVMValueRef Arg, LLVMAttribute PA) { - unwrap(Arg)->removeAttr(PA); + unwrap(Arg)->removeAttr(Attributes(PA)); } LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg) { Argument *A = unwrap(Arg); Attributes attr = A->getParent()->getAttributes().getParamAttributes( A->getArgNo()+1); - return (LLVMAttribute)attr; + return (LLVMAttribute)attr.Raw(); } @@ -1635,14 +1636,14 @@ void LLVMAddInstrAttribute(LLVMValueRef Instr, unsigned index, LLVMAttribute PA) { CallSite Call = CallSite(unwrap(Instr)); Call.setAttributes( - Call.getAttributes().addAttr(index, PA)); + Call.getAttributes().addAttr(index, Attributes(PA))); } void LLVMRemoveInstrAttribute(LLVMValueRef Instr, unsigned index, LLVMAttribute PA) { CallSite Call = CallSite(unwrap(Instr)); Call.setAttributes( - Call.getAttributes().removeAttr(index, PA)); + Call.getAttributes().removeAttr(index, Attributes(PA))); } void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index, diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index ea773b3a62d..b678f251b3f 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -547,7 +547,7 @@ void Verifier::VerifyParameterAttrs(Attributes Attrs, Type *Ty, for (unsigned i = 0; i < array_lengthof(Attribute::MutuallyIncompatible); ++i) { Attributes MutI = Attrs & Attribute::MutuallyIncompatible[i]; - Assert1(!(MutI & (MutI - 1)), "Attributes " + + Assert1(MutI.isEmptyOrSingleton(), "Attributes " + Attribute::getAsString(MutI) + " are incompatible!", V); } @@ -607,7 +607,7 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, for (unsigned i = 0; i < array_lengthof(Attribute::MutuallyIncompatible); ++i) { Attributes MutI = FAttrs & Attribute::MutuallyIncompatible[i]; - Assert1(!(MutI & (MutI - 1)), "Attributes " + + Assert1(MutI.isEmptyOrSingleton(), "Attributes " + Attribute::getAsString(MutI) + " are incompatible!", V); } } diff --git a/utils/llvm.grm b/utils/llvm.grm index fb26dbb66f6..322036b2c20 100644 --- a/utils/llvm.grm +++ b/utils/llvm.grm @@ -174,6 +174,7 @@ FuncAttr ::= noreturn | sspreq | returns_twice | nonlazybind + | address_safety ; OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ; -- 2.11.0