1249259Sdim//===-- AttributeImpl.h - Attribute Internals -------------------*- C++ -*-===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim///
10249259Sdim/// \file
11249259Sdim/// \brief This file defines various helper methods and classes used by
12249259Sdim/// LLVMContextImpl for creating and managing attributes.
13249259Sdim///
14249259Sdim//===----------------------------------------------------------------------===//
15249259Sdim
16280031Sdim#ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H
17280031Sdim#define LLVM_LIB_IR_ATTRIBUTEIMPL_H
18249259Sdim
19249259Sdim#include "llvm/ADT/FoldingSet.h"
20249259Sdim#include "llvm/IR/Attributes.h"
21296417Sdim#include "llvm/Support/TrailingObjects.h"
22249259Sdim#include <string>
23249259Sdim
24249259Sdimnamespace llvm {
25249259Sdim
26249259Sdimclass Constant;
27249259Sdimclass LLVMContext;
28249259Sdim
29249259Sdim//===----------------------------------------------------------------------===//
30249259Sdim/// \class
31261991Sdim/// \brief This class represents a single, uniqued attribute. That attribute
32261991Sdim/// could be a single enum, a tuple, or a string.
33261991Sdimclass AttributeImpl : public FoldingSetNode {
34261991Sdim  unsigned char KindID; ///< Holds the AttrEntryKind of the attribute
35261991Sdim
36261991Sdim  // AttributesImpl is uniqued, these should not be publicly available.
37288943Sdim  void operator=(const AttributeImpl &) = delete;
38288943Sdim  AttributeImpl(const AttributeImpl &) = delete;
39261991Sdim
40249259Sdimprotected:
41249259Sdim  enum AttrEntryKind {
42249259Sdim    EnumAttrEntry,
43276479Sdim    IntAttrEntry,
44249259Sdim    StringAttrEntry
45249259Sdim  };
46249259Sdim
47261991Sdim  AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {}
48249259Sdim
49249259Sdimpublic:
50261991Sdim  virtual ~AttributeImpl();
51249259Sdim
52261991Sdim  bool isEnumAttribute() const { return KindID == EnumAttrEntry; }
53276479Sdim  bool isIntAttribute() const { return KindID == IntAttrEntry; }
54261991Sdim  bool isStringAttribute() const { return KindID == StringAttrEntry; }
55249259Sdim
56249259Sdim  bool hasAttribute(Attribute::AttrKind A) const;
57249259Sdim  bool hasAttribute(StringRef Kind) const;
58249259Sdim
59249259Sdim  Attribute::AttrKind getKindAsEnum() const;
60249259Sdim  uint64_t getValueAsInt() const;
61249259Sdim
62249259Sdim  StringRef getKindAsString() const;
63249259Sdim  StringRef getValueAsString() const;
64249259Sdim
65249259Sdim  /// \brief Used when sorting the attributes.
66249259Sdim  bool operator<(const AttributeImpl &AI) const;
67249259Sdim
68249259Sdim  void Profile(FoldingSetNodeID &ID) const {
69249259Sdim    if (isEnumAttribute())
70249259Sdim      Profile(ID, getKindAsEnum(), 0);
71276479Sdim    else if (isIntAttribute())
72249259Sdim      Profile(ID, getKindAsEnum(), getValueAsInt());
73249259Sdim    else
74249259Sdim      Profile(ID, getKindAsString(), getValueAsString());
75249259Sdim  }
76249259Sdim  static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
77249259Sdim                      uint64_t Val) {
78249259Sdim    ID.AddInteger(Kind);
79249259Sdim    if (Val) ID.AddInteger(Val);
80249259Sdim  }
81249259Sdim  static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) {
82249259Sdim    ID.AddString(Kind);
83249259Sdim    if (!Values.empty()) ID.AddString(Values);
84249259Sdim  }
85249259Sdim
86249259Sdim  // FIXME: Remove this!
87249259Sdim  static uint64_t getAttrMask(Attribute::AttrKind Val);
88249259Sdim};
89249259Sdim
90249259Sdim//===----------------------------------------------------------------------===//
91249259Sdim/// \class
92261991Sdim/// \brief A set of classes that contain the value of the
93261991Sdim/// attribute object. There are three main categories: enum attribute entries,
94261991Sdim/// represented by Attribute::AttrKind; alignment attribute entries; and string
95261991Sdim/// attribute enties, which are for target-dependent attributes.
96261991Sdim
97261991Sdimclass EnumAttributeImpl : public AttributeImpl {
98261991Sdim  virtual void anchor();
99261991Sdim  Attribute::AttrKind Kind;
100261991Sdim
101261991Sdimprotected:
102261991Sdim  EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind)
103261991Sdim      : AttributeImpl(ID), Kind(Kind) {}
104261991Sdim
105261991Sdimpublic:
106261991Sdim  EnumAttributeImpl(Attribute::AttrKind Kind)
107261991Sdim      : AttributeImpl(EnumAttrEntry), Kind(Kind) {}
108261991Sdim
109261991Sdim  Attribute::AttrKind getEnumKind() const { return Kind; }
110261991Sdim};
111261991Sdim
112276479Sdimclass IntAttributeImpl : public EnumAttributeImpl {
113276479Sdim  void anchor() override;
114276479Sdim  uint64_t Val;
115261991Sdim
116261991Sdimpublic:
117276479Sdim  IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val)
118276479Sdim      : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) {
119288943Sdim    assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment ||
120288943Sdim            Kind == Attribute::Dereferenceable ||
121288943Sdim            Kind == Attribute::DereferenceableOrNull) &&
122288943Sdim           "Wrong kind for int attribute!");
123261991Sdim  }
124261991Sdim
125276479Sdim  uint64_t getValue() const { return Val; }
126261991Sdim};
127261991Sdim
128261991Sdimclass StringAttributeImpl : public AttributeImpl {
129261991Sdim  virtual void anchor();
130261991Sdim  std::string Kind;
131261991Sdim  std::string Val;
132261991Sdim
133261991Sdimpublic:
134261991Sdim  StringAttributeImpl(StringRef Kind, StringRef Val = StringRef())
135261991Sdim      : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {}
136261991Sdim
137261991Sdim  StringRef getStringKind() const { return Kind; }
138261991Sdim  StringRef getStringValue() const { return Val; }
139261991Sdim};
140261991Sdim
141261991Sdim//===----------------------------------------------------------------------===//
142261991Sdim/// \class
143249259Sdim/// \brief This class represents a group of attributes that apply to one
144249259Sdim/// element: function, return type, or parameter.
145296417Sdimclass AttributeSetNode final
146296417Sdim    : public FoldingSetNode,
147296417Sdim      private TrailingObjects<AttributeSetNode, Attribute> {
148296417Sdim  friend TrailingObjects;
149296417Sdim
150261991Sdim  unsigned NumAttrs; ///< Number of attributes in this node.
151249259Sdim
152261991Sdim  AttributeSetNode(ArrayRef<Attribute> Attrs) : NumAttrs(Attrs.size()) {
153261991Sdim    // There's memory after the node where we can store the entries in.
154296417Sdim    std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>());
155261991Sdim  }
156249259Sdim
157249259Sdim  // AttributesSetNode is uniqued, these should not be publicly available.
158288943Sdim  void operator=(const AttributeSetNode &) = delete;
159288943Sdim  AttributeSetNode(const AttributeSetNode &) = delete;
160249259Sdimpublic:
161249259Sdim  static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
162249259Sdim
163249259Sdim  bool hasAttribute(Attribute::AttrKind Kind) const;
164249259Sdim  bool hasAttribute(StringRef Kind) const;
165261991Sdim  bool hasAttributes() const { return NumAttrs != 0; }
166249259Sdim
167249259Sdim  Attribute getAttribute(Attribute::AttrKind Kind) const;
168249259Sdim  Attribute getAttribute(StringRef Kind) const;
169249259Sdim
170249259Sdim  unsigned getAlignment() const;
171249259Sdim  unsigned getStackAlignment() const;
172276479Sdim  uint64_t getDereferenceableBytes() const;
173288943Sdim  uint64_t getDereferenceableOrNullBytes() const;
174249259Sdim  std::string getAsString(bool InAttrGrp) const;
175249259Sdim
176261991Sdim  typedef const Attribute *iterator;
177296417Sdim  iterator begin() const { return getTrailingObjects<Attribute>(); }
178261991Sdim  iterator end() const { return begin() + NumAttrs; }
179249259Sdim
180249259Sdim  void Profile(FoldingSetNodeID &ID) const {
181261991Sdim    Profile(ID, makeArrayRef(begin(), end()));
182249259Sdim  }
183249259Sdim  static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {
184249259Sdim    for (unsigned I = 0, E = AttrList.size(); I != E; ++I)
185249259Sdim      AttrList[I].Profile(ID);
186249259Sdim  }
187249259Sdim};
188249259Sdim
189296417Sdimtypedef std::pair<unsigned, AttributeSetNode *> IndexAttrPair;
190296417Sdim
191249259Sdim//===----------------------------------------------------------------------===//
192249259Sdim/// \class
193249259Sdim/// \brief This class represents a set of attributes that apply to the function,
194249259Sdim/// return type, and parameters.
195296417Sdimclass AttributeSetImpl final
196296417Sdim    : public FoldingSetNode,
197296417Sdim      private TrailingObjects<AttributeSetImpl, IndexAttrPair> {
198249259Sdim  friend class AttributeSet;
199296417Sdim  friend TrailingObjects;
200249259Sdim
201288943Sdimprivate:
202249259Sdim  LLVMContext &Context;
203261991Sdim  unsigned NumAttrs; ///< Number of entries in this set.
204249259Sdim
205296417Sdim  // Helper fn for TrailingObjects class.
206296417Sdim  size_t numTrailingObjects(OverloadToken<IndexAttrPair>) { return NumAttrs; }
207296417Sdim
208261991Sdim  /// \brief Return a pointer to the IndexAttrPair for the specified slot.
209261991Sdim  const IndexAttrPair *getNode(unsigned Slot) const {
210296417Sdim    return getTrailingObjects<IndexAttrPair>() + Slot;
211261991Sdim  }
212261991Sdim
213249259Sdim  // AttributesSet is uniqued, these should not be publicly available.
214288943Sdim  void operator=(const AttributeSetImpl &) = delete;
215288943Sdim  AttributeSetImpl(const AttributeSetImpl &) = delete;
216249259Sdimpublic:
217249259Sdim  AttributeSetImpl(LLVMContext &C,
218261991Sdim                   ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
219261991Sdim      : Context(C), NumAttrs(Attrs.size()) {
220288943Sdim
221261991Sdim#ifndef NDEBUG
222261991Sdim    if (Attrs.size() >= 2) {
223261991Sdim      for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1,
224261991Sdim                                                         *e = Attrs.end();
225261991Sdim           i != e; ++i) {
226261991Sdim        assert((i-1)->first <= i->first && "Attribute set not ordered!");
227261991Sdim      }
228261991Sdim    }
229261991Sdim#endif
230261991Sdim    // There's memory after the node where we can store the entries in.
231296417Sdim    std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<IndexAttrPair>());
232261991Sdim  }
233249259Sdim
234249259Sdim  /// \brief Get the context that created this AttributeSetImpl.
235249259Sdim  LLVMContext &getContext() { return Context; }
236249259Sdim
237249259Sdim  /// \brief Return the number of attributes this AttributeSet contains.
238261991Sdim  unsigned getNumAttributes() const { return NumAttrs; }
239249259Sdim
240249259Sdim  /// \brief Get the index of the given "slot" in the AttrNodes list. This index
241249259Sdim  /// is the index of the return, parameter, or function object that the
242249259Sdim  /// attributes are applied to, not the index into the AttrNodes list where the
243249259Sdim  /// attributes reside.
244251662Sdim  unsigned getSlotIndex(unsigned Slot) const {
245261991Sdim    return getNode(Slot)->first;
246249259Sdim  }
247249259Sdim
248249259Sdim  /// \brief Retrieve the attributes for the given "slot" in the AttrNode list.
249249259Sdim  /// \p Slot is an index into the AttrNodes list, not the index of the return /
250249259Sdim  /// parameter/ function which the attributes apply to.
251249259Sdim  AttributeSet getSlotAttributes(unsigned Slot) const {
252261991Sdim    return AttributeSet::get(Context, *getNode(Slot));
253249259Sdim  }
254249259Sdim
255249259Sdim  /// \brief Retrieve the attribute set node for the given "slot" in the
256249259Sdim  /// AttrNode list.
257249259Sdim  AttributeSetNode *getSlotNode(unsigned Slot) const {
258261991Sdim    return getNode(Slot)->second;
259249259Sdim  }
260249259Sdim
261261991Sdim  typedef AttributeSetNode::iterator iterator;
262261991Sdim  iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); }
263261991Sdim  iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); }
264249259Sdim
265249259Sdim  void Profile(FoldingSetNodeID &ID) const {
266261991Sdim    Profile(ID, makeArrayRef(getNode(0), getNumAttributes()));
267249259Sdim  }
268249259Sdim  static void Profile(FoldingSetNodeID &ID,
269249259Sdim                      ArrayRef<std::pair<unsigned, AttributeSetNode*> > Nodes) {
270249259Sdim    for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
271249259Sdim      ID.AddInteger(Nodes[i].first);
272249259Sdim      ID.AddPointer(Nodes[i].second);
273249259Sdim    }
274249259Sdim  }
275249259Sdim
276249259Sdim  // FIXME: This atrocity is temporary.
277251662Sdim  uint64_t Raw(unsigned Index) const;
278261991Sdim
279261991Sdim  void dump() const;
280249259Sdim};
281249259Sdim
282249259Sdim} // end llvm namespace
283249259Sdim
284249259Sdim#endif
285