1 //===- AttributeImpl.h - Attribute Internals --------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file defines various helper methods and classes used by 11 /// LLVMContextImpl for creating and managing attributes. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H 16 #define LLVM_LIB_IR_ATTRIBUTEIMPL_H 17 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/ADT/DenseMap.h" 20 #include "llvm/ADT/FoldingSet.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/IR/Attributes.h" 23 #include "llvm/Support/TrailingObjects.h" 24 #include <cassert> 25 #include <cstddef> 26 #include <cstdint> 27 #include <optional> 28 #include <string> 29 #include <utility> 30 31 namespace llvm { 32 33 class LLVMContext; 34 class Type; 35 36 //===----------------------------------------------------------------------===// 37 /// \class 38 /// This class represents a single, uniqued attribute. That attribute 39 /// could be a single enum, a tuple, or a string. 40 class AttributeImpl : public FoldingSetNode { 41 unsigned char KindID; ///< Holds the AttrEntryKind of the attribute 42 43 protected: 44 enum AttrEntryKind { 45 EnumAttrEntry, 46 IntAttrEntry, 47 StringAttrEntry, 48 TypeAttrEntry, 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 bool isEnumAttribute() const { return KindID == EnumAttrEntry; } 59 bool isIntAttribute() const { return KindID == IntAttrEntry; } 60 bool isStringAttribute() const { return KindID == StringAttrEntry; } 61 bool isTypeAttribute() const { return KindID == TypeAttrEntry; } 62 63 bool hasAttribute(Attribute::AttrKind A) const; 64 bool hasAttribute(StringRef Kind) const; 65 66 Attribute::AttrKind getKindAsEnum() const; 67 uint64_t getValueAsInt() const; 68 bool getValueAsBool() const; 69 70 StringRef getKindAsString() const; 71 StringRef getValueAsString() const; 72 73 Type *getValueAsType() const; 74 75 /// Used when sorting the attributes. 76 bool operator<(const AttributeImpl &AI) const; 77 78 void Profile(FoldingSetNodeID &ID) const { 79 if (isEnumAttribute()) 80 Profile(ID, getKindAsEnum()); 81 else if (isIntAttribute()) 82 Profile(ID, getKindAsEnum(), getValueAsInt()); 83 else if (isStringAttribute()) 84 Profile(ID, getKindAsString(), getValueAsString()); 85 else 86 Profile(ID, getKindAsEnum(), getValueAsType()); 87 } 88 89 static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind) { 90 assert(Attribute::isEnumAttrKind(Kind) && "Expected enum attribute"); 91 ID.AddInteger(Kind); 92 } 93 94 static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 95 uint64_t Val) { 96 assert(Attribute::isIntAttrKind(Kind) && "Expected int attribute"); 97 ID.AddInteger(Kind); 98 ID.AddInteger(Val); 99 } 100 101 static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) { 102 ID.AddString(Kind); 103 if (!Values.empty()) ID.AddString(Values); 104 } 105 106 static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 107 Type *Ty) { 108 ID.AddInteger(Kind); 109 ID.AddPointer(Ty); 110 } 111 }; 112 113 static_assert(std::is_trivially_destructible<AttributeImpl>::value, 114 "AttributeImpl should be trivially destructible"); 115 116 //===----------------------------------------------------------------------===// 117 /// \class 118 /// A set of classes that contain the value of the 119 /// attribute object. There are three main categories: enum attribute entries, 120 /// represented by Attribute::AttrKind; alignment attribute entries; and string 121 /// attribute enties, which are for target-dependent attributes. 122 123 class EnumAttributeImpl : public AttributeImpl { 124 Attribute::AttrKind Kind; 125 126 protected: 127 EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind) 128 : AttributeImpl(ID), Kind(Kind) {} 129 130 public: 131 EnumAttributeImpl(Attribute::AttrKind Kind) 132 : AttributeImpl(EnumAttrEntry), Kind(Kind) { 133 assert(Kind != Attribute::AttrKind::None && 134 "Can't create a None attribute!"); 135 } 136 137 Attribute::AttrKind getEnumKind() const { return Kind; } 138 }; 139 140 class IntAttributeImpl : public EnumAttributeImpl { 141 uint64_t Val; 142 143 public: 144 IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) 145 : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { 146 assert(Attribute::isIntAttrKind(Kind) && 147 "Wrong kind for int attribute!"); 148 } 149 150 uint64_t getValue() const { return Val; } 151 }; 152 153 class StringAttributeImpl final 154 : public AttributeImpl, 155 private TrailingObjects<StringAttributeImpl, char> { 156 friend TrailingObjects; 157 158 unsigned KindSize; 159 unsigned ValSize; 160 size_t numTrailingObjects(OverloadToken<char>) const { 161 return KindSize + 1 + ValSize + 1; 162 } 163 164 public: 165 StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) 166 : AttributeImpl(StringAttrEntry), KindSize(Kind.size()), 167 ValSize(Val.size()) { 168 char *TrailingString = getTrailingObjects<char>(); 169 // Some users rely on zero-termination. 170 llvm::copy(Kind, TrailingString); 171 TrailingString[KindSize] = '\0'; 172 llvm::copy(Val, &TrailingString[KindSize + 1]); 173 TrailingString[KindSize + 1 + ValSize] = '\0'; 174 } 175 176 StringRef getStringKind() const { 177 return StringRef(getTrailingObjects<char>(), KindSize); 178 } 179 StringRef getStringValue() const { 180 return StringRef(getTrailingObjects<char>() + KindSize + 1, ValSize); 181 } 182 183 static size_t totalSizeToAlloc(StringRef Kind, StringRef Val) { 184 return TrailingObjects::totalSizeToAlloc<char>(Kind.size() + 1 + 185 Val.size() + 1); 186 } 187 }; 188 189 class TypeAttributeImpl : public EnumAttributeImpl { 190 Type *Ty; 191 192 public: 193 TypeAttributeImpl(Attribute::AttrKind Kind, Type *Ty) 194 : EnumAttributeImpl(TypeAttrEntry, Kind), Ty(Ty) {} 195 196 Type *getTypeValue() const { return Ty; } 197 }; 198 199 class AttributeBitSet { 200 /// Bitset with a bit for each available attribute Attribute::AttrKind. 201 uint8_t AvailableAttrs[12] = {}; 202 static_assert(Attribute::EndAttrKinds <= sizeof(AvailableAttrs) * CHAR_BIT, 203 "Too many attributes"); 204 205 public: 206 bool hasAttribute(Attribute::AttrKind Kind) const { 207 return AvailableAttrs[Kind / 8] & (1 << (Kind % 8)); 208 } 209 210 void addAttribute(Attribute::AttrKind Kind) { 211 AvailableAttrs[Kind / 8] |= 1 << (Kind % 8); 212 } 213 }; 214 215 //===----------------------------------------------------------------------===// 216 /// \class 217 /// This class represents a group of attributes that apply to one 218 /// element: function, return type, or parameter. 219 class AttributeSetNode final 220 : public FoldingSetNode, 221 private TrailingObjects<AttributeSetNode, Attribute> { 222 friend TrailingObjects; 223 224 unsigned NumAttrs; ///< Number of attributes in this node. 225 AttributeBitSet AvailableAttrs; ///< Available enum attributes. 226 227 DenseMap<StringRef, Attribute> StringAttrs; 228 229 AttributeSetNode(ArrayRef<Attribute> Attrs); 230 231 static AttributeSetNode *getSorted(LLVMContext &C, 232 ArrayRef<Attribute> SortedAttrs); 233 std::optional<Attribute> findEnumAttribute(Attribute::AttrKind Kind) const; 234 235 public: 236 // AttributesSetNode is uniqued, these should not be available. 237 AttributeSetNode(const AttributeSetNode &) = delete; 238 AttributeSetNode &operator=(const AttributeSetNode &) = delete; 239 240 void operator delete(void *p) { ::operator delete(p); } 241 242 static AttributeSetNode *get(LLVMContext &C, const AttrBuilder &B); 243 244 static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs); 245 246 /// Return the number of attributes this AttributeList contains. 247 unsigned getNumAttributes() const { return NumAttrs; } 248 249 bool hasAttribute(Attribute::AttrKind Kind) const { 250 return AvailableAttrs.hasAttribute(Kind); 251 } 252 bool hasAttribute(StringRef Kind) const; 253 bool hasAttributes() const { return NumAttrs != 0; } 254 255 Attribute getAttribute(Attribute::AttrKind Kind) const; 256 Attribute getAttribute(StringRef Kind) const; 257 258 MaybeAlign getAlignment() const; 259 MaybeAlign getStackAlignment() const; 260 uint64_t getDereferenceableBytes() const; 261 uint64_t getDereferenceableOrNullBytes() const; 262 std::optional<std::pair<unsigned, std::optional<unsigned>>> getAllocSizeArgs() 263 const; 264 unsigned getVScaleRangeMin() const; 265 std::optional<unsigned> getVScaleRangeMax() const; 266 UWTableKind getUWTableKind() const; 267 AllocFnKind getAllocKind() const; 268 MemoryEffects getMemoryEffects() const; 269 FPClassTest getNoFPClass() const; 270 std::string getAsString(bool InAttrGrp) const; 271 Type *getAttributeType(Attribute::AttrKind Kind) const; 272 273 using iterator = const Attribute *; 274 275 iterator begin() const { return getTrailingObjects<Attribute>(); } 276 iterator end() const { return begin() + NumAttrs; } 277 278 void Profile(FoldingSetNodeID &ID) const { 279 Profile(ID, ArrayRef(begin(), end())); 280 } 281 282 static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) { 283 for (const auto &Attr : AttrList) 284 Attr.Profile(ID); 285 } 286 }; 287 288 //===----------------------------------------------------------------------===// 289 /// \class 290 /// This class represents a set of attributes that apply to the function, 291 /// return type, and parameters. 292 class AttributeListImpl final 293 : public FoldingSetNode, 294 private TrailingObjects<AttributeListImpl, AttributeSet> { 295 friend class AttributeList; 296 friend TrailingObjects; 297 298 private: 299 unsigned NumAttrSets; ///< Number of entries in this set. 300 /// Available enum function attributes. 301 AttributeBitSet AvailableFunctionAttrs; 302 /// Union of enum attributes available at any index. 303 AttributeBitSet AvailableSomewhereAttrs; 304 305 // Helper fn for TrailingObjects class. 306 size_t numTrailingObjects(OverloadToken<AttributeSet>) { return NumAttrSets; } 307 308 public: 309 AttributeListImpl(ArrayRef<AttributeSet> Sets); 310 311 // AttributesSetImpt is uniqued, these should not be available. 312 AttributeListImpl(const AttributeListImpl &) = delete; 313 AttributeListImpl &operator=(const AttributeListImpl &) = delete; 314 315 /// Return true if the AttributeSet or the FunctionIndex has an 316 /// enum attribute of the given kind. 317 bool hasFnAttribute(Attribute::AttrKind Kind) const { 318 return AvailableFunctionAttrs.hasAttribute(Kind); 319 } 320 321 /// Return true if the specified attribute is set for at least one 322 /// parameter or for the return value. If Index is not nullptr, the index 323 /// of a parameter with the specified attribute is provided. 324 bool hasAttrSomewhere(Attribute::AttrKind Kind, 325 unsigned *Index = nullptr) const; 326 327 using iterator = const AttributeSet *; 328 329 iterator begin() const { return getTrailingObjects<AttributeSet>(); } 330 iterator end() const { return begin() + NumAttrSets; } 331 332 void Profile(FoldingSetNodeID &ID) const; 333 static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeSet> Nodes); 334 335 void dump() const; 336 }; 337 338 static_assert(std::is_trivially_destructible<AttributeListImpl>::value, 339 "AttributeListImpl should be trivially destructible"); 340 341 } // end namespace llvm 342 343 #endif // LLVM_LIB_IR_ATTRIBUTEIMPL_H 344