10b57cec5SDimitry Andric //===- AttributeImpl.h - Attribute Internals --------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This file defines various helper methods and classes used by 110b57cec5SDimitry Andric /// LLVMContextImpl for creating and managing attributes. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H 160b57cec5SDimitry Andric #define LLVM_LIB_IR_ATTRIBUTEIMPL_H 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 195ffd83dbSDimitry Andric #include "llvm/ADT/DenseMap.h" 200b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h" 210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 220b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 23*0fca6ea1SDimitry Andric #include "llvm/IR/ConstantRange.h" 24*0fca6ea1SDimitry Andric #include "llvm/IR/ConstantRangeList.h" 250b57cec5SDimitry Andric #include "llvm/Support/TrailingObjects.h" 260b57cec5SDimitry Andric #include <cassert> 270b57cec5SDimitry Andric #include <cstddef> 280b57cec5SDimitry Andric #include <cstdint> 29bdd1243dSDimitry Andric #include <optional> 300b57cec5SDimitry Andric #include <string> 310b57cec5SDimitry Andric #include <utility> 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace llvm { 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric class LLVMContext; 360b57cec5SDimitry Andric class Type; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 390b57cec5SDimitry Andric /// \class 400b57cec5SDimitry Andric /// This class represents a single, uniqued attribute. That attribute 410b57cec5SDimitry Andric /// could be a single enum, a tuple, or a string. 420b57cec5SDimitry Andric class AttributeImpl : public FoldingSetNode { 430b57cec5SDimitry Andric unsigned char KindID; ///< Holds the AttrEntryKind of the attribute 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric protected: 460b57cec5SDimitry Andric enum AttrEntryKind { 470b57cec5SDimitry Andric EnumAttrEntry, 480b57cec5SDimitry Andric IntAttrEntry, 490b57cec5SDimitry Andric StringAttrEntry, 500b57cec5SDimitry Andric TypeAttrEntry, 51*0fca6ea1SDimitry Andric ConstantRangeAttrEntry, 52*0fca6ea1SDimitry Andric ConstantRangeListAttrEntry, 530b57cec5SDimitry Andric }; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric public: 580b57cec5SDimitry Andric // AttributesImpl is uniqued, these should not be available. 590b57cec5SDimitry Andric AttributeImpl(const AttributeImpl &) = delete; 600b57cec5SDimitry Andric AttributeImpl &operator=(const AttributeImpl &) = delete; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric bool isEnumAttribute() const { return KindID == EnumAttrEntry; } 630b57cec5SDimitry Andric bool isIntAttribute() const { return KindID == IntAttrEntry; } 640b57cec5SDimitry Andric bool isStringAttribute() const { return KindID == StringAttrEntry; } 650b57cec5SDimitry Andric bool isTypeAttribute() const { return KindID == TypeAttrEntry; } 66*0fca6ea1SDimitry Andric bool isConstantRangeAttribute() const { 67*0fca6ea1SDimitry Andric return KindID == ConstantRangeAttrEntry; 68*0fca6ea1SDimitry Andric } 69*0fca6ea1SDimitry Andric bool isConstantRangeListAttribute() const { 70*0fca6ea1SDimitry Andric return KindID == ConstantRangeListAttrEntry; 71*0fca6ea1SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric bool hasAttribute(Attribute::AttrKind A) const; 740b57cec5SDimitry Andric bool hasAttribute(StringRef Kind) const; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric Attribute::AttrKind getKindAsEnum() const; 770b57cec5SDimitry Andric uint64_t getValueAsInt() const; 78fe6060f1SDimitry Andric bool getValueAsBool() const; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric StringRef getKindAsString() const; 810b57cec5SDimitry Andric StringRef getValueAsString() const; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric Type *getValueAsType() const; 840b57cec5SDimitry Andric 85*0fca6ea1SDimitry Andric const ConstantRange &getValueAsConstantRange() const; 86*0fca6ea1SDimitry Andric 87*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> getValueAsConstantRangeList() const; 88*0fca6ea1SDimitry Andric 890b57cec5SDimitry Andric /// Used when sorting the attributes. 900b57cec5SDimitry Andric bool operator<(const AttributeImpl &AI) const; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric void Profile(FoldingSetNodeID &ID) const { 930b57cec5SDimitry Andric if (isEnumAttribute()) 94bdd1243dSDimitry Andric Profile(ID, getKindAsEnum()); 950b57cec5SDimitry Andric else if (isIntAttribute()) 960b57cec5SDimitry Andric Profile(ID, getKindAsEnum(), getValueAsInt()); 970b57cec5SDimitry Andric else if (isStringAttribute()) 980b57cec5SDimitry Andric Profile(ID, getKindAsString(), getValueAsString()); 99*0fca6ea1SDimitry Andric else if (isTypeAttribute()) 1000b57cec5SDimitry Andric Profile(ID, getKindAsEnum(), getValueAsType()); 101*0fca6ea1SDimitry Andric else if (isConstantRangeAttribute()) 102*0fca6ea1SDimitry Andric Profile(ID, getKindAsEnum(), getValueAsConstantRange()); 103*0fca6ea1SDimitry Andric else 104*0fca6ea1SDimitry Andric Profile(ID, getKindAsEnum(), getValueAsConstantRangeList()); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 107bdd1243dSDimitry Andric static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind) { 108bdd1243dSDimitry Andric assert(Attribute::isEnumAttrKind(Kind) && "Expected enum attribute"); 109bdd1243dSDimitry Andric ID.AddInteger(Kind); 110bdd1243dSDimitry Andric } 111bdd1243dSDimitry Andric 1120b57cec5SDimitry Andric static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 1130b57cec5SDimitry Andric uint64_t Val) { 114bdd1243dSDimitry Andric assert(Attribute::isIntAttrKind(Kind) && "Expected int attribute"); 1150b57cec5SDimitry Andric ID.AddInteger(Kind); 116bdd1243dSDimitry Andric ID.AddInteger(Val); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) { 1200b57cec5SDimitry Andric ID.AddString(Kind); 1210b57cec5SDimitry Andric if (!Values.empty()) ID.AddString(Values); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 1250b57cec5SDimitry Andric Type *Ty) { 1260b57cec5SDimitry Andric ID.AddInteger(Kind); 1270b57cec5SDimitry Andric ID.AddPointer(Ty); 1280b57cec5SDimitry Andric } 129*0fca6ea1SDimitry Andric 130*0fca6ea1SDimitry Andric static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 131*0fca6ea1SDimitry Andric const ConstantRange &CR) { 132*0fca6ea1SDimitry Andric ID.AddInteger(Kind); 133*0fca6ea1SDimitry Andric CR.getLower().Profile(ID); 134*0fca6ea1SDimitry Andric CR.getUpper().Profile(ID); 135*0fca6ea1SDimitry Andric } 136*0fca6ea1SDimitry Andric 137*0fca6ea1SDimitry Andric static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 138*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> Val) { 139*0fca6ea1SDimitry Andric ID.AddInteger(Kind); 140*0fca6ea1SDimitry Andric ID.AddInteger(Val.size()); 141*0fca6ea1SDimitry Andric for (auto &CR : Val) { 142*0fca6ea1SDimitry Andric CR.getLower().Profile(ID); 143*0fca6ea1SDimitry Andric CR.getUpper().Profile(ID); 144*0fca6ea1SDimitry Andric } 145*0fca6ea1SDimitry Andric } 1460b57cec5SDimitry Andric }; 1470b57cec5SDimitry Andric 1485ffd83dbSDimitry Andric static_assert(std::is_trivially_destructible<AttributeImpl>::value, 1495ffd83dbSDimitry Andric "AttributeImpl should be trivially destructible"); 1505ffd83dbSDimitry Andric 1510b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1520b57cec5SDimitry Andric /// \class 1530b57cec5SDimitry Andric /// A set of classes that contain the value of the 1540b57cec5SDimitry Andric /// attribute object. There are three main categories: enum attribute entries, 1550b57cec5SDimitry Andric /// represented by Attribute::AttrKind; alignment attribute entries; and string 1560b57cec5SDimitry Andric /// attribute enties, which are for target-dependent attributes. 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric class EnumAttributeImpl : public AttributeImpl { 1590b57cec5SDimitry Andric Attribute::AttrKind Kind; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric protected: 1620b57cec5SDimitry Andric EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind) 1630b57cec5SDimitry Andric : AttributeImpl(ID), Kind(Kind) {} 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric public: 1660b57cec5SDimitry Andric EnumAttributeImpl(Attribute::AttrKind Kind) 167e8d8bef9SDimitry Andric : AttributeImpl(EnumAttrEntry), Kind(Kind) { 168e8d8bef9SDimitry Andric assert(Kind != Attribute::AttrKind::None && 169e8d8bef9SDimitry Andric "Can't create a None attribute!"); 170e8d8bef9SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric Attribute::AttrKind getEnumKind() const { return Kind; } 1730b57cec5SDimitry Andric }; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric class IntAttributeImpl : public EnumAttributeImpl { 1760b57cec5SDimitry Andric uint64_t Val; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric public: 1790b57cec5SDimitry Andric IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) 1800b57cec5SDimitry Andric : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { 181fe6060f1SDimitry Andric assert(Attribute::isIntAttrKind(Kind) && 1820b57cec5SDimitry Andric "Wrong kind for int attribute!"); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric uint64_t getValue() const { return Val; } 1860b57cec5SDimitry Andric }; 1870b57cec5SDimitry Andric 1885ffd83dbSDimitry Andric class StringAttributeImpl final 1895ffd83dbSDimitry Andric : public AttributeImpl, 1905ffd83dbSDimitry Andric private TrailingObjects<StringAttributeImpl, char> { 1915ffd83dbSDimitry Andric friend TrailingObjects; 1920b57cec5SDimitry Andric 1935ffd83dbSDimitry Andric unsigned KindSize; 1945ffd83dbSDimitry Andric unsigned ValSize; 1955ffd83dbSDimitry Andric size_t numTrailingObjects(OverloadToken<char>) const { 1965ffd83dbSDimitry Andric return KindSize + 1 + ValSize + 1; 1975ffd83dbSDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric public: 2000b57cec5SDimitry Andric StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) 2015ffd83dbSDimitry Andric : AttributeImpl(StringAttrEntry), KindSize(Kind.size()), 2025ffd83dbSDimitry Andric ValSize(Val.size()) { 2035ffd83dbSDimitry Andric char *TrailingString = getTrailingObjects<char>(); 2045ffd83dbSDimitry Andric // Some users rely on zero-termination. 2055ffd83dbSDimitry Andric llvm::copy(Kind, TrailingString); 2065ffd83dbSDimitry Andric TrailingString[KindSize] = '\0'; 2075ffd83dbSDimitry Andric llvm::copy(Val, &TrailingString[KindSize + 1]); 2085ffd83dbSDimitry Andric TrailingString[KindSize + 1 + ValSize] = '\0'; 2095ffd83dbSDimitry Andric } 2100b57cec5SDimitry Andric 2115ffd83dbSDimitry Andric StringRef getStringKind() const { 2125ffd83dbSDimitry Andric return StringRef(getTrailingObjects<char>(), KindSize); 2135ffd83dbSDimitry Andric } 2145ffd83dbSDimitry Andric StringRef getStringValue() const { 2155ffd83dbSDimitry Andric return StringRef(getTrailingObjects<char>() + KindSize + 1, ValSize); 2165ffd83dbSDimitry Andric } 2175ffd83dbSDimitry Andric 2185ffd83dbSDimitry Andric static size_t totalSizeToAlloc(StringRef Kind, StringRef Val) { 2195ffd83dbSDimitry Andric return TrailingObjects::totalSizeToAlloc<char>(Kind.size() + 1 + 2205ffd83dbSDimitry Andric Val.size() + 1); 2215ffd83dbSDimitry Andric } 2220b57cec5SDimitry Andric }; 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric class TypeAttributeImpl : public EnumAttributeImpl { 2250b57cec5SDimitry Andric Type *Ty; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric public: 2280b57cec5SDimitry Andric TypeAttributeImpl(Attribute::AttrKind Kind, Type *Ty) 2290b57cec5SDimitry Andric : EnumAttributeImpl(TypeAttrEntry, Kind), Ty(Ty) {} 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric Type *getTypeValue() const { return Ty; } 2320b57cec5SDimitry Andric }; 2330b57cec5SDimitry Andric 234*0fca6ea1SDimitry Andric class ConstantRangeAttributeImpl : public EnumAttributeImpl { 235*0fca6ea1SDimitry Andric ConstantRange CR; 236*0fca6ea1SDimitry Andric 237*0fca6ea1SDimitry Andric public: 238*0fca6ea1SDimitry Andric ConstantRangeAttributeImpl(Attribute::AttrKind Kind, const ConstantRange &CR) 239*0fca6ea1SDimitry Andric : EnumAttributeImpl(ConstantRangeAttrEntry, Kind), CR(CR) {} 240*0fca6ea1SDimitry Andric 241*0fca6ea1SDimitry Andric const ConstantRange &getConstantRangeValue() const { return CR; } 242*0fca6ea1SDimitry Andric }; 243*0fca6ea1SDimitry Andric 244*0fca6ea1SDimitry Andric class ConstantRangeListAttributeImpl final 245*0fca6ea1SDimitry Andric : public EnumAttributeImpl, 246*0fca6ea1SDimitry Andric private TrailingObjects<ConstantRangeListAttributeImpl, ConstantRange> { 247*0fca6ea1SDimitry Andric friend TrailingObjects; 248*0fca6ea1SDimitry Andric 249*0fca6ea1SDimitry Andric unsigned Size; 250*0fca6ea1SDimitry Andric size_t numTrailingObjects(OverloadToken<ConstantRange>) const { return Size; } 251*0fca6ea1SDimitry Andric 252*0fca6ea1SDimitry Andric public: 253*0fca6ea1SDimitry Andric ConstantRangeListAttributeImpl(Attribute::AttrKind Kind, 254*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> Val) 255*0fca6ea1SDimitry Andric : EnumAttributeImpl(ConstantRangeListAttrEntry, Kind), Size(Val.size()) { 256*0fca6ea1SDimitry Andric assert(Size > 0); 257*0fca6ea1SDimitry Andric ConstantRange *TrailingCR = getTrailingObjects<ConstantRange>(); 258*0fca6ea1SDimitry Andric std::uninitialized_copy(Val.begin(), Val.end(), TrailingCR); 259*0fca6ea1SDimitry Andric } 260*0fca6ea1SDimitry Andric 261*0fca6ea1SDimitry Andric ~ConstantRangeListAttributeImpl() { 262*0fca6ea1SDimitry Andric ConstantRange *TrailingCR = getTrailingObjects<ConstantRange>(); 263*0fca6ea1SDimitry Andric for (unsigned I = 0; I != Size; ++I) 264*0fca6ea1SDimitry Andric TrailingCR[I].~ConstantRange(); 265*0fca6ea1SDimitry Andric } 266*0fca6ea1SDimitry Andric 267*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> getConstantRangeListValue() const { 268*0fca6ea1SDimitry Andric return ArrayRef(getTrailingObjects<ConstantRange>(), Size); 269*0fca6ea1SDimitry Andric } 270*0fca6ea1SDimitry Andric 271*0fca6ea1SDimitry Andric static size_t totalSizeToAlloc(ArrayRef<ConstantRange> Val) { 272*0fca6ea1SDimitry Andric return TrailingObjects::totalSizeToAlloc<ConstantRange>(Val.size()); 273*0fca6ea1SDimitry Andric } 274*0fca6ea1SDimitry Andric }; 275*0fca6ea1SDimitry Andric 2765ffd83dbSDimitry Andric class AttributeBitSet { 2775ffd83dbSDimitry Andric /// Bitset with a bit for each available attribute Attribute::AttrKind. 2785ffd83dbSDimitry Andric uint8_t AvailableAttrs[12] = {}; 2795ffd83dbSDimitry Andric static_assert(Attribute::EndAttrKinds <= sizeof(AvailableAttrs) * CHAR_BIT, 2805ffd83dbSDimitry Andric "Too many attributes"); 2815ffd83dbSDimitry Andric 2825ffd83dbSDimitry Andric public: 2835ffd83dbSDimitry Andric bool hasAttribute(Attribute::AttrKind Kind) const { 2845ffd83dbSDimitry Andric return AvailableAttrs[Kind / 8] & (1 << (Kind % 8)); 2855ffd83dbSDimitry Andric } 2865ffd83dbSDimitry Andric 2875ffd83dbSDimitry Andric void addAttribute(Attribute::AttrKind Kind) { 2885ffd83dbSDimitry Andric AvailableAttrs[Kind / 8] |= 1 << (Kind % 8); 2895ffd83dbSDimitry Andric } 2905ffd83dbSDimitry Andric }; 2915ffd83dbSDimitry Andric 2920b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2930b57cec5SDimitry Andric /// \class 2940b57cec5SDimitry Andric /// This class represents a group of attributes that apply to one 2950b57cec5SDimitry Andric /// element: function, return type, or parameter. 2960b57cec5SDimitry Andric class AttributeSetNode final 2970b57cec5SDimitry Andric : public FoldingSetNode, 2980b57cec5SDimitry Andric private TrailingObjects<AttributeSetNode, Attribute> { 2990b57cec5SDimitry Andric friend TrailingObjects; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric unsigned NumAttrs; ///< Number of attributes in this node. 3025ffd83dbSDimitry Andric AttributeBitSet AvailableAttrs; ///< Available enum attributes. 3035ffd83dbSDimitry Andric 3045ffd83dbSDimitry Andric DenseMap<StringRef, Attribute> StringAttrs; 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric AttributeSetNode(ArrayRef<Attribute> Attrs); 3070b57cec5SDimitry Andric 3085ffd83dbSDimitry Andric static AttributeSetNode *getSorted(LLVMContext &C, 3095ffd83dbSDimitry Andric ArrayRef<Attribute> SortedAttrs); 310bdd1243dSDimitry Andric std::optional<Attribute> findEnumAttribute(Attribute::AttrKind Kind) const; 3115ffd83dbSDimitry Andric 3120b57cec5SDimitry Andric public: 3130b57cec5SDimitry Andric // AttributesSetNode is uniqued, these should not be available. 3140b57cec5SDimitry Andric AttributeSetNode(const AttributeSetNode &) = delete; 3150b57cec5SDimitry Andric AttributeSetNode &operator=(const AttributeSetNode &) = delete; 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric void operator delete(void *p) { ::operator delete(p); } 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric static AttributeSetNode *get(LLVMContext &C, const AttrBuilder &B); 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs); 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric /// Return the number of attributes this AttributeList contains. 3240b57cec5SDimitry Andric unsigned getNumAttributes() const { return NumAttrs; } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric bool hasAttribute(Attribute::AttrKind Kind) const { 3275ffd83dbSDimitry Andric return AvailableAttrs.hasAttribute(Kind); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric bool hasAttribute(StringRef Kind) const; 3300b57cec5SDimitry Andric bool hasAttributes() const { return NumAttrs != 0; } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric Attribute getAttribute(Attribute::AttrKind Kind) const; 3330b57cec5SDimitry Andric Attribute getAttribute(StringRef Kind) const; 3340b57cec5SDimitry Andric 3358bcb0991SDimitry Andric MaybeAlign getAlignment() const; 3368bcb0991SDimitry Andric MaybeAlign getStackAlignment() const; 3370b57cec5SDimitry Andric uint64_t getDereferenceableBytes() const; 3380b57cec5SDimitry Andric uint64_t getDereferenceableOrNullBytes() const; 339bdd1243dSDimitry Andric std::optional<std::pair<unsigned, std::optional<unsigned>>> getAllocSizeArgs() 340bdd1243dSDimitry Andric const; 3410eae32dcSDimitry Andric unsigned getVScaleRangeMin() const; 342bdd1243dSDimitry Andric std::optional<unsigned> getVScaleRangeMax() const; 34381ad6265SDimitry Andric UWTableKind getUWTableKind() const; 34481ad6265SDimitry Andric AllocFnKind getAllocKind() const; 345bdd1243dSDimitry Andric MemoryEffects getMemoryEffects() const; 34606c3fb27SDimitry Andric FPClassTest getNoFPClass() const; 3470b57cec5SDimitry Andric std::string getAsString(bool InAttrGrp) const; 348fe6060f1SDimitry Andric Type *getAttributeType(Attribute::AttrKind Kind) const; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric using iterator = const Attribute *; 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric iterator begin() const { return getTrailingObjects<Attribute>(); } 3530b57cec5SDimitry Andric iterator end() const { return begin() + NumAttrs; } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric void Profile(FoldingSetNodeID &ID) const { 356bdd1243dSDimitry Andric Profile(ID, ArrayRef(begin(), end())); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) { 3600b57cec5SDimitry Andric for (const auto &Attr : AttrList) 3610b57cec5SDimitry Andric Attr.Profile(ID); 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric }; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3660b57cec5SDimitry Andric /// \class 3670b57cec5SDimitry Andric /// This class represents a set of attributes that apply to the function, 3680b57cec5SDimitry Andric /// return type, and parameters. 3690b57cec5SDimitry Andric class AttributeListImpl final 3700b57cec5SDimitry Andric : public FoldingSetNode, 3710b57cec5SDimitry Andric private TrailingObjects<AttributeListImpl, AttributeSet> { 3720b57cec5SDimitry Andric friend class AttributeList; 3730b57cec5SDimitry Andric friend TrailingObjects; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric private: 3760b57cec5SDimitry Andric unsigned NumAttrSets; ///< Number of entries in this set. 3775ffd83dbSDimitry Andric /// Available enum function attributes. 3785ffd83dbSDimitry Andric AttributeBitSet AvailableFunctionAttrs; 3795ffd83dbSDimitry Andric /// Union of enum attributes available at any index. 3805ffd83dbSDimitry Andric AttributeBitSet AvailableSomewhereAttrs; 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric // Helper fn for TrailingObjects class. 3830b57cec5SDimitry Andric size_t numTrailingObjects(OverloadToken<AttributeSet>) { return NumAttrSets; } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric public: 3865ffd83dbSDimitry Andric AttributeListImpl(ArrayRef<AttributeSet> Sets); 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric // AttributesSetImpt is uniqued, these should not be available. 3890b57cec5SDimitry Andric AttributeListImpl(const AttributeListImpl &) = delete; 3900b57cec5SDimitry Andric AttributeListImpl &operator=(const AttributeListImpl &) = delete; 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric /// Return true if the AttributeSet or the FunctionIndex has an 3930b57cec5SDimitry Andric /// enum attribute of the given kind. 3940b57cec5SDimitry Andric bool hasFnAttribute(Attribute::AttrKind Kind) const { 3955ffd83dbSDimitry Andric return AvailableFunctionAttrs.hasAttribute(Kind); 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3985ffd83dbSDimitry Andric /// Return true if the specified attribute is set for at least one 3995ffd83dbSDimitry Andric /// parameter or for the return value. If Index is not nullptr, the index 4005ffd83dbSDimitry Andric /// of a parameter with the specified attribute is provided. 4015ffd83dbSDimitry Andric bool hasAttrSomewhere(Attribute::AttrKind Kind, 4025ffd83dbSDimitry Andric unsigned *Index = nullptr) const; 4035ffd83dbSDimitry Andric 4040b57cec5SDimitry Andric using iterator = const AttributeSet *; 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric iterator begin() const { return getTrailingObjects<AttributeSet>(); } 4070b57cec5SDimitry Andric iterator end() const { return begin() + NumAttrSets; } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric void Profile(FoldingSetNodeID &ID) const; 4100b57cec5SDimitry Andric static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeSet> Nodes); 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric void dump() const; 4130b57cec5SDimitry Andric }; 4140b57cec5SDimitry Andric 4155ffd83dbSDimitry Andric static_assert(std::is_trivially_destructible<AttributeListImpl>::value, 4165ffd83dbSDimitry Andric "AttributeListImpl should be trivially destructible"); 4175ffd83dbSDimitry Andric 4180b57cec5SDimitry Andric } // end namespace llvm 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric #endif // LLVM_LIB_IR_ATTRIBUTEIMPL_H 421