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
16249259Sdim#ifndef LLVM_ATTRIBUTESIMPL_H
17249259Sdim#define LLVM_ATTRIBUTESIMPL_H
18249259Sdim
19249259Sdim#include "llvm/ADT/FoldingSet.h"
20249259Sdim#include "llvm/IR/Attributes.h"
21249259Sdim#include <string>
22249259Sdim
23249259Sdimnamespace llvm {
24249259Sdim
25249259Sdimclass Constant;
26249259Sdimclass LLVMContext;
27249259Sdim
28249259Sdim//===----------------------------------------------------------------------===//
29249259Sdim/// \class
30263508Sdim/// \brief This class represents a single, uniqued attribute. That attribute
31263508Sdim/// could be a single enum, a tuple, or a string.
32263508Sdimclass AttributeImpl : public FoldingSetNode {
33263508Sdim  unsigned char KindID; ///< Holds the AttrEntryKind of the attribute
34263508Sdim
35263508Sdim  // AttributesImpl is uniqued, these should not be publicly available.
36263508Sdim  void operator=(const AttributeImpl &) LLVM_DELETED_FUNCTION;
37263508Sdim  AttributeImpl(const AttributeImpl &) LLVM_DELETED_FUNCTION;
38263508Sdim
39249259Sdimprotected:
40249259Sdim  enum AttrEntryKind {
41249259Sdim    EnumAttrEntry,
42249259Sdim    AlignAttrEntry,
43249259Sdim    StringAttrEntry
44249259Sdim  };
45249259Sdim
46263508Sdim  AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {}
47249259Sdim
48249259Sdimpublic:
49263508Sdim  virtual ~AttributeImpl();
50249259Sdim
51263508Sdim  bool isEnumAttribute() const { return KindID == EnumAttrEntry; }
52263508Sdim  bool isAlignAttribute() const { return KindID == AlignAttrEntry; }
53263508Sdim  bool isStringAttribute() const { return KindID == StringAttrEntry; }
54249259Sdim
55249259Sdim  bool hasAttribute(Attribute::AttrKind A) const;
56249259Sdim  bool hasAttribute(StringRef Kind) const;
57249259Sdim
58249259Sdim  Attribute::AttrKind getKindAsEnum() const;
59249259Sdim  uint64_t getValueAsInt() const;
60249259Sdim
61249259Sdim  StringRef getKindAsString() const;
62249259Sdim  StringRef getValueAsString() const;
63249259Sdim
64249259Sdim  /// \brief Used when sorting the attributes.
65249259Sdim  bool operator<(const AttributeImpl &AI) const;
66249259Sdim
67249259Sdim  void Profile(FoldingSetNodeID &ID) const {
68249259Sdim    if (isEnumAttribute())
69249259Sdim      Profile(ID, getKindAsEnum(), 0);
70249259Sdim    else if (isAlignAttribute())
71249259Sdim      Profile(ID, getKindAsEnum(), getValueAsInt());
72249259Sdim    else
73249259Sdim      Profile(ID, getKindAsString(), getValueAsString());
74249259Sdim  }
75249259Sdim  static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
76249259Sdim                      uint64_t Val) {
77249259Sdim    ID.AddInteger(Kind);
78249259Sdim    if (Val) ID.AddInteger(Val);
79249259Sdim  }
80249259Sdim  static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) {
81249259Sdim    ID.AddString(Kind);
82249259Sdim    if (!Values.empty()) ID.AddString(Values);
83249259Sdim  }
84249259Sdim
85249259Sdim  // FIXME: Remove this!
86249259Sdim  static uint64_t getAttrMask(Attribute::AttrKind Val);
87249259Sdim};
88249259Sdim
89249259Sdim//===----------------------------------------------------------------------===//
90249259Sdim/// \class
91263508Sdim/// \brief A set of classes that contain the value of the
92263508Sdim/// attribute object. There are three main categories: enum attribute entries,
93263508Sdim/// represented by Attribute::AttrKind; alignment attribute entries; and string
94263508Sdim/// attribute enties, which are for target-dependent attributes.
95263508Sdim
96263508Sdimclass EnumAttributeImpl : public AttributeImpl {
97263508Sdim  virtual void anchor();
98263508Sdim  Attribute::AttrKind Kind;
99263508Sdim
100263508Sdimprotected:
101263508Sdim  EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind)
102263508Sdim      : AttributeImpl(ID), Kind(Kind) {}
103263508Sdim
104263508Sdimpublic:
105263508Sdim  EnumAttributeImpl(Attribute::AttrKind Kind)
106263508Sdim      : AttributeImpl(EnumAttrEntry), Kind(Kind) {}
107263508Sdim
108263508Sdim  Attribute::AttrKind getEnumKind() const { return Kind; }
109263508Sdim};
110263508Sdim
111263508Sdimclass AlignAttributeImpl : public EnumAttributeImpl {
112263508Sdim  virtual void anchor();
113263508Sdim  unsigned Align;
114263508Sdim
115263508Sdimpublic:
116263508Sdim  AlignAttributeImpl(Attribute::AttrKind Kind, unsigned Align)
117263508Sdim      : EnumAttributeImpl(AlignAttrEntry, Kind), Align(Align) {
118263508Sdim    assert(
119263508Sdim        (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) &&
120263508Sdim        "Wrong kind for alignment attribute!");
121263508Sdim  }
122263508Sdim
123263508Sdim  unsigned getAlignment() const { return Align; }
124263508Sdim};
125263508Sdim
126263508Sdimclass StringAttributeImpl : public AttributeImpl {
127263508Sdim  virtual void anchor();
128263508Sdim  std::string Kind;
129263508Sdim  std::string Val;
130263508Sdim
131263508Sdimpublic:
132263508Sdim  StringAttributeImpl(StringRef Kind, StringRef Val = StringRef())
133263508Sdim      : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {}
134263508Sdim
135263508Sdim  StringRef getStringKind() const { return Kind; }
136263508Sdim  StringRef getStringValue() const { return Val; }
137263508Sdim};
138263508Sdim
139263508Sdim//===----------------------------------------------------------------------===//
140263508Sdim/// \class
141249259Sdim/// \brief This class represents a group of attributes that apply to one
142249259Sdim/// element: function, return type, or parameter.
143249259Sdimclass AttributeSetNode : public FoldingSetNode {
144263508Sdim  unsigned NumAttrs; ///< Number of attributes in this node.
145249259Sdim
146263508Sdim  AttributeSetNode(ArrayRef<Attribute> Attrs) : NumAttrs(Attrs.size()) {
147263508Sdim    // There's memory after the node where we can store the entries in.
148263508Sdim    std::copy(Attrs.begin(), Attrs.end(),
149263508Sdim              reinterpret_cast<Attribute *>(this + 1));
150263508Sdim  }
151249259Sdim
152249259Sdim  // AttributesSetNode is uniqued, these should not be publicly available.
153249259Sdim  void operator=(const AttributeSetNode &) LLVM_DELETED_FUNCTION;
154249259Sdim  AttributeSetNode(const AttributeSetNode &) LLVM_DELETED_FUNCTION;
155249259Sdimpublic:
156249259Sdim  static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
157249259Sdim
158249259Sdim  bool hasAttribute(Attribute::AttrKind Kind) const;
159249259Sdim  bool hasAttribute(StringRef Kind) const;
160263508Sdim  bool hasAttributes() const { return NumAttrs != 0; }
161249259Sdim
162249259Sdim  Attribute getAttribute(Attribute::AttrKind Kind) const;
163249259Sdim  Attribute getAttribute(StringRef Kind) const;
164249259Sdim
165249259Sdim  unsigned getAlignment() const;
166249259Sdim  unsigned getStackAlignment() const;
167249259Sdim  std::string getAsString(bool InAttrGrp) const;
168249259Sdim
169263508Sdim  typedef const Attribute *iterator;
170263508Sdim  iterator begin() const { return reinterpret_cast<iterator>(this + 1); }
171263508Sdim  iterator end() const { return begin() + NumAttrs; }
172249259Sdim
173249259Sdim  void Profile(FoldingSetNodeID &ID) const {
174263508Sdim    Profile(ID, makeArrayRef(begin(), end()));
175249259Sdim  }
176249259Sdim  static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {
177249259Sdim    for (unsigned I = 0, E = AttrList.size(); I != E; ++I)
178249259Sdim      AttrList[I].Profile(ID);
179249259Sdim  }
180249259Sdim};
181249259Sdim
182249259Sdim//===----------------------------------------------------------------------===//
183249259Sdim/// \class
184249259Sdim/// \brief This class represents a set of attributes that apply to the function,
185249259Sdim/// return type, and parameters.
186249259Sdimclass AttributeSetImpl : public FoldingSetNode {
187249259Sdim  friend class AttributeSet;
188249259Sdim
189249259Sdim  LLVMContext &Context;
190249259Sdim
191249259Sdim  typedef std::pair<unsigned, AttributeSetNode*> IndexAttrPair;
192263508Sdim  unsigned NumAttrs; ///< Number of entries in this set.
193249259Sdim
194263508Sdim  /// \brief Return a pointer to the IndexAttrPair for the specified slot.
195263508Sdim  const IndexAttrPair *getNode(unsigned Slot) const {
196263508Sdim    return reinterpret_cast<const IndexAttrPair *>(this + 1) + Slot;
197263508Sdim  }
198263508Sdim
199249259Sdim  // AttributesSet is uniqued, these should not be publicly available.
200249259Sdim  void operator=(const AttributeSetImpl &) LLVM_DELETED_FUNCTION;
201249259Sdim  AttributeSetImpl(const AttributeSetImpl &) LLVM_DELETED_FUNCTION;
202249259Sdimpublic:
203249259Sdim  AttributeSetImpl(LLVMContext &C,
204263508Sdim                   ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
205263508Sdim      : Context(C), NumAttrs(Attrs.size()) {
206263508Sdim#ifndef NDEBUG
207263508Sdim    if (Attrs.size() >= 2) {
208263508Sdim      for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1,
209263508Sdim                                                         *e = Attrs.end();
210263508Sdim           i != e; ++i) {
211263508Sdim        assert((i-1)->first <= i->first && "Attribute set not ordered!");
212263508Sdim      }
213263508Sdim    }
214263508Sdim#endif
215263508Sdim    // There's memory after the node where we can store the entries in.
216263508Sdim    std::copy(Attrs.begin(), Attrs.end(),
217263508Sdim              reinterpret_cast<IndexAttrPair *>(this + 1));
218263508Sdim  }
219249259Sdim
220249259Sdim  /// \brief Get the context that created this AttributeSetImpl.
221249259Sdim  LLVMContext &getContext() { return Context; }
222249259Sdim
223249259Sdim  /// \brief Return the number of attributes this AttributeSet contains.
224263508Sdim  unsigned getNumAttributes() const { return NumAttrs; }
225249259Sdim
226249259Sdim  /// \brief Get the index of the given "slot" in the AttrNodes list. This index
227249259Sdim  /// is the index of the return, parameter, or function object that the
228249259Sdim  /// attributes are applied to, not the index into the AttrNodes list where the
229249259Sdim  /// attributes reside.
230251662Sdim  unsigned getSlotIndex(unsigned Slot) const {
231263508Sdim    return getNode(Slot)->first;
232249259Sdim  }
233249259Sdim
234249259Sdim  /// \brief Retrieve the attributes for the given "slot" in the AttrNode list.
235249259Sdim  /// \p Slot is an index into the AttrNodes list, not the index of the return /
236249259Sdim  /// parameter/ function which the attributes apply to.
237249259Sdim  AttributeSet getSlotAttributes(unsigned Slot) const {
238263508Sdim    return AttributeSet::get(Context, *getNode(Slot));
239249259Sdim  }
240249259Sdim
241249259Sdim  /// \brief Retrieve the attribute set node for the given "slot" in the
242249259Sdim  /// AttrNode list.
243249259Sdim  AttributeSetNode *getSlotNode(unsigned Slot) const {
244263508Sdim    return getNode(Slot)->second;
245249259Sdim  }
246249259Sdim
247263508Sdim  typedef AttributeSetNode::iterator iterator;
248263508Sdim  iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); }
249263508Sdim  iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); }
250249259Sdim
251249259Sdim  void Profile(FoldingSetNodeID &ID) const {
252263508Sdim    Profile(ID, makeArrayRef(getNode(0), getNumAttributes()));
253249259Sdim  }
254249259Sdim  static void Profile(FoldingSetNodeID &ID,
255249259Sdim                      ArrayRef<std::pair<unsigned, AttributeSetNode*> > Nodes) {
256249259Sdim    for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
257249259Sdim      ID.AddInteger(Nodes[i].first);
258249259Sdim      ID.AddPointer(Nodes[i].second);
259249259Sdim    }
260249259Sdim  }
261249259Sdim
262249259Sdim  // FIXME: This atrocity is temporary.
263251662Sdim  uint64_t Raw(unsigned Index) const;
264263508Sdim
265263508Sdim  void dump() const;
266249259Sdim};
267249259Sdim
268249259Sdim} // end llvm namespace
269249259Sdim
270249259Sdim#endif
271