xref: /aosp_15_r20/external/llvm/lib/IR/AttributeImpl.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- AttributeImpl.h - Attribute Internals -------------------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker ///
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief This file defines various helper methods and classes used by
12*9880d681SAndroid Build Coastguard Worker /// LLVMContextImpl for creating and managing attributes.
13*9880d681SAndroid Build Coastguard Worker ///
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker 
16*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H
17*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_IR_ATTRIBUTEIMPL_H
18*9880d681SAndroid Build Coastguard Worker 
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/FoldingSet.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Optional.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Attributes.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/DataTypes.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TrailingObjects.h"
24*9880d681SAndroid Build Coastguard Worker #include <climits>
25*9880d681SAndroid Build Coastguard Worker #include <string>
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker namespace llvm {
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker class Constant;
30*9880d681SAndroid Build Coastguard Worker class LLVMContext;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
33*9880d681SAndroid Build Coastguard Worker /// \class
34*9880d681SAndroid Build Coastguard Worker /// \brief This class represents a single, uniqued attribute. That attribute
35*9880d681SAndroid Build Coastguard Worker /// could be a single enum, a tuple, or a string.
36*9880d681SAndroid Build Coastguard Worker class AttributeImpl : public FoldingSetNode {
37*9880d681SAndroid Build Coastguard Worker   unsigned char KindID; ///< Holds the AttrEntryKind of the attribute
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker   // AttributesImpl is uniqued, these should not be publicly available.
40*9880d681SAndroid Build Coastguard Worker   void operator=(const AttributeImpl &) = delete;
41*9880d681SAndroid Build Coastguard Worker   AttributeImpl(const AttributeImpl &) = delete;
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker protected:
44*9880d681SAndroid Build Coastguard Worker   enum AttrEntryKind {
45*9880d681SAndroid Build Coastguard Worker     EnumAttrEntry,
46*9880d681SAndroid Build Coastguard Worker     IntAttrEntry,
47*9880d681SAndroid Build Coastguard Worker     StringAttrEntry
48*9880d681SAndroid Build Coastguard Worker   };
49*9880d681SAndroid Build Coastguard Worker 
AttributeImpl(AttrEntryKind KindID)50*9880d681SAndroid Build Coastguard Worker   AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {}
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker public:
53*9880d681SAndroid Build Coastguard Worker   virtual ~AttributeImpl();
54*9880d681SAndroid Build Coastguard Worker 
isEnumAttribute()55*9880d681SAndroid Build Coastguard Worker   bool isEnumAttribute() const { return KindID == EnumAttrEntry; }
isIntAttribute()56*9880d681SAndroid Build Coastguard Worker   bool isIntAttribute() const { return KindID == IntAttrEntry; }
isStringAttribute()57*9880d681SAndroid Build Coastguard Worker   bool isStringAttribute() const { return KindID == StringAttrEntry; }
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker   bool hasAttribute(Attribute::AttrKind A) const;
60*9880d681SAndroid Build Coastguard Worker   bool hasAttribute(StringRef Kind) const;
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker   Attribute::AttrKind getKindAsEnum() const;
63*9880d681SAndroid Build Coastguard Worker   uint64_t getValueAsInt() const;
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   StringRef getKindAsString() const;
66*9880d681SAndroid Build Coastguard Worker   StringRef getValueAsString() const;
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   /// \brief Used when sorting the attributes.
69*9880d681SAndroid Build Coastguard Worker   bool operator<(const AttributeImpl &AI) const;
70*9880d681SAndroid Build Coastguard Worker 
Profile(FoldingSetNodeID & ID)71*9880d681SAndroid Build Coastguard Worker   void Profile(FoldingSetNodeID &ID) const {
72*9880d681SAndroid Build Coastguard Worker     if (isEnumAttribute())
73*9880d681SAndroid Build Coastguard Worker       Profile(ID, getKindAsEnum(), 0);
74*9880d681SAndroid Build Coastguard Worker     else if (isIntAttribute())
75*9880d681SAndroid Build Coastguard Worker       Profile(ID, getKindAsEnum(), getValueAsInt());
76*9880d681SAndroid Build Coastguard Worker     else
77*9880d681SAndroid Build Coastguard Worker       Profile(ID, getKindAsString(), getValueAsString());
78*9880d681SAndroid Build Coastguard Worker   }
Profile(FoldingSetNodeID & ID,Attribute::AttrKind Kind,uint64_t Val)79*9880d681SAndroid Build Coastguard Worker   static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
80*9880d681SAndroid Build Coastguard Worker                       uint64_t Val) {
81*9880d681SAndroid Build Coastguard Worker     ID.AddInteger(Kind);
82*9880d681SAndroid Build Coastguard Worker     if (Val) ID.AddInteger(Val);
83*9880d681SAndroid Build Coastguard Worker   }
Profile(FoldingSetNodeID & ID,StringRef Kind,StringRef Values)84*9880d681SAndroid Build Coastguard Worker   static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) {
85*9880d681SAndroid Build Coastguard Worker     ID.AddString(Kind);
86*9880d681SAndroid Build Coastguard Worker     if (!Values.empty()) ID.AddString(Values);
87*9880d681SAndroid Build Coastguard Worker   }
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   // FIXME: Remove this!
90*9880d681SAndroid Build Coastguard Worker   static uint64_t getAttrMask(Attribute::AttrKind Val);
91*9880d681SAndroid Build Coastguard Worker };
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
94*9880d681SAndroid Build Coastguard Worker /// \class
95*9880d681SAndroid Build Coastguard Worker /// \brief A set of classes that contain the value of the
96*9880d681SAndroid Build Coastguard Worker /// attribute object. There are three main categories: enum attribute entries,
97*9880d681SAndroid Build Coastguard Worker /// represented by Attribute::AttrKind; alignment attribute entries; and string
98*9880d681SAndroid Build Coastguard Worker /// attribute enties, which are for target-dependent attributes.
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker class EnumAttributeImpl : public AttributeImpl {
101*9880d681SAndroid Build Coastguard Worker   virtual void anchor();
102*9880d681SAndroid Build Coastguard Worker   Attribute::AttrKind Kind;
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker protected:
EnumAttributeImpl(AttrEntryKind ID,Attribute::AttrKind Kind)105*9880d681SAndroid Build Coastguard Worker   EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind)
106*9880d681SAndroid Build Coastguard Worker       : AttributeImpl(ID), Kind(Kind) {}
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker public:
EnumAttributeImpl(Attribute::AttrKind Kind)109*9880d681SAndroid Build Coastguard Worker   EnumAttributeImpl(Attribute::AttrKind Kind)
110*9880d681SAndroid Build Coastguard Worker       : AttributeImpl(EnumAttrEntry), Kind(Kind) {}
111*9880d681SAndroid Build Coastguard Worker 
getEnumKind()112*9880d681SAndroid Build Coastguard Worker   Attribute::AttrKind getEnumKind() const { return Kind; }
113*9880d681SAndroid Build Coastguard Worker };
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker class IntAttributeImpl : public EnumAttributeImpl {
116*9880d681SAndroid Build Coastguard Worker   void anchor() override;
117*9880d681SAndroid Build Coastguard Worker   uint64_t Val;
118*9880d681SAndroid Build Coastguard Worker 
119*9880d681SAndroid Build Coastguard Worker public:
IntAttributeImpl(Attribute::AttrKind Kind,uint64_t Val)120*9880d681SAndroid Build Coastguard Worker   IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val)
121*9880d681SAndroid Build Coastguard Worker       : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) {
122*9880d681SAndroid Build Coastguard Worker     assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment ||
123*9880d681SAndroid Build Coastguard Worker             Kind == Attribute::Dereferenceable ||
124*9880d681SAndroid Build Coastguard Worker             Kind == Attribute::DereferenceableOrNull ||
125*9880d681SAndroid Build Coastguard Worker             Kind == Attribute::AllocSize) &&
126*9880d681SAndroid Build Coastguard Worker            "Wrong kind for int attribute!");
127*9880d681SAndroid Build Coastguard Worker   }
128*9880d681SAndroid Build Coastguard Worker 
getValue()129*9880d681SAndroid Build Coastguard Worker   uint64_t getValue() const { return Val; }
130*9880d681SAndroid Build Coastguard Worker };
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker class StringAttributeImpl : public AttributeImpl {
133*9880d681SAndroid Build Coastguard Worker   virtual void anchor();
134*9880d681SAndroid Build Coastguard Worker   std::string Kind;
135*9880d681SAndroid Build Coastguard Worker   std::string Val;
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker public:
138*9880d681SAndroid Build Coastguard Worker   StringAttributeImpl(StringRef Kind, StringRef Val = StringRef())
AttributeImpl(StringAttrEntry)139*9880d681SAndroid Build Coastguard Worker       : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {}
140*9880d681SAndroid Build Coastguard Worker 
getStringKind()141*9880d681SAndroid Build Coastguard Worker   StringRef getStringKind() const { return Kind; }
getStringValue()142*9880d681SAndroid Build Coastguard Worker   StringRef getStringValue() const { return Val; }
143*9880d681SAndroid Build Coastguard Worker };
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
146*9880d681SAndroid Build Coastguard Worker /// \class
147*9880d681SAndroid Build Coastguard Worker /// \brief This class represents a group of attributes that apply to one
148*9880d681SAndroid Build Coastguard Worker /// element: function, return type, or parameter.
149*9880d681SAndroid Build Coastguard Worker class AttributeSetNode final
150*9880d681SAndroid Build Coastguard Worker     : public FoldingSetNode,
151*9880d681SAndroid Build Coastguard Worker       private TrailingObjects<AttributeSetNode, Attribute> {
152*9880d681SAndroid Build Coastguard Worker   friend TrailingObjects;
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker   unsigned NumAttrs; ///< Number of attributes in this node.
155*9880d681SAndroid Build Coastguard Worker   /// Bitset with a bit for each available attribute Attribute::AttrKind.
156*9880d681SAndroid Build Coastguard Worker   uint64_t AvailableAttrs;
157*9880d681SAndroid Build Coastguard Worker 
AttributeSetNode(ArrayRef<Attribute> Attrs)158*9880d681SAndroid Build Coastguard Worker   AttributeSetNode(ArrayRef<Attribute> Attrs)
159*9880d681SAndroid Build Coastguard Worker     : NumAttrs(Attrs.size()), AvailableAttrs(0) {
160*9880d681SAndroid Build Coastguard Worker     static_assert(Attribute::EndAttrKinds <= sizeof(AvailableAttrs) * CHAR_BIT,
161*9880d681SAndroid Build Coastguard Worker                   "Too many attributes for AvailableAttrs");
162*9880d681SAndroid Build Coastguard Worker     // There's memory after the node where we can store the entries in.
163*9880d681SAndroid Build Coastguard Worker     std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>());
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker     for (Attribute I : *this) {
166*9880d681SAndroid Build Coastguard Worker       if (!I.isStringAttribute()) {
167*9880d681SAndroid Build Coastguard Worker         AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
168*9880d681SAndroid Build Coastguard Worker       }
169*9880d681SAndroid Build Coastguard Worker     }
170*9880d681SAndroid Build Coastguard Worker   }
171*9880d681SAndroid Build Coastguard Worker 
172*9880d681SAndroid Build Coastguard Worker   // AttributesSetNode is uniqued, these should not be publicly available.
173*9880d681SAndroid Build Coastguard Worker   void operator=(const AttributeSetNode &) = delete;
174*9880d681SAndroid Build Coastguard Worker   AttributeSetNode(const AttributeSetNode &) = delete;
175*9880d681SAndroid Build Coastguard Worker public:
delete(void * p)176*9880d681SAndroid Build Coastguard Worker   void operator delete(void *p) { ::operator delete(p); }
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker   static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
179*9880d681SAndroid Build Coastguard Worker 
180*9880d681SAndroid Build Coastguard Worker   /// \brief Return the number of attributes this AttributeSet contains.
getNumAttributes()181*9880d681SAndroid Build Coastguard Worker   unsigned getNumAttributes() const { return NumAttrs; }
182*9880d681SAndroid Build Coastguard Worker 
hasAttribute(Attribute::AttrKind Kind)183*9880d681SAndroid Build Coastguard Worker   bool hasAttribute(Attribute::AttrKind Kind) const {
184*9880d681SAndroid Build Coastguard Worker     return AvailableAttrs & ((uint64_t)1) << Kind;
185*9880d681SAndroid Build Coastguard Worker   }
186*9880d681SAndroid Build Coastguard Worker   bool hasAttribute(StringRef Kind) const;
hasAttributes()187*9880d681SAndroid Build Coastguard Worker   bool hasAttributes() const { return NumAttrs != 0; }
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker   Attribute getAttribute(Attribute::AttrKind Kind) const;
190*9880d681SAndroid Build Coastguard Worker   Attribute getAttribute(StringRef Kind) const;
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker   unsigned getAlignment() const;
193*9880d681SAndroid Build Coastguard Worker   unsigned getStackAlignment() const;
194*9880d681SAndroid Build Coastguard Worker   uint64_t getDereferenceableBytes() const;
195*9880d681SAndroid Build Coastguard Worker   uint64_t getDereferenceableOrNullBytes() const;
196*9880d681SAndroid Build Coastguard Worker   std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
197*9880d681SAndroid Build Coastguard Worker   std::string getAsString(bool InAttrGrp) const;
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker   typedef const Attribute *iterator;
begin()200*9880d681SAndroid Build Coastguard Worker   iterator begin() const { return getTrailingObjects<Attribute>(); }
end()201*9880d681SAndroid Build Coastguard Worker   iterator end() const { return begin() + NumAttrs; }
202*9880d681SAndroid Build Coastguard Worker 
Profile(FoldingSetNodeID & ID)203*9880d681SAndroid Build Coastguard Worker   void Profile(FoldingSetNodeID &ID) const {
204*9880d681SAndroid Build Coastguard Worker     Profile(ID, makeArrayRef(begin(), end()));
205*9880d681SAndroid Build Coastguard Worker   }
Profile(FoldingSetNodeID & ID,ArrayRef<Attribute> AttrList)206*9880d681SAndroid Build Coastguard Worker   static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {
207*9880d681SAndroid Build Coastguard Worker     for (unsigned I = 0, E = AttrList.size(); I != E; ++I)
208*9880d681SAndroid Build Coastguard Worker       AttrList[I].Profile(ID);
209*9880d681SAndroid Build Coastguard Worker   }
210*9880d681SAndroid Build Coastguard Worker };
211*9880d681SAndroid Build Coastguard Worker 
212*9880d681SAndroid Build Coastguard Worker typedef std::pair<unsigned, AttributeSetNode *> IndexAttrPair;
213*9880d681SAndroid Build Coastguard Worker 
214*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
215*9880d681SAndroid Build Coastguard Worker /// \class
216*9880d681SAndroid Build Coastguard Worker /// \brief This class represents a set of attributes that apply to the function,
217*9880d681SAndroid Build Coastguard Worker /// return type, and parameters.
218*9880d681SAndroid Build Coastguard Worker class AttributeSetImpl final
219*9880d681SAndroid Build Coastguard Worker     : public FoldingSetNode,
220*9880d681SAndroid Build Coastguard Worker       private TrailingObjects<AttributeSetImpl, IndexAttrPair> {
221*9880d681SAndroid Build Coastguard Worker   friend class AttributeSet;
222*9880d681SAndroid Build Coastguard Worker   friend TrailingObjects;
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker private:
225*9880d681SAndroid Build Coastguard Worker   LLVMContext &Context;
226*9880d681SAndroid Build Coastguard Worker   unsigned NumSlots; ///< Number of entries in this set.
227*9880d681SAndroid Build Coastguard Worker   /// Bitset with a bit for each available attribute Attribute::AttrKind.
228*9880d681SAndroid Build Coastguard Worker   uint64_t AvailableFunctionAttrs;
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker   // Helper fn for TrailingObjects class.
numTrailingObjects(OverloadToken<IndexAttrPair>)231*9880d681SAndroid Build Coastguard Worker   size_t numTrailingObjects(OverloadToken<IndexAttrPair>) { return NumSlots; }
232*9880d681SAndroid Build Coastguard Worker 
233*9880d681SAndroid Build Coastguard Worker   /// \brief Return a pointer to the IndexAttrPair for the specified slot.
getNode(unsigned Slot)234*9880d681SAndroid Build Coastguard Worker   const IndexAttrPair *getNode(unsigned Slot) const {
235*9880d681SAndroid Build Coastguard Worker     return getTrailingObjects<IndexAttrPair>() + Slot;
236*9880d681SAndroid Build Coastguard Worker   }
237*9880d681SAndroid Build Coastguard Worker 
238*9880d681SAndroid Build Coastguard Worker   // AttributesSet is uniqued, these should not be publicly available.
239*9880d681SAndroid Build Coastguard Worker   void operator=(const AttributeSetImpl &) = delete;
240*9880d681SAndroid Build Coastguard Worker   AttributeSetImpl(const AttributeSetImpl &) = delete;
241*9880d681SAndroid Build Coastguard Worker public:
AttributeSetImpl(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSetNode * >> Slots)242*9880d681SAndroid Build Coastguard Worker   AttributeSetImpl(LLVMContext &C,
243*9880d681SAndroid Build Coastguard Worker                    ArrayRef<std::pair<unsigned, AttributeSetNode *> > Slots)
244*9880d681SAndroid Build Coastguard Worker       : Context(C), NumSlots(Slots.size()), AvailableFunctionAttrs(0) {
245*9880d681SAndroid Build Coastguard Worker     static_assert(Attribute::EndAttrKinds <=
246*9880d681SAndroid Build Coastguard Worker                       sizeof(AvailableFunctionAttrs) * CHAR_BIT,
247*9880d681SAndroid Build Coastguard Worker                   "Too many attributes");
248*9880d681SAndroid Build Coastguard Worker 
249*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
250*9880d681SAndroid Build Coastguard Worker     if (Slots.size() >= 2) {
251*9880d681SAndroid Build Coastguard Worker       for (const std::pair<unsigned, AttributeSetNode *> *i = Slots.begin() + 1,
252*9880d681SAndroid Build Coastguard Worker                                                          *e = Slots.end();
253*9880d681SAndroid Build Coastguard Worker            i != e; ++i) {
254*9880d681SAndroid Build Coastguard Worker         assert((i-1)->first <= i->first && "Attribute set not ordered!");
255*9880d681SAndroid Build Coastguard Worker       }
256*9880d681SAndroid Build Coastguard Worker     }
257*9880d681SAndroid Build Coastguard Worker #endif
258*9880d681SAndroid Build Coastguard Worker     // There's memory after the node where we can store the entries in.
259*9880d681SAndroid Build Coastguard Worker     std::copy(Slots.begin(), Slots.end(), getTrailingObjects<IndexAttrPair>());
260*9880d681SAndroid Build Coastguard Worker 
261*9880d681SAndroid Build Coastguard Worker     // Initialize AvailableFunctionAttrs summary bitset.
262*9880d681SAndroid Build Coastguard Worker     if (NumSlots > 0) {
263*9880d681SAndroid Build Coastguard Worker       static_assert(AttributeSet::FunctionIndex == ~0u,
264*9880d681SAndroid Build Coastguard Worker                     "FunctionIndex should be biggest possible index");
265*9880d681SAndroid Build Coastguard Worker       const std::pair<unsigned, AttributeSetNode *> &Last = Slots.back();
266*9880d681SAndroid Build Coastguard Worker       if (Last.first == AttributeSet::FunctionIndex) {
267*9880d681SAndroid Build Coastguard Worker         const AttributeSetNode *Node = Last.second;
268*9880d681SAndroid Build Coastguard Worker         for (Attribute I : *Node) {
269*9880d681SAndroid Build Coastguard Worker           if (!I.isStringAttribute())
270*9880d681SAndroid Build Coastguard Worker             AvailableFunctionAttrs |= ((uint64_t)1) << I.getKindAsEnum();
271*9880d681SAndroid Build Coastguard Worker         }
272*9880d681SAndroid Build Coastguard Worker       }
273*9880d681SAndroid Build Coastguard Worker     }
274*9880d681SAndroid Build Coastguard Worker   }
275*9880d681SAndroid Build Coastguard Worker 
delete(void * p)276*9880d681SAndroid Build Coastguard Worker   void operator delete(void *p) { ::operator delete(p); }
277*9880d681SAndroid Build Coastguard Worker 
278*9880d681SAndroid Build Coastguard Worker   /// \brief Get the context that created this AttributeSetImpl.
getContext()279*9880d681SAndroid Build Coastguard Worker   LLVMContext &getContext() { return Context; }
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker   /// \brief Return the number of slots used in this attribute list. This is
282*9880d681SAndroid Build Coastguard Worker   /// the number of arguments that have an attribute set on them (including the
283*9880d681SAndroid Build Coastguard Worker   /// function itself).
getNumSlots()284*9880d681SAndroid Build Coastguard Worker   unsigned getNumSlots() const { return NumSlots; }
285*9880d681SAndroid Build Coastguard Worker 
286*9880d681SAndroid Build Coastguard Worker   /// \brief Get the index of the given "slot" in the AttrNodes list. This index
287*9880d681SAndroid Build Coastguard Worker   /// is the index of the return, parameter, or function object that the
288*9880d681SAndroid Build Coastguard Worker   /// attributes are applied to, not the index into the AttrNodes list where the
289*9880d681SAndroid Build Coastguard Worker   /// attributes reside.
getSlotIndex(unsigned Slot)290*9880d681SAndroid Build Coastguard Worker   unsigned getSlotIndex(unsigned Slot) const {
291*9880d681SAndroid Build Coastguard Worker     return getNode(Slot)->first;
292*9880d681SAndroid Build Coastguard Worker   }
293*9880d681SAndroid Build Coastguard Worker 
294*9880d681SAndroid Build Coastguard Worker   /// \brief Retrieve the attributes for the given "slot" in the AttrNode list.
295*9880d681SAndroid Build Coastguard Worker   /// \p Slot is an index into the AttrNodes list, not the index of the return /
296*9880d681SAndroid Build Coastguard Worker   /// parameter/ function which the attributes apply to.
getSlotAttributes(unsigned Slot)297*9880d681SAndroid Build Coastguard Worker   AttributeSet getSlotAttributes(unsigned Slot) const {
298*9880d681SAndroid Build Coastguard Worker     return AttributeSet::get(Context, *getNode(Slot));
299*9880d681SAndroid Build Coastguard Worker   }
300*9880d681SAndroid Build Coastguard Worker 
301*9880d681SAndroid Build Coastguard Worker   /// \brief Retrieve the attribute set node for the given "slot" in the
302*9880d681SAndroid Build Coastguard Worker   /// AttrNode list.
getSlotNode(unsigned Slot)303*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *getSlotNode(unsigned Slot) const {
304*9880d681SAndroid Build Coastguard Worker     return getNode(Slot)->second;
305*9880d681SAndroid Build Coastguard Worker   }
306*9880d681SAndroid Build Coastguard Worker 
307*9880d681SAndroid Build Coastguard Worker   /// \brief Return true if the AttributeSetNode for the FunctionIndex has an
308*9880d681SAndroid Build Coastguard Worker   /// enum attribute of the given kind.
hasFnAttribute(Attribute::AttrKind Kind)309*9880d681SAndroid Build Coastguard Worker   bool hasFnAttribute(Attribute::AttrKind Kind) const {
310*9880d681SAndroid Build Coastguard Worker     return AvailableFunctionAttrs & ((uint64_t)1) << Kind;
311*9880d681SAndroid Build Coastguard Worker   }
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker   typedef AttributeSetNode::iterator iterator;
begin(unsigned Slot)314*9880d681SAndroid Build Coastguard Worker   iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); }
end(unsigned Slot)315*9880d681SAndroid Build Coastguard Worker   iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); }
316*9880d681SAndroid Build Coastguard Worker 
Profile(FoldingSetNodeID & ID)317*9880d681SAndroid Build Coastguard Worker   void Profile(FoldingSetNodeID &ID) const {
318*9880d681SAndroid Build Coastguard Worker     Profile(ID, makeArrayRef(getNode(0), getNumSlots()));
319*9880d681SAndroid Build Coastguard Worker   }
Profile(FoldingSetNodeID & ID,ArrayRef<std::pair<unsigned,AttributeSetNode * >> Nodes)320*9880d681SAndroid Build Coastguard Worker   static void Profile(FoldingSetNodeID &ID,
321*9880d681SAndroid Build Coastguard Worker                       ArrayRef<std::pair<unsigned, AttributeSetNode*> > Nodes) {
322*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
323*9880d681SAndroid Build Coastguard Worker       ID.AddInteger(Nodes[i].first);
324*9880d681SAndroid Build Coastguard Worker       ID.AddPointer(Nodes[i].second);
325*9880d681SAndroid Build Coastguard Worker     }
326*9880d681SAndroid Build Coastguard Worker   }
327*9880d681SAndroid Build Coastguard Worker 
328*9880d681SAndroid Build Coastguard Worker   // FIXME: This atrocity is temporary.
329*9880d681SAndroid Build Coastguard Worker   uint64_t Raw(unsigned Index) const;
330*9880d681SAndroid Build Coastguard Worker 
331*9880d681SAndroid Build Coastguard Worker   void dump() const;
332*9880d681SAndroid Build Coastguard Worker };
333*9880d681SAndroid Build Coastguard Worker 
334*9880d681SAndroid Build Coastguard Worker } // end llvm namespace
335*9880d681SAndroid Build Coastguard Worker 
336*9880d681SAndroid Build Coastguard Worker #endif
337