xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/AttributeImpl.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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