1 //===-- AttributeImpl.h - Attribute Internals -------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief This file defines various helper methods and classes used by 12 /// LLVMContextImpl for creating and managing attributes. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H 17 #define LLVM_LIB_IR_ATTRIBUTEIMPL_H 18 19 #include "AttributeSetNode.h" 20 #include "llvm/ADT/ArrayRef.h" 21 #include "llvm/ADT/FoldingSet.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/IR/Attributes.h" 24 #include "llvm/Support/TrailingObjects.h" 25 #include <algorithm> 26 #include <cassert> 27 #include <climits> 28 #include <cstddef> 29 #include <cstdint> 30 #include <string> 31 #include <utility> 32 33 namespace llvm { 34 35 class LLVMContext; 36 37 //===----------------------------------------------------------------------===// 38 /// \class 39 /// \brief This class represents a single, uniqued attribute. That attribute 40 /// could be a single enum, a tuple, or a string. 41 class AttributeImpl : public FoldingSetNode { 42 unsigned char KindID; ///< Holds the AttrEntryKind of the attribute 43 44 protected: 45 enum AttrEntryKind { 46 EnumAttrEntry, 47 IntAttrEntry, 48 StringAttrEntry 49 }; 50 51 AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} 52 53 public: 54 // AttributesImpl is uniqued, these should not be available. 55 AttributeImpl(const AttributeImpl &) = delete; 56 AttributeImpl &operator=(const AttributeImpl &) = delete; 57 58 virtual ~AttributeImpl(); 59 60 bool isEnumAttribute() const { return KindID == EnumAttrEntry; } 61 bool isIntAttribute() const { return KindID == IntAttrEntry; } 62 bool isStringAttribute() const { return KindID == StringAttrEntry; } 63 64 bool hasAttribute(Attribute::AttrKind A) const; 65 bool hasAttribute(StringRef Kind) const; 66 67 Attribute::AttrKind getKindAsEnum() const; 68 uint64_t getValueAsInt() const; 69 70 StringRef getKindAsString() const; 71 StringRef getValueAsString() const; 72 73 /// \brief Used when sorting the attributes. 74 bool operator<(const AttributeImpl &AI) const; 75 76 void Profile(FoldingSetNodeID &ID) const { 77 if (isEnumAttribute()) 78 Profile(ID, getKindAsEnum(), 0); 79 else if (isIntAttribute()) 80 Profile(ID, getKindAsEnum(), getValueAsInt()); 81 else 82 Profile(ID, getKindAsString(), getValueAsString()); 83 } 84 static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 85 uint64_t Val) { 86 ID.AddInteger(Kind); 87 if (Val) ID.AddInteger(Val); 88 } 89 static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) { 90 ID.AddString(Kind); 91 if (!Values.empty()) ID.AddString(Values); 92 } 93 }; 94 95 //===----------------------------------------------------------------------===// 96 /// \class 97 /// \brief A set of classes that contain the value of the 98 /// attribute object. There are three main categories: enum attribute entries, 99 /// represented by Attribute::AttrKind; alignment attribute entries; and string 100 /// attribute enties, which are for target-dependent attributes. 101 102 class EnumAttributeImpl : public AttributeImpl { 103 virtual void anchor(); 104 Attribute::AttrKind Kind; 105 106 protected: 107 EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind) 108 : AttributeImpl(ID), Kind(Kind) {} 109 110 public: 111 EnumAttributeImpl(Attribute::AttrKind Kind) 112 : AttributeImpl(EnumAttrEntry), Kind(Kind) {} 113 114 Attribute::AttrKind getEnumKind() const { return Kind; } 115 }; 116 117 class IntAttributeImpl : public EnumAttributeImpl { 118 void anchor() override; 119 uint64_t Val; 120 121 public: 122 IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) 123 : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { 124 assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment || 125 Kind == Attribute::Dereferenceable || 126 Kind == Attribute::DereferenceableOrNull || 127 Kind == Attribute::AllocSize) && 128 "Wrong kind for int attribute!"); 129 } 130 131 uint64_t getValue() const { return Val; } 132 }; 133 134 class StringAttributeImpl : public AttributeImpl { 135 virtual void anchor(); 136 std::string Kind; 137 std::string Val; 138 139 public: 140 StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) 141 : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {} 142 143 StringRef getStringKind() const { return Kind; } 144 StringRef getStringValue() const { return Val; } 145 }; 146 147 typedef std::pair<unsigned, AttributeSetNode *> IndexAttrPair; 148 149 //===----------------------------------------------------------------------===// 150 /// \class 151 /// \brief This class represents a set of attributes that apply to the function, 152 /// return type, and parameters. 153 class AttributeSetImpl final 154 : public FoldingSetNode, 155 private TrailingObjects<AttributeSetImpl, IndexAttrPair> { 156 friend class AttributeSet; 157 friend TrailingObjects; 158 159 private: 160 LLVMContext &Context; 161 unsigned NumSlots; ///< Number of entries in this set. 162 /// Bitset with a bit for each available attribute Attribute::AttrKind. 163 uint64_t AvailableFunctionAttrs; 164 165 // Helper fn for TrailingObjects class. 166 size_t numTrailingObjects(OverloadToken<IndexAttrPair>) { return NumSlots; } 167 168 /// \brief Return a pointer to the IndexAttrPair for the specified slot. 169 const IndexAttrPair *getNode(unsigned Slot) const { 170 return getTrailingObjects<IndexAttrPair>() + Slot; 171 } 172 173 public: 174 AttributeSetImpl(LLVMContext &C, 175 ArrayRef<std::pair<unsigned, AttributeSetNode *>> Slots) 176 : Context(C), NumSlots(Slots.size()), AvailableFunctionAttrs(0) { 177 static_assert(Attribute::EndAttrKinds <= 178 sizeof(AvailableFunctionAttrs) * CHAR_BIT, 179 "Too many attributes"); 180 181 #ifndef NDEBUG 182 if (Slots.size() >= 2) { 183 for (const std::pair<unsigned, AttributeSetNode *> *i = Slots.begin() + 1, 184 *e = Slots.end(); 185 i != e; ++i) { 186 assert((i-1)->first <= i->first && "Attribute set not ordered!"); 187 } 188 } 189 #endif 190 // There's memory after the node where we can store the entries in. 191 std::copy(Slots.begin(), Slots.end(), getTrailingObjects<IndexAttrPair>()); 192 193 // Initialize AvailableFunctionAttrs summary bitset. 194 if (NumSlots > 0) { 195 static_assert(AttributeSet::FunctionIndex == ~0u, 196 "FunctionIndex should be biggest possible index"); 197 const std::pair<unsigned, AttributeSetNode *> &Last = Slots.back(); 198 if (Last.first == AttributeSet::FunctionIndex) { 199 const AttributeSetNode *Node = Last.second; 200 for (Attribute I : *Node) { 201 if (!I.isStringAttribute()) 202 AvailableFunctionAttrs |= ((uint64_t)1) << I.getKindAsEnum(); 203 } 204 } 205 } 206 } 207 208 // AttributesSetImpt is uniqued, these should not be available. 209 AttributeSetImpl(const AttributeSetImpl &) = delete; 210 AttributeSetImpl &operator=(const AttributeSetImpl &) = delete; 211 212 void operator delete(void *p) { ::operator delete(p); } 213 214 /// \brief Get the context that created this AttributeSetImpl. 215 LLVMContext &getContext() { return Context; } 216 217 /// \brief Return the number of slots used in this attribute list. This is 218 /// the number of arguments that have an attribute set on them (including the 219 /// function itself). 220 unsigned getNumSlots() const { return NumSlots; } 221 222 /// \brief Get the index of the given "slot" in the AttrNodes list. This index 223 /// is the index of the return, parameter, or function object that the 224 /// attributes are applied to, not the index into the AttrNodes list where the 225 /// attributes reside. 226 unsigned getSlotIndex(unsigned Slot) const { 227 return getNode(Slot)->first; 228 } 229 230 /// \brief Retrieve the attributes for the given "slot" in the AttrNode list. 231 /// \p Slot is an index into the AttrNodes list, not the index of the return / 232 /// parameter/ function which the attributes apply to. 233 AttributeSet getSlotAttributes(unsigned Slot) const { 234 return AttributeSet::get(Context, *getNode(Slot)); 235 } 236 237 /// \brief Retrieve the attribute set node for the given "slot" in the 238 /// AttrNode list. 239 AttributeSetNode *getSlotNode(unsigned Slot) const { 240 return getNode(Slot)->second; 241 } 242 243 /// \brief Return true if the AttributeSetNode for the FunctionIndex has an 244 /// enum attribute of the given kind. 245 bool hasFnAttribute(Attribute::AttrKind Kind) const { 246 return AvailableFunctionAttrs & ((uint64_t)1) << Kind; 247 } 248 249 typedef AttributeSetNode::iterator iterator; 250 iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); } 251 iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); } 252 253 void Profile(FoldingSetNodeID &ID) const { 254 Profile(ID, makeArrayRef(getNode(0), getNumSlots())); 255 } 256 static void Profile(FoldingSetNodeID &ID, 257 ArrayRef<std::pair<unsigned, AttributeSetNode*>> Nodes) { 258 for (const auto &Node : Nodes) { 259 ID.AddInteger(Node.first); 260 ID.AddPointer(Node.second); 261 } 262 } 263 264 void dump() const; 265 }; 266 267 } // end namespace llvm 268 269 #endif // LLVM_LIB_IR_ATTRIBUTEIMPL_H 270