AttributeImpl.h revision 263508
1168404Spjd//===-- AttributeImpl.h - Attribute Internals -------------------*- C++ -*-===//
2168404Spjd//
3168404Spjd//                     The LLVM Compiler Infrastructure
4168404Spjd//
5168404Spjd// This file is distributed under the University of Illinois Open Source
6168404Spjd// License. See LICENSE.TXT for details.
7168404Spjd//
8168404Spjd//===----------------------------------------------------------------------===//
9168404Spjd///
10168404Spjd/// \file
11168404Spjd/// \brief This file defines various helper methods and classes used by
12168404Spjd/// LLVMContextImpl for creating and managing attributes.
13168404Spjd///
14168404Spjd//===----------------------------------------------------------------------===//
15168404Spjd
16168404Spjd#ifndef LLVM_ATTRIBUTESIMPL_H
17168404Spjd#define LLVM_ATTRIBUTESIMPL_H
18168404Spjd
19168404Spjd#include "llvm/ADT/FoldingSet.h"
20168404Spjd#include "llvm/IR/Attributes.h"
21168404Spjd#include <string>
22168404Spjd
23168404Spjdnamespace llvm {
24168404Spjd
25168404Spjdclass Constant;
26168404Spjdclass LLVMContext;
27168404Spjd
28168404Spjd//===----------------------------------------------------------------------===//
29168404Spjd/// \class
30168404Spjd/// \brief This class represents a single, uniqued attribute. That attribute
31168404Spjd/// could be a single enum, a tuple, or a string.
32168404Spjdclass AttributeImpl : public FoldingSetNode {
33168404Spjd  unsigned char KindID; ///< Holds the AttrEntryKind of the attribute
34168404Spjd
35168404Spjd  // AttributesImpl is uniqued, these should not be publicly available.
36168404Spjd  void operator=(const AttributeImpl &) LLVM_DELETED_FUNCTION;
37168404Spjd  AttributeImpl(const AttributeImpl &) LLVM_DELETED_FUNCTION;
38168404Spjd
39168404Spjdprotected:
40168404Spjd  enum AttrEntryKind {
41168404Spjd    EnumAttrEntry,
42168404Spjd    AlignAttrEntry,
43168404Spjd    StringAttrEntry
44168404Spjd  };
45168404Spjd
46168404Spjd  AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {}
47168404Spjd
48168404Spjdpublic:
49168404Spjd  virtual ~AttributeImpl();
50168404Spjd
51168404Spjd  bool isEnumAttribute() const { return KindID == EnumAttrEntry; }
52168404Spjd  bool isAlignAttribute() const { return KindID == AlignAttrEntry; }
53168404Spjd  bool isStringAttribute() const { return KindID == StringAttrEntry; }
54168404Spjd
55168404Spjd  bool hasAttribute(Attribute::AttrKind A) const;
56168404Spjd  bool hasAttribute(StringRef Kind) const;
57168404Spjd
58168404Spjd  Attribute::AttrKind getKindAsEnum() const;
59168404Spjd  uint64_t getValueAsInt() const;
60168404Spjd
61168404Spjd  StringRef getKindAsString() const;
62168404Spjd  StringRef getValueAsString() const;
63168404Spjd
64168404Spjd  /// \brief Used when sorting the attributes.
65168404Spjd  bool operator<(const AttributeImpl &AI) const;
66168404Spjd
67168404Spjd  void Profile(FoldingSetNodeID &ID) const {
68168404Spjd    if (isEnumAttribute())
69168404Spjd      Profile(ID, getKindAsEnum(), 0);
70168404Spjd    else if (isAlignAttribute())
71168404Spjd      Profile(ID, getKindAsEnum(), getValueAsInt());
72168404Spjd    else
73168404Spjd      Profile(ID, getKindAsString(), getValueAsString());
74168404Spjd  }
75168404Spjd  static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
76168404Spjd                      uint64_t Val) {
77168404Spjd    ID.AddInteger(Kind);
78168404Spjd    if (Val) ID.AddInteger(Val);
79168404Spjd  }
80168404Spjd  static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) {
81168404Spjd    ID.AddString(Kind);
82168404Spjd    if (!Values.empty()) ID.AddString(Values);
83168404Spjd  }
84168404Spjd
85168404Spjd  // FIXME: Remove this!
86168404Spjd  static uint64_t getAttrMask(Attribute::AttrKind Val);
87168404Spjd};
88168404Spjd
89168404Spjd//===----------------------------------------------------------------------===//
90168404Spjd/// \class
91168404Spjd/// \brief A set of classes that contain the value of the
92168404Spjd/// attribute object. There are three main categories: enum attribute entries,
93168404Spjd/// represented by Attribute::AttrKind; alignment attribute entries; and string
94168404Spjd/// attribute enties, which are for target-dependent attributes.
95168404Spjd
96168404Spjdclass EnumAttributeImpl : public AttributeImpl {
97168404Spjd  virtual void anchor();
98168404Spjd  Attribute::AttrKind Kind;
99168404Spjd
100168404Spjdprotected:
101168404Spjd  EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind)
102168404Spjd      : AttributeImpl(ID), Kind(Kind) {}
103168404Spjd
104168404Spjdpublic:
105168404Spjd  EnumAttributeImpl(Attribute::AttrKind Kind)
106168404Spjd      : AttributeImpl(EnumAttrEntry), Kind(Kind) {}
107168404Spjd
108168404Spjd  Attribute::AttrKind getEnumKind() const { return Kind; }
109168404Spjd};
110168404Spjd
111168404Spjdclass AlignAttributeImpl : public EnumAttributeImpl {
112168404Spjd  virtual void anchor();
113168404Spjd  unsigned Align;
114168404Spjd
115168404Spjdpublic:
116168404Spjd  AlignAttributeImpl(Attribute::AttrKind Kind, unsigned Align)
117168404Spjd      : EnumAttributeImpl(AlignAttrEntry, Kind), Align(Align) {
118168404Spjd    assert(
119168404Spjd        (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) &&
120168404Spjd        "Wrong kind for alignment attribute!");
121168404Spjd  }
122168404Spjd
123168404Spjd  unsigned getAlignment() const { return Align; }
124168404Spjd};
125168404Spjd
126168404Spjdclass StringAttributeImpl : public AttributeImpl {
127168404Spjd  virtual void anchor();
128168404Spjd  std::string Kind;
129168404Spjd  std::string Val;
130168404Spjd
131168404Spjdpublic:
132168404Spjd  StringAttributeImpl(StringRef Kind, StringRef Val = StringRef())
133168404Spjd      : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {}
134168404Spjd
135168404Spjd  StringRef getStringKind() const { return Kind; }
136168404Spjd  StringRef getStringValue() const { return Val; }
137168404Spjd};
138168404Spjd
139168404Spjd//===----------------------------------------------------------------------===//
140168404Spjd/// \class
141168404Spjd/// \brief This class represents a group of attributes that apply to one
142168404Spjd/// element: function, return type, or parameter.
143168404Spjdclass AttributeSetNode : public FoldingSetNode {
144168404Spjd  unsigned NumAttrs; ///< Number of attributes in this node.
145168404Spjd
146168404Spjd  AttributeSetNode(ArrayRef<Attribute> Attrs) : NumAttrs(Attrs.size()) {
147168404Spjd    // There's memory after the node where we can store the entries in.
148168404Spjd    std::copy(Attrs.begin(), Attrs.end(),
149168404Spjd              reinterpret_cast<Attribute *>(this + 1));
150168404Spjd  }
151168404Spjd
152168404Spjd  // AttributesSetNode is uniqued, these should not be publicly available.
153168404Spjd  void operator=(const AttributeSetNode &) LLVM_DELETED_FUNCTION;
154168404Spjd  AttributeSetNode(const AttributeSetNode &) LLVM_DELETED_FUNCTION;
155168404Spjdpublic:
156168404Spjd  static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
157168404Spjd
158168404Spjd  bool hasAttribute(Attribute::AttrKind Kind) const;
159168404Spjd  bool hasAttribute(StringRef Kind) const;
160168404Spjd  bool hasAttributes() const { return NumAttrs != 0; }
161168404Spjd
162168404Spjd  Attribute getAttribute(Attribute::AttrKind Kind) const;
163168404Spjd  Attribute getAttribute(StringRef Kind) const;
164168404Spjd
165168404Spjd  unsigned getAlignment() const;
166168404Spjd  unsigned getStackAlignment() const;
167168404Spjd  std::string getAsString(bool InAttrGrp) const;
168168404Spjd
169168404Spjd  typedef const Attribute *iterator;
170168404Spjd  iterator begin() const { return reinterpret_cast<iterator>(this + 1); }
171168404Spjd  iterator end() const { return begin() + NumAttrs; }
172168404Spjd
173168404Spjd  void Profile(FoldingSetNodeID &ID) const {
174168404Spjd    Profile(ID, makeArrayRef(begin(), end()));
175168404Spjd  }
176168404Spjd  static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {
177168404Spjd    for (unsigned I = 0, E = AttrList.size(); I != E; ++I)
178168404Spjd      AttrList[I].Profile(ID);
179168404Spjd  }
180168404Spjd};
181168404Spjd
182168404Spjd//===----------------------------------------------------------------------===//
183168404Spjd/// \class
184168404Spjd/// \brief This class represents a set of attributes that apply to the function,
185168404Spjd/// return type, and parameters.
186168404Spjdclass AttributeSetImpl : public FoldingSetNode {
187168404Spjd  friend class AttributeSet;
188168404Spjd
189168404Spjd  LLVMContext &Context;
190168404Spjd
191168404Spjd  typedef std::pair<unsigned, AttributeSetNode*> IndexAttrPair;
192168404Spjd  unsigned NumAttrs; ///< Number of entries in this set.
193168404Spjd
194168404Spjd  /// \brief Return a pointer to the IndexAttrPair for the specified slot.
195168404Spjd  const IndexAttrPair *getNode(unsigned Slot) const {
196168404Spjd    return reinterpret_cast<const IndexAttrPair *>(this + 1) + Slot;
197168404Spjd  }
198168404Spjd
199168404Spjd  // AttributesSet is uniqued, these should not be publicly available.
200168404Spjd  void operator=(const AttributeSetImpl &) LLVM_DELETED_FUNCTION;
201168404Spjd  AttributeSetImpl(const AttributeSetImpl &) LLVM_DELETED_FUNCTION;
202168404Spjdpublic:
203168404Spjd  AttributeSetImpl(LLVMContext &C,
204168404Spjd                   ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
205168404Spjd      : Context(C), NumAttrs(Attrs.size()) {
206168404Spjd#ifndef NDEBUG
207168404Spjd    if (Attrs.size() >= 2) {
208168404Spjd      for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1,
209168404Spjd                                                         *e = Attrs.end();
210168404Spjd           i != e; ++i) {
211168404Spjd        assert((i-1)->first <= i->first && "Attribute set not ordered!");
212168404Spjd      }
213168404Spjd    }
214168404Spjd#endif
215168404Spjd    // There's memory after the node where we can store the entries in.
216168404Spjd    std::copy(Attrs.begin(), Attrs.end(),
217168404Spjd              reinterpret_cast<IndexAttrPair *>(this + 1));
218168404Spjd  }
219168404Spjd
220168404Spjd  /// \brief Get the context that created this AttributeSetImpl.
221168404Spjd  LLVMContext &getContext() { return Context; }
222168404Spjd
223168404Spjd  /// \brief Return the number of attributes this AttributeSet contains.
224168404Spjd  unsigned getNumAttributes() const { return NumAttrs; }
225168404Spjd
226168404Spjd  /// \brief Get the index of the given "slot" in the AttrNodes list. This index
227168404Spjd  /// is the index of the return, parameter, or function object that the
228168404Spjd  /// attributes are applied to, not the index into the AttrNodes list where the
229168404Spjd  /// attributes reside.
230168404Spjd  unsigned getSlotIndex(unsigned Slot) const {
231168404Spjd    return getNode(Slot)->first;
232168404Spjd  }
233168404Spjd
234168404Spjd  /// \brief Retrieve the attributes for the given "slot" in the AttrNode list.
235168404Spjd  /// \p Slot is an index into the AttrNodes list, not the index of the return /
236168404Spjd  /// parameter/ function which the attributes apply to.
237168404Spjd  AttributeSet getSlotAttributes(unsigned Slot) const {
238168404Spjd    return AttributeSet::get(Context, *getNode(Slot));
239168404Spjd  }
240168404Spjd
241168404Spjd  /// \brief Retrieve the attribute set node for the given "slot" in the
242168404Spjd  /// AttrNode list.
243168404Spjd  AttributeSetNode *getSlotNode(unsigned Slot) const {
244168404Spjd    return getNode(Slot)->second;
245168404Spjd  }
246168404Spjd
247168404Spjd  typedef AttributeSetNode::iterator iterator;
248168404Spjd  iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); }
249168404Spjd  iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); }
250168404Spjd
251168404Spjd  void Profile(FoldingSetNodeID &ID) const {
252168404Spjd    Profile(ID, makeArrayRef(getNode(0), getNumAttributes()));
253168404Spjd  }
254168404Spjd  static void Profile(FoldingSetNodeID &ID,
255168404Spjd                      ArrayRef<std::pair<unsigned, AttributeSetNode*> > Nodes) {
256168404Spjd    for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
257168404Spjd      ID.AddInteger(Nodes[i].first);
258168404Spjd      ID.AddPointer(Nodes[i].second);
259168404Spjd    }
260168404Spjd  }
261168404Spjd
262168404Spjd  // FIXME: This atrocity is temporary.
263168404Spjd  uint64_t Raw(unsigned Index) const;
264168404Spjd
265168404Spjd  void dump() const;
266168404Spjd};
267168404Spjd
268168404Spjd} // end llvm namespace
269168404Spjd
270168404Spjd#endif
271168404Spjd