diff options
Diffstat (limited to 'llvm/include/llvm/IR/Attributes.h')
-rw-r--r-- | llvm/include/llvm/IR/Attributes.h | 98 |
1 files changed, 84 insertions, 14 deletions
diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h index f64f15bd38ba..0e75371037bf 100644 --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -28,12 +28,14 @@ #include <cassert> #include <cstdint> #include <map> +#include <set> #include <string> #include <utility> namespace llvm { class AttrBuilder; +class AttributeMask; class AttributeImpl; class AttributeListImpl; class AttributeSetNode; @@ -320,7 +322,7 @@ public: /// Remove the specified attributes from this set. Returns a new set because /// attribute sets are immutable. LLVM_NODISCARD AttributeSet - removeAttributes(LLVMContext &C, const AttrBuilder &AttrsToRemove) const; + removeAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const; /// Return the number of attributes in this set. unsigned getNumAttributes() const; @@ -580,7 +582,7 @@ public: /// Remove the specified attributes at the specified index from this /// attribute list. Returns a new list because attribute lists are immutable. LLVM_NODISCARD AttributeList removeAttributesAtIndex( - LLVMContext &C, unsigned Index, const AttrBuilder &AttrsToRemove) const; + LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const; /// Remove all attributes at the specified index from this /// attribute list. Returns a new list because attribute lists are immutable. @@ -604,7 +606,7 @@ public: /// Remove the specified attribute at the function index from this /// attribute list. Returns a new list because attribute lists are immutable. LLVM_NODISCARD AttributeList - removeFnAttributes(LLVMContext &C, const AttrBuilder &AttrsToRemove) const { + removeFnAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const { return removeAttributesAtIndex(C, FunctionIndex, AttrsToRemove); } @@ -630,8 +632,8 @@ public: /// Remove the specified attribute at the return value index from this /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList - removeRetAttributes(LLVMContext &C, const AttrBuilder &AttrsToRemove) const { + LLVM_NODISCARD AttributeList removeRetAttributes( + LLVMContext &C, const AttributeMask &AttrsToRemove) const { return removeAttributesAtIndex(C, ReturnIndex, AttrsToRemove); } @@ -652,8 +654,9 @@ public: /// Remove the specified attribute at the specified arg index from this /// attribute list. Returns a new list because attribute lists are immutable. - LLVM_NODISCARD AttributeList removeParamAttributes( - LLVMContext &C, unsigned ArgNo, const AttrBuilder &AttrsToRemove) const { + LLVM_NODISCARD AttributeList + removeParamAttributes(LLVMContext &C, unsigned ArgNo, + const AttributeMask &AttrsToRemove) const { return removeAttributesAtIndex(C, ArgNo + FirstArgIndex, AttrsToRemove); } @@ -929,6 +932,65 @@ template <> struct DenseMapInfo<AttributeList, void> { //===----------------------------------------------------------------------===// /// \class +/// This class stores enough information to efficiently remove some attributes +/// from an existing AttrBuilder, AttributeSet or AttributeList. +class AttributeMask { + std::bitset<Attribute::EndAttrKinds> Attrs; + std::set<SmallString<32>, std::less<>> TargetDepAttrs; + +public: + AttributeMask() = default; + AttributeMask(const AttributeMask &) = delete; + AttributeMask(AttributeMask &&) = default; + + AttributeMask(AttributeSet AS) { + for (Attribute A : AS) + addAttribute(A); + } + + /// Add an attribute to the mask. + AttributeMask &addAttribute(Attribute::AttrKind Val) { + assert((unsigned)Val < Attribute::EndAttrKinds && + "Attribute out of range!"); + Attrs[Val] = true; + return *this; + } + + /// Add the Attribute object to the builder. + AttributeMask &addAttribute(Attribute A) { + if (A.isStringAttribute()) + addAttribute(A.getKindAsString()); + else + addAttribute(A.getKindAsEnum()); + return *this; + } + + /// Add the target-dependent attribute to the builder. + AttributeMask &addAttribute(StringRef A) { + TargetDepAttrs.insert(A); + return *this; + } + + /// Return true if the builder has the specified attribute. + bool contains(Attribute::AttrKind A) const { + assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); + return Attrs[A]; + } + + /// Return true if the builder has the specified target-dependent + /// attribute. + bool contains(StringRef A) const { return TargetDepAttrs.count(A); } + + using td_const_iterator = decltype(TargetDepAttrs)::const_iterator; + using td_const_range = iterator_range<td_const_iterator>; + td_const_range td_attrs() const { + return {TargetDepAttrs.begin(), TargetDepAttrs.end()}; + } + auto const &attrs() const { return Attrs; } +}; + +//===----------------------------------------------------------------------===// +/// \class /// This class is used in conjunction with the Attribute::get method to /// create an Attribute object. The object itself is uniquified. The Builder's /// value, however, is not. So this can be used as a quick way to test for @@ -975,21 +1037,29 @@ public: /// Remove an attribute from the builder. AttrBuilder &removeAttribute(Attribute::AttrKind Val); + /// Remove the target-dependent attribute from the builder. + AttrBuilder &removeAttribute(StringRef A); + + /// Remove the target-dependent attribute from the builder. + AttrBuilder &removeAttribute(Attribute A) { + if (A.isStringAttribute()) + return removeAttribute(A.getKindAsString()); + else + return removeAttribute(A.getKindAsEnum()); + } + /// Remove the attributes from the builder. AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex); - /// Remove the target-dependent attribute to the builder. - AttrBuilder &removeAttribute(StringRef A); - /// Add the attributes from the builder. AttrBuilder &merge(const AttrBuilder &B); /// Remove the attributes from the builder. - AttrBuilder &remove(const AttrBuilder &B); + AttrBuilder &remove(const AttributeMask &AM); /// Return true if the builder has any attribute that's in the /// specified builder. - bool overlaps(const AttrBuilder &B) const; + bool overlaps(const AttributeMask &AM) const; /// Return true if the builder has the specified attribute. bool contains(Attribute::AttrKind A) const { @@ -1168,14 +1238,14 @@ public: namespace AttributeFuncs { /// Which attributes cannot be applied to a type. -AttrBuilder typeIncompatible(Type *Ty); +AttributeMask typeIncompatible(Type *Ty); /// Get param/return attributes which imply immediate undefined behavior if an /// invalid value is passed. For example, this includes noundef (where undef /// implies UB), but not nonnull (where null implies poison). It also does not /// include attributes like nocapture, which constrain the function /// implementation rather than the passed value. -AttrBuilder getUBImplyingAttributes(); +AttributeMask getUBImplyingAttributes(); /// \returns Return true if the two functions have compatible target-independent /// attributes for inlining purposes. |