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
30263509Sdim/// \brief This class represents a single, uniqued attribute. That attribute
31263509Sdim/// could be a single enum, a tuple, or a string.
32263509Sdimclass AttributeImpl : public FoldingSetNode {
33263509Sdim  unsigned char KindID; ///< Holds the AttrEntryKind of the attribute
34263509Sdim
35263509Sdim  // AttributesImpl is uniqued, these should not be publicly available.
36263509Sdim  void operator=(const AttributeImpl &) LLVM_DELETED_FUNCTION;
37263509Sdim  AttributeImpl(const AttributeImpl &) LLVM_DELETED_FUNCTION;
38263509Sdim
39249259Sdimprotected:
40249259Sdim  enum AttrEntryKind {
41249259Sdim    EnumAttrEntry,
42249259Sdim    AlignAttrEntry,
43249259Sdim    StringAttrEntry
44249259Sdim  };
45249259Sdim
46263509Sdim  AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {}
47249259Sdim
48249259Sdimpublic:
49263509Sdim  virtual ~AttributeImpl();
50249259Sdim
51263509Sdim  bool isEnumAttribute() const { return KindID == EnumAttrEntry; }
52263509Sdim  bool isAlignAttribute() const { return KindID == AlignAttrEntry; }
53263509Sdim  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
91263509Sdim/// \brief A set of classes that contain the value of the
92263509Sdim/// attribute object. There are three main categories: enum attribute entries,
93263509Sdim/// represented by Attribute::AttrKind; alignment attribute entries; and string
94263509Sdim/// attribute enties, which are for target-dependent attributes.
95263509Sdim
96263509Sdimclass EnumAttributeImpl : public AttributeImpl {
97263509Sdim  virtual void anchor();
98263509Sdim  Attribute::AttrKind Kind;
99263509Sdim
100263509Sdimprotected:
101263509Sdim  EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind)
102263509Sdim      : AttributeImpl(ID), Kind(Kind) {}
103263509Sdim
104263509Sdimpublic:
105263509Sdim  EnumAttributeImpl(Attribute::AttrKind Kind)
106263509Sdim      : AttributeImpl(EnumAttrEntry), Kind(Kind) {}
107263509Sdim
108263509Sdim  Attribute::AttrKind getEnumKind() const { return Kind; }
109263509Sdim};
110263509Sdim
111263509Sdimclass AlignAttributeImpl : public EnumAttributeImpl {
112263509Sdim  virtual void anchor();
113263509Sdim  unsigned Align;
114263509Sdim
115263509Sdimpublic:
116263509Sdim  AlignAttributeImpl(Attribute::AttrKind Kind, unsigned Align)
117263509Sdim      : EnumAttributeImpl(AlignAttrEntry, Kind), Align(Align) {
118263509Sdim    assert(
119263509Sdim        (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) &&
120263509Sdim        "Wrong kind for alignment attribute!");
121263509Sdim  }
122263509Sdim
123263509Sdim  unsigned getAlignment() const { return Align; }
124263509Sdim};
125263509Sdim
126263509Sdimclass StringAttributeImpl : public AttributeImpl {
127263509Sdim  virtual void anchor();
128263509Sdim  std::string Kind;
129263509Sdim  std::string Val;
130263509Sdim
131263509Sdimpublic:
132263509Sdim  StringAttributeImpl(StringRef Kind, StringRef Val = StringRef())
133263509Sdim      : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {}
134263509Sdim
135263509Sdim  StringRef getStringKind() const { return Kind; }
136263509Sdim  StringRef getStringValue() const { return Val; }
137263509Sdim};
138263509Sdim
139263509Sdim//===----------------------------------------------------------------------===//
140263509Sdim/// \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 {
144263509Sdim  unsigned NumAttrs; ///< Number of attributes in this node.
145249259Sdim
146263509Sdim  AttributeSetNode(ArrayRef<Attribute> Attrs) : NumAttrs(Attrs.size()) {
147263509Sdim    // There's memory after the node where we can store the entries in.
148263509Sdim    std::copy(Attrs.begin(), Attrs.end(),
149263509Sdim              reinterpret_cast<Attribute *>(this + 1));
150263509Sdim  }
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;
160263509Sdim  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
169263509Sdim  typedef const Attribute *iterator;
170263509Sdim  iterator begin() const { return reinterpret_cast<iterator>(this + 1); }
171263509Sdim  iterator end() const { return begin() + NumAttrs; }
172249259Sdim
173249259Sdim  void Profile(FoldingSetNodeID &ID) const {
174263509Sdim    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;
192263509Sdim  unsigned NumAttrs; ///< Number of entries in this set.
193249259Sdim
194263509Sdim  /// \brief Return a pointer to the IndexAttrPair for the specified slot.
195263509Sdim  const IndexAttrPair *getNode(unsigned Slot) const {
196263509Sdim    return reinterpret_cast<const IndexAttrPair *>(this + 1) + Slot;
197263509Sdim  }
198263509Sdim
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,
204263509Sdim                   ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
205263509Sdim      : Context(C), NumAttrs(Attrs.size()) {
206263509Sdim#ifndef NDEBUG
207263509Sdim    if (Attrs.size() >= 2) {
208263509Sdim      for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1,
209263509Sdim                                                         *e = Attrs.end();
210263509Sdim           i != e; ++i) {
211263509Sdim        assert((i-1)->first <= i->first && "Attribute set not ordered!");
212263509Sdim      }
213263509Sdim    }
214263509Sdim#endif
215263509Sdim    // There's memory after the node where we can store the entries in.
216263509Sdim    std::copy(Attrs.begin(), Attrs.end(),
217263509Sdim              reinterpret_cast<IndexAttrPair *>(this + 1));
218263509Sdim  }
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.
224263509Sdim  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.
230252723Sdim  unsigned getSlotIndex(unsigned Slot) const {
231263509Sdim    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 {
238263509Sdim    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 {
244263509Sdim    return getNode(Slot)->second;
245249259Sdim  }
246249259Sdim
247263509Sdim  typedef AttributeSetNode::iterator iterator;
248263509Sdim  iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); }
249263509Sdim  iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); }
250249259Sdim
251249259Sdim  void Profile(FoldingSetNodeID &ID) const {
252263509Sdim    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.
263252723Sdim  uint64_t Raw(unsigned Index) const;
264263509Sdim
265263509Sdim  void dump() const;
266249259Sdim};
267249259Sdim
268249259Sdim} // end llvm namespace
269249259Sdim
270249259Sdim#endif
271