Get rid of the 'Bits' mask in the attribute builder.
authorBill Wendling <isanbard@gmail.com>
Fri, 4 Jan 2013 23:27:34 +0000 (23:27 +0000)
committerBill Wendling <isanbard@gmail.com>
Fri, 4 Jan 2013 23:27:34 +0000 (23:27 +0000)
The bit mask thing will be a thing of the past. It's not extensible enough. Get
rid of its use here. Opt instead for using a vector to hold the attributes.

Note: Some of this code will become obsolete once the rewrite is further along.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171553 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Attributes.h
lib/IR/Attributes.cpp

index b80e9069e51f41abbcf07fdc0f6a604214aebd5b..e5a1ad294b59fc4d01a602029fe1c684266efd4c 100644 (file)
@@ -17,6 +17,7 @@
 #define LLVM_ATTRIBUTES_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/Support/MathExtras.h"
 #include <cassert>
 #include <string>
@@ -90,7 +91,9 @@ public:
     StackProtectReq,       ///< Stack protection required.
     StructRet,             ///< Hidden pointer to structure to return
     UWTable,               ///< Function must be in a unwind table
-    ZExt                   ///< Zero extended before/after call
+    ZExt,                  ///< Zero extended before/after call
+
+    EndAttrKinds           ///< Sentinal value useful for loops
   };
 private:
   AttributeImpl *pImpl;
@@ -150,6 +153,26 @@ public:
   std::string getAsString() const;
 };
 
+//===----------------------------------------------------------------------===//
+/// \class
+/// \brief Provide DenseMapInfo for Attribute::AttrKinds. This is used by
+/// AttrBuilder.
+template<> struct DenseMapInfo<Attribute::AttrKind> {
+  static inline Attribute::AttrKind getEmptyKey() {
+    return Attribute::AttrKind(~0U);
+  }
+  static inline Attribute::AttrKind getTombstoneKey() {
+    return Attribute::AttrKind(~0U - 1);
+  }
+  static unsigned getHashValue(const Attribute::AttrKind &Val) {
+    return Val * 37U;
+  }
+  static bool isEqual(const Attribute::AttrKind &LHS,
+                      const Attribute::AttrKind &RHS) {
+    return LHS == RHS;
+  }
+};
+
 //===----------------------------------------------------------------------===//
 /// \class
 /// \brief This class is used in conjunction with the Attribute::get method to
@@ -157,13 +180,19 @@ public:
 /// value, however, is not. So this can be used as a quick way to test for
 /// equality, presence of attributes, etc.
 class AttrBuilder {
-  uint64_t Bits;
+  DenseSet<Attribute::AttrKind> Attrs;
+  uint64_t Alignment;
+  uint64_t StackAlignment;
 public:
-  AttrBuilder() : Bits(0) {}
-  explicit AttrBuilder(uint64_t B) : Bits(B) {}
-  AttrBuilder(const Attribute &A) : Bits(A.getBitMask()) {}
+  AttrBuilder() : Alignment(0), StackAlignment(0) {}
+  explicit AttrBuilder(uint64_t B) : Alignment(0), StackAlignment(0) {
+    addRawValue(B);
+  }
+  AttrBuilder(const Attribute &A) : Alignment(0), StackAlignment(0) {
+    addAttributes(A);
+  }
 
-  void clear() { Bits = 0; }
+  void clear();
 
   /// \brief Add an attribute to the builder.
   AttrBuilder &addAttribute(Attribute::AttrKind Val);
@@ -191,10 +220,10 @@ public:
   bool hasAlignmentAttr() const;
 
   /// \brief Retrieve the alignment attribute, if it exists.
-  uint64_t getAlignment() const;
+  uint64_t getAlignment() const { return Alignment; }
 
   /// \brief Retrieve the stack alignment attribute, if it exists.
-  uint64_t getStackAlignment() const;
+  uint64_t getStackAlignment() const { return StackAlignment; }
 
   /// \brief This turns an int alignment (which must be a power of 2) into the
   /// form used internally in Attribute.
@@ -233,13 +262,11 @@ public:
       .removeAttribute(Attribute::NoDuplicate);
   }
 
-  uint64_t getBitMask() const { return Bits; }
+  uint64_t getBitMask() const;
 
-  bool operator==(const AttrBuilder &B) {
-    return Bits == B.Bits;
-  }
+  bool operator==(const AttrBuilder &B);
   bool operator!=(const AttrBuilder &B) {
-    return Bits != B.Bits;
+    return !(*this == B);
   }
 };
 
index 5057f783bb5a727ba8c64255c84e3281c7d4f422..068b504294877e529359df4386d8a3a6ffb23142 100644 (file)
@@ -225,78 +225,142 @@ std::string Attribute::getAsString() const {
 }
 
 //===----------------------------------------------------------------------===//
-// AttrBuilder Implementation
+// AttrBuilder Method Implementations
 //===----------------------------------------------------------------------===//
 
-AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val){
-  Bits |= AttributeImpl::getAttrMask(Val);
+void AttrBuilder::clear() {
+  Attrs.clear();
+  Alignment = StackAlignment = 0;
+}
+
+AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
+  Attrs.insert(Val);
   return *this;
 }
 
-AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
-  Bits |= Val;
+AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
+  Attrs.erase(Val);
+  if (Val == Attribute::Alignment)
+    Alignment = 0;
+  else if (Val == Attribute::StackAlignment)
+    StackAlignment = 0;
+
   return *this;
 }
 
 AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
   if (Align == 0) return *this;
+
   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
   assert(Align <= 0x40000000 && "Alignment too large.");
-  Bits |= (Log2_32(Align) + 1) << 16;
+
+  Attrs.insert(Attribute::Alignment);
+  Alignment = Align;
   return *this;
 }
-AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align){
+
+AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) {
   // Default alignment, allow the target to define how to align it.
   if (Align == 0) return *this;
+
   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
   assert(Align <= 0x100 && "Alignment too large.");
-  Bits |= (Log2_32(Align) + 1) << 26;
+
+  Attrs.insert(Attribute::StackAlignment);
+  StackAlignment = Align;
   return *this;
 }
 
-AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
-  Bits &= ~AttributeImpl::getAttrMask(Val);
+AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
+  for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
+       I = Attribute::AttrKind(I + 1)) {
+    if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {
+      Attrs.insert(I);
+
+      if (I == Attribute::Alignment)
+        Alignment = 1ULL << ((A >> 16) - 1);
+      else if (I == Attribute::StackAlignment)
+        StackAlignment = 1ULL << ((A >> 26)-1);
+    }
+  }
+
   return *this;
 }
 
 AttrBuilder &AttrBuilder::addAttributes(const Attribute &A) {
-  Bits |= A.getBitMask();
+  uint64_t Mask = A.getBitMask();
+
+  for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
+       I = Attribute::AttrKind(I + 1)) {
+    if (uint64_t A = (Mask & AttributeImpl::getAttrMask(I))) {
+      Attrs.insert(I);
+
+      if (I == Attribute::Alignment)
+        Alignment = 1ULL << ((A >> 16) - 1);
+      else if (I == Attribute::StackAlignment)
+        StackAlignment = 1ULL << ((A >> 26)-1);
+    }
+  }
+
   return *this;
 }
 
 AttrBuilder &AttrBuilder::removeAttributes(const Attribute &A){
-  Bits &= ~A.getBitMask();
+  uint64_t Mask = A.getBitMask();
+
+  for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
+       I = Attribute::AttrKind(I + 1)) {
+    if (Mask & AttributeImpl::getAttrMask(I)) {
+      Attrs.erase(I);
+
+      if (I == Attribute::Alignment)
+        Alignment = 0;
+      else if (I == Attribute::StackAlignment)
+        StackAlignment = 0;
+    }
+  }
+
   return *this;
 }
 
 bool AttrBuilder::contains(Attribute::AttrKind A) const {
-  return Bits & AttributeImpl::getAttrMask(A);
+  return Attrs.count(A);
 }
 
 bool AttrBuilder::hasAttributes() const {
-  return Bits != 0;
+  return !Attrs.empty();
 }
 
 bool AttrBuilder::hasAttributes(const Attribute &A) const {
-  return Bits & A.getBitMask();
+  return getBitMask() & A.getBitMask();
 }
 
 bool AttrBuilder::hasAlignmentAttr() const {
-  return Bits & AttributeImpl::getAttrMask(Attribute::Alignment);
+  return Alignment != 0;
 }
 
-uint64_t AttrBuilder::getAlignment() const {
-  if (!hasAlignmentAttr())
-    return 0;
-  return 1ULL <<
-    (((Bits & AttributeImpl::getAttrMask(Attribute::Alignment)) >> 16) - 1);
+uint64_t AttrBuilder::getBitMask() const {
+  uint64_t Mask = 0;
+
+  for (DenseSet<Attribute::AttrKind>::const_iterator I = Attrs.begin(),
+         E = Attrs.end(); I != E; ++I) {
+    Attribute::AttrKind Kind = *I;
+
+    if (Kind == Attribute::Alignment)
+      Mask |= (Log2_32(Alignment) + 1) << 16;
+    else if (Kind == Attribute::StackAlignment)
+      Mask |= (Log2_32(StackAlignment) + 1) << 26;
+    else
+      Mask |= AttributeImpl::getAttrMask(Kind);
+  }
+
+  return Mask;
 }
 
-uint64_t AttrBuilder::getStackAlignment() const {
-  if (!hasAlignmentAttr())
-    return 0;
-  return 1ULL <<
-    (((Bits & AttributeImpl::getAttrMask(Attribute::StackAlignment))>>26)-1);
+bool AttrBuilder::operator==(const AttrBuilder &B) {
+  SmallVector<Attribute::AttrKind, 8> This(Attrs.begin(), Attrs.end());
+  SmallVector<Attribute::AttrKind, 8> That(B.Attrs.begin(), B.Attrs.end());
+  return This == That;
 }
 
 //===----------------------------------------------------------------------===//
@@ -345,6 +409,7 @@ uint64_t AttributeImpl::getBitMask() const {
 
 uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
   switch (Val) {
+  case Attribute::EndAttrKinds:    break;
   case Attribute::None:            return 0;
   case Attribute::ZExt:            return 1 << 0;
   case Attribute::SExt:            return 1 << 1;