diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index b80e9069e51..e5a1ad294b5 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -17,6 +17,7 @@ #define LLVM_ATTRIBUTES_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/Support/MathExtras.h" #include #include @@ -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 { + 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 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); } }; diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 5057f783bb5..068b5042948 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -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; - return *this; -} -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::Alignment); + Alignment = Align; return *this; } -AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { - Bits &= ~AttributeImpl::getAttrMask(Val); +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."); + + Attrs.insert(Attribute::StackAlignment); + StackAlignment = Align; + return *this; +} + +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::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 This(Attrs.begin(), Attrs.end()); + SmallVector 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;