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