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