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/FoldingSet.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/IR/Attributes.h" 22 #include "llvm/Support/TrailingObjects.h" 23 #include <cassert> 24 #include <cstddef> 25 #include <cstdint> 26 #include <string> 27 #include <utility> 28 29 namespace llvm { 30 31 class LLVMContext; 32 class Type; 33 34 //===----------------------------------------------------------------------===// 35 /// \class 36 /// This class represents a single, uniqued attribute. That attribute 37 /// could be a single enum, a tuple, or a string. 38 class AttributeImpl : public FoldingSetNode { 39 unsigned char KindID; ///< Holds the AttrEntryKind of the attribute 40 41 protected: 42 enum AttrEntryKind { 43 EnumAttrEntry, 44 IntAttrEntry, 45 StringAttrEntry, 46 TypeAttrEntry, 47 }; 48 AttributeImpl(AttrEntryKind KindID)49 AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} 50 51 public: 52 // AttributesImpl is uniqued, these should not be available. 53 AttributeImpl(const AttributeImpl &) = delete; 54 AttributeImpl &operator=(const AttributeImpl &) = delete; 55 56 virtual ~AttributeImpl(); 57 isEnumAttribute()58 bool isEnumAttribute() const { return KindID == EnumAttrEntry; } isIntAttribute()59 bool isIntAttribute() const { return KindID == IntAttrEntry; } isStringAttribute()60 bool isStringAttribute() const { return KindID == StringAttrEntry; } isTypeAttribute()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 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 //===----------------------------------------------------------------------===// 107 /// \class 108 /// A set of classes that contain the value of the 109 /// attribute object. There are three main categories: enum attribute entries, 110 /// represented by Attribute::AttrKind; alignment attribute entries; and string 111 /// attribute enties, which are for target-dependent attributes. 112 113 class EnumAttributeImpl : public AttributeImpl { 114 virtual void anchor(); 115 116 Attribute::AttrKind Kind; 117 118 protected: EnumAttributeImpl(AttrEntryKind ID,Attribute::AttrKind Kind)119 EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind) 120 : AttributeImpl(ID), Kind(Kind) {} 121 122 public: EnumAttributeImpl(Attribute::AttrKind Kind)123 EnumAttributeImpl(Attribute::AttrKind Kind) 124 : AttributeImpl(EnumAttrEntry), Kind(Kind) {} 125 getEnumKind()126 Attribute::AttrKind getEnumKind() const { return Kind; } 127 }; 128 129 class IntAttributeImpl : public EnumAttributeImpl { 130 uint64_t Val; 131 132 void anchor() override; 133 134 public: IntAttributeImpl(Attribute::AttrKind Kind,uint64_t Val)135 IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) 136 : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { 137 assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment || 138 Kind == Attribute::Dereferenceable || 139 Kind == Attribute::DereferenceableOrNull || 140 Kind == Attribute::AllocSize) && 141 "Wrong kind for int attribute!"); 142 } 143 getValue()144 uint64_t getValue() const { return Val; } 145 }; 146 147 class StringAttributeImpl : public AttributeImpl { 148 virtual void anchor(); 149 150 std::string Kind; 151 std::string Val; 152 153 public: 154 StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) AttributeImpl(StringAttrEntry)155 : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {} 156 getStringKind()157 StringRef getStringKind() const { return Kind; } getStringValue()158 StringRef getStringValue() const { return Val; } 159 }; 160 161 class TypeAttributeImpl : public EnumAttributeImpl { 162 void anchor() override; 163 164 Type *Ty; 165 166 public: TypeAttributeImpl(Attribute::AttrKind Kind,Type * Ty)167 TypeAttributeImpl(Attribute::AttrKind Kind, Type *Ty) 168 : EnumAttributeImpl(TypeAttrEntry, Kind), Ty(Ty) {} 169 getTypeValue()170 Type *getTypeValue() const { return Ty; } 171 }; 172 173 //===----------------------------------------------------------------------===// 174 /// \class 175 /// This class represents a group of attributes that apply to one 176 /// element: function, return type, or parameter. 177 class AttributeSetNode final 178 : public FoldingSetNode, 179 private TrailingObjects<AttributeSetNode, Attribute> { 180 friend TrailingObjects; 181 182 unsigned NumAttrs; ///< Number of attributes in this node. 183 /// Bitset with a bit for each available attribute Attribute::AttrKind. 184 uint8_t AvailableAttrs[12] = {}; 185 186 AttributeSetNode(ArrayRef<Attribute> Attrs); 187 188 public: 189 // AttributesSetNode is uniqued, these should not be available. 190 AttributeSetNode(const AttributeSetNode &) = delete; 191 AttributeSetNode &operator=(const AttributeSetNode &) = delete; 192 delete(void * p)193 void operator delete(void *p) { ::operator delete(p); } 194 195 static AttributeSetNode *get(LLVMContext &C, const AttrBuilder &B); 196 197 static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs); 198 199 /// Return the number of attributes this AttributeList contains. getNumAttributes()200 unsigned getNumAttributes() const { return NumAttrs; } 201 hasAttribute(Attribute::AttrKind Kind)202 bool hasAttribute(Attribute::AttrKind Kind) const { 203 return AvailableAttrs[Kind / 8] & ((uint64_t)1) << (Kind % 8); 204 } 205 bool hasAttribute(StringRef Kind) const; hasAttributes()206 bool hasAttributes() const { return NumAttrs != 0; } 207 208 Attribute getAttribute(Attribute::AttrKind Kind) const; 209 Attribute getAttribute(StringRef Kind) const; 210 211 MaybeAlign getAlignment() const; 212 MaybeAlign getStackAlignment() const; 213 uint64_t getDereferenceableBytes() const; 214 uint64_t getDereferenceableOrNullBytes() const; 215 std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const; 216 std::string getAsString(bool InAttrGrp) const; 217 Type *getByValType() const; 218 219 using iterator = const Attribute *; 220 begin()221 iterator begin() const { return getTrailingObjects<Attribute>(); } end()222 iterator end() const { return begin() + NumAttrs; } 223 Profile(FoldingSetNodeID & ID)224 void Profile(FoldingSetNodeID &ID) const { 225 Profile(ID, makeArrayRef(begin(), end())); 226 } 227 Profile(FoldingSetNodeID & ID,ArrayRef<Attribute> AttrList)228 static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) { 229 for (const auto &Attr : AttrList) 230 Attr.Profile(ID); 231 } 232 }; 233 234 using IndexAttrPair = std::pair<unsigned, AttributeSet>; 235 236 //===----------------------------------------------------------------------===// 237 /// \class 238 /// This class represents a set of attributes that apply to the function, 239 /// return type, and parameters. 240 class AttributeListImpl final 241 : public FoldingSetNode, 242 private TrailingObjects<AttributeListImpl, AttributeSet> { 243 friend class AttributeList; 244 friend TrailingObjects; 245 246 private: 247 LLVMContext &Context; 248 unsigned NumAttrSets; ///< Number of entries in this set. 249 /// Bitset with a bit for each available attribute Attribute::AttrKind. 250 uint8_t AvailableFunctionAttrs[12] = {}; 251 252 // Helper fn for TrailingObjects class. numTrailingObjects(OverloadToken<AttributeSet>)253 size_t numTrailingObjects(OverloadToken<AttributeSet>) { return NumAttrSets; } 254 255 public: 256 AttributeListImpl(LLVMContext &C, ArrayRef<AttributeSet> Sets); 257 258 // AttributesSetImpt is uniqued, these should not be available. 259 AttributeListImpl(const AttributeListImpl &) = delete; 260 AttributeListImpl &operator=(const AttributeListImpl &) = delete; 261 delete(void * p)262 void operator delete(void *p) { ::operator delete(p); } 263 264 /// Get the context that created this AttributeListImpl. getContext()265 LLVMContext &getContext() { return Context; } 266 267 /// Return true if the AttributeSet or the FunctionIndex has an 268 /// enum attribute of the given kind. hasFnAttribute(Attribute::AttrKind Kind)269 bool hasFnAttribute(Attribute::AttrKind Kind) const { 270 return AvailableFunctionAttrs[Kind / 8] & ((uint64_t)1) << (Kind % 8); 271 } 272 273 using iterator = const AttributeSet *; 274 begin()275 iterator begin() const { return getTrailingObjects<AttributeSet>(); } end()276 iterator end() const { return begin() + NumAttrSets; } 277 278 void Profile(FoldingSetNodeID &ID) const; 279 static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeSet> Nodes); 280 281 void dump() const; 282 }; 283 284 } // end namespace llvm 285 286 #endif // LLVM_LIB_IR_ATTRIBUTEIMPL_H 287