OSDN Git Service

Extend Attributes to 64 bits
authorKostya Serebryany <kcc@google.com>
Fri, 20 Jan 2012 17:56:17 +0000 (17:56 +0000)
committerKostya Serebryany <kcc@google.com>
Fri, 20 Jan 2012 17:56:17 +0000 (17:56 +0000)
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

16 files changed:
docs/LangRef.html
include/llvm-c/Core.h
include/llvm/Attributes.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/AsmParser/LLToken.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/CodeGen/Analysis.cpp
lib/Transforms/InstCombine/InstCombineCalls.cpp
lib/Transforms/Scalar/CodeGenPrepare.cpp
lib/VMCore/Attributes.cpp
lib/VMCore/Core.cpp
lib/VMCore/Verifier.cpp
utils/llvm.grm

index 1172b7c..e214c5f 100644 (file)
@@ -1143,6 +1143,10 @@ define void @f() optsize { ... }
 </pre>
 
 <dl>
+  <dt><tt><b>address_safety</b></tt></dt>
+  <dd>This attribute indicates that the address safety analysis
+  is enabled for this function.  </dd>
+
   <dt><tt><b>alignstack(&lt;<em>n</em>&gt;)</b></tt></dt>
   <dd>This attribute indicates that, when emitting the prologue and epilogue,
       the backend should forcibly align the stack pointer. Specify the
index 63d6fd4..de60f77 100644 (file)
@@ -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 {
index 2d7b33b..6082cf0 100644 (file)
@@ -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
index d93108f..982ea48 100644 (file)
@@ -548,6 +548,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(noimplicitfloat);
   KEYWORD(naked);
   KEYWORD(nonlazybind);
+  KEYWORD(address_safety);
 
   KEYWORD(type);
   KEYWORD(opaque);
index bab4f9d..e056f69 100644 (file)
@@ -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<ParamInfo> &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<ArgInfo> &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<ArgInfo, 8> 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;
index c2537d7..dda8808 100644 (file)
@@ -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<ParamInfo> &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<ArgInfo> &ArgList, bool &isVarArg);
index 8f16772..78564db 100644 (file)
@@ -102,6 +102,7 @@ namespace lltok {
     kw_noimplicitfloat,
     kw_naked,
     kw_nonlazybind,
+    kw_address_safety,
 
     kw_type,
     kw_opaque,
index 9d10498..bddcde8 100644 (file)
@@ -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()));
index b6da85e..7fb57ea 100644 (file)
@@ -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);
     }
index 0c84be5..6980e7d 100644 (file)
@@ -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;
 
index 27c7c54..db31e91 100644 (file)
@@ -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();
 }
-
index f9abfe9..5ca5e47 100644 (file)
@@ -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;
 
index 485be75..c05132b 100644 (file)
@@ -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);
+    }
   }
 };
 }
index 7f86baa..ddc2604 100644 (file)
@@ -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<Function>(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<Function>(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<Function>(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<Argument>(Arg)->addAttr(PA);
+  unwrap<Argument>(Arg)->addAttr(Attributes(PA));
 }
 
 void LLVMRemoveAttribute(LLVMValueRef Arg, LLVMAttribute PA) {
-  unwrap<Argument>(Arg)->removeAttr(PA);
+  unwrap<Argument>(Arg)->removeAttr(Attributes(PA));
 }
 
 LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg) {
   Argument *A = unwrap<Argument>(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<Instruction>(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<Instruction>(Instr));
   Call.setAttributes(
-    Call.getAttributes().removeAttr(index, PA));
+    Call.getAttributes().removeAttr(index, Attributes(PA)));
 }
 
 void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index, 
index ea773b3..b678f25 100644 (file)
@@ -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);
   }
 }
index fb26dbb..322036b 100644 (file)
@@ -174,6 +174,7 @@ FuncAttr      ::= noreturn
  | sspreq
  | returns_twice
  | nonlazybind
+ | address_safety
  ;
 
 OptFuncAttrs  ::= + _ | OptFuncAttrs FuncAttr ;