Attributes.cpp revision e9e6bdf27fca46dc9eca2ebdf73e03747d1859ab
1//===-- Attributes.cpp - Implement AttributesList -------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the AttributesList class and Attribute utilities.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Attributes.h"
15#include "llvm/Type.h"
16#include "llvm/ADT/StringExtras.h"
17#include "llvm/ADT/FoldingSet.h"
18#include "llvm/Support/Streams.h"
19#include "llvm/Support/ManagedStatic.h"
20using namespace llvm;
21
22//===----------------------------------------------------------------------===//
23// Attribute Function Definitions
24//===----------------------------------------------------------------------===//
25
26std::string Attribute::getAsString(Attributes Attrs) {
27  std::string Result;
28  if (Attrs & Attribute::ZExt)
29    Result += "zeroext ";
30  if (Attrs & Attribute::SExt)
31    Result += "signext ";
32  if (Attrs & Attribute::NoReturn)
33    Result += "noreturn ";
34  if (Attrs & Attribute::NoUnwind)
35    Result += "nounwind ";
36  if (Attrs & Attribute::InReg)
37    Result += "inreg ";
38  if (Attrs & Attribute::NoAlias)
39    Result += "noalias ";
40  if (Attrs & Attribute::StructRet)
41    Result += "sret ";
42  if (Attrs & Attribute::ByVal)
43    Result += "byval ";
44  if (Attrs & Attribute::Nest)
45    Result += "nest ";
46  if (Attrs & Attribute::ReadNone)
47    Result += "readnone ";
48  if (Attrs & Attribute::ReadOnly)
49    Result += "readonly ";
50  if (Attrs & Attribute::OptimizeForSize)
51    Result += "optsize ";
52  if (Attrs & Attribute::NoInline)
53    Result += "noinline ";
54  if (Attrs & Attribute::AlwaysInline)
55    Result += "alwaysinline ";
56  if (Attrs & Attribute::StackProtect)
57    Result += "ssp ";
58  if (Attrs & Attribute::StackProtectReq)
59    Result += "sspreq ";
60  if (Attrs & Attribute::Alignment) {
61    Result += "align ";
62    Result += utostr((Attrs & Attribute::Alignment) >> 16);
63    Result += " ";
64  }
65  // Trim the trailing space.
66  Result.erase(Result.end()-1);
67  return Result;
68}
69
70Attributes Attribute::typeIncompatible(const Type *Ty) {
71  Attributes Incompatible = None;
72
73  if (!Ty->isInteger())
74    // Attributes that only apply to integers.
75    Incompatible |= SExt | ZExt;
76
77  if (!isa<PointerType>(Ty))
78    // Attributes that only apply to pointers.
79    Incompatible |= ByVal | Nest | NoAlias | StructRet;
80
81  return Incompatible;
82}
83
84//===----------------------------------------------------------------------===//
85// AttributeListImpl Definition
86//===----------------------------------------------------------------------===//
87
88namespace llvm {
89class AttributeListImpl : public FoldingSetNode {
90  unsigned RefCount;
91
92  // AttributesList is uniqued, these should not be publicly available.
93  void operator=(const AttributeListImpl &); // Do not implement
94  AttributeListImpl(const AttributeListImpl &); // Do not implement
95  ~AttributeListImpl();                        // Private implementation
96public:
97  SmallVector<AttributeWithIndex, 4> Attrs;
98
99  AttributeListImpl(const AttributeWithIndex *Attr, unsigned NumAttrs)
100    : Attrs(Attr, Attr+NumAttrs) {
101    RefCount = 0;
102  }
103
104  void AddRef() { ++RefCount; }
105  void DropRef() { if (--RefCount == 0) delete this; }
106
107  void Profile(FoldingSetNodeID &ID) const {
108    Profile(ID, &Attrs[0], Attrs.size());
109  }
110  static void Profile(FoldingSetNodeID &ID, const AttributeWithIndex *Attr,
111                      unsigned NumAttrs) {
112    for (unsigned i = 0; i != NumAttrs; ++i)
113      ID.AddInteger(uint64_t(Attr[i].Attrs) << 32 | unsigned(Attr[i].Index));
114  }
115};
116}
117
118static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists;
119
120AttributeListImpl::~AttributeListImpl() {
121  AttributesLists->RemoveNode(this);
122}
123
124
125AttrListPtr AttrListPtr::get(const AttributeWithIndex *Attrs, unsigned NumAttrs) {
126  // If there are no attributes then return a null AttributesList pointer.
127  if (NumAttrs == 0)
128    return AttrListPtr();
129
130#ifndef NDEBUG
131  for (unsigned i = 0; i != NumAttrs; ++i) {
132    assert(Attrs[i].Attrs != Attribute::None &&
133           "Pointless attribute!");
134    assert((!i || Attrs[i-1].Index < Attrs[i].Index) &&
135           "Misordered AttributesList!");
136  }
137#endif
138
139  // Otherwise, build a key to look up the existing attributes.
140  FoldingSetNodeID ID;
141  AttributeListImpl::Profile(ID, Attrs, NumAttrs);
142  void *InsertPos;
143  AttributeListImpl *PAL =
144    AttributesLists->FindNodeOrInsertPos(ID, InsertPos);
145
146  // If we didn't find any existing attributes of the same shape then
147  // create a new one and insert it.
148  if (!PAL) {
149    PAL = new AttributeListImpl(Attrs, NumAttrs);
150    AttributesLists->InsertNode(PAL, InsertPos);
151  }
152
153  // Return the AttributesList that we found or created.
154  return AttrListPtr(PAL);
155}
156
157
158//===----------------------------------------------------------------------===//
159// AttrListPtr Method Implementations
160//===----------------------------------------------------------------------===//
161
162AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) {
163  if (LI) LI->AddRef();
164}
165
166AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) {
167  if (AttrList) AttrList->AddRef();
168}
169
170const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) {
171  if (AttrList == RHS.AttrList) return *this;
172  if (AttrList) AttrList->DropRef();
173  AttrList = RHS.AttrList;
174  if (AttrList) AttrList->AddRef();
175  return *this;
176}
177
178AttrListPtr::~AttrListPtr() {
179  if (AttrList) AttrList->DropRef();
180}
181
182/// getNumSlots - Return the number of slots used in this attribute list.
183/// This is the number of arguments that have an attribute set on them
184/// (including the function itself).
185unsigned AttrListPtr::getNumSlots() const {
186  return AttrList ? AttrList->Attrs.size() : 0;
187}
188
189/// getSlot - Return the AttributeWithIndex at the specified slot.  This
190/// holds a number plus a set of attributes.
191const AttributeWithIndex &AttrListPtr::getSlot(unsigned Slot) const {
192  assert(AttrList && Slot < AttrList->Attrs.size() && "Slot # out of range!");
193  return AttrList->Attrs[Slot];
194}
195
196
197/// getAttributes - The attributes for the specified index are
198/// returned.  Attributes for the result are denoted with Idx = 0.
199/// Function notes are denoted with idx = ~0.
200Attributes AttrListPtr::getAttributes(unsigned Idx) const {
201  if (AttrList == 0) return Attribute::None;
202
203  const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
204  for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i)
205    if (Attrs[i].Index == Idx)
206      return Attrs[i].Attrs;
207  return Attribute::None;
208}
209
210/// hasAttrSomewhere - Return true if the specified attribute is set for at
211/// least one parameter or for the return value.
212bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const {
213  if (AttrList == 0) return false;
214
215  const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
216  for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
217    if (Attrs[i].Attrs & Attr)
218      return true;
219  return false;
220}
221
222
223AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const {
224  Attributes OldAttrs = getAttributes(Idx);
225#ifndef NDEBUG
226  // FIXME it is not obvious how this should work for alignment.
227  // For now, say we can't change a known alignment.
228  Attributes OldAlign = OldAttrs & Attribute::Alignment;
229  Attributes NewAlign = Attrs & Attribute::Alignment;
230  assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
231         "Attempt to change alignment!");
232#endif
233
234  Attributes NewAttrs = OldAttrs | Attrs;
235  if (NewAttrs == OldAttrs)
236    return *this;
237
238  SmallVector<AttributeWithIndex, 8> NewAttrList;
239  if (AttrList == 0)
240    NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
241  else {
242    const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
243    unsigned i = 0, e = OldAttrList.size();
244    // Copy attributes for arguments before this one.
245    for (; i != e && OldAttrList[i].Index < Idx; ++i)
246      NewAttrList.push_back(OldAttrList[i]);
247
248    // If there are attributes already at this index, merge them in.
249    if (i != e && OldAttrList[i].Index == Idx) {
250      Attrs |= OldAttrList[i].Attrs;
251      ++i;
252    }
253
254    NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
255
256    // Copy attributes for arguments after this one.
257    NewAttrList.insert(NewAttrList.end(),
258                       OldAttrList.begin()+i, OldAttrList.end());
259  }
260
261  return get(&NewAttrList[0], NewAttrList.size());
262}
263
264AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const {
265#ifndef NDEBUG
266  // FIXME it is not obvious how this should work for alignment.
267  // For now, say we can't pass in alignment, which no current use does.
268  assert(!(Attrs & Attribute::Alignment) && "Attempt to exclude alignment!");
269#endif
270  if (AttrList == 0) return AttrListPtr();
271
272  Attributes OldAttrs = getAttributes(Idx);
273  Attributes NewAttrs = OldAttrs & ~Attrs;
274  if (NewAttrs == OldAttrs)
275    return *this;
276
277  SmallVector<AttributeWithIndex, 8> NewAttrList;
278  const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
279  unsigned i = 0, e = OldAttrList.size();
280
281  // Copy attributes for arguments before this one.
282  for (; i != e && OldAttrList[i].Index < Idx; ++i)
283    NewAttrList.push_back(OldAttrList[i]);
284
285  // If there are attributes already at this index, merge them in.
286  assert(OldAttrList[i].Index == Idx && "Attribute isn't set?");
287  Attrs = OldAttrList[i].Attrs & ~Attrs;
288  ++i;
289  if (Attrs)  // If any attributes left for this parameter, add them.
290    NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
291
292  // Copy attributes for arguments after this one.
293  NewAttrList.insert(NewAttrList.end(),
294                     OldAttrList.begin()+i, OldAttrList.end());
295
296  return get(&NewAttrList[0], NewAttrList.size());
297}
298
299void AttrListPtr::dump() const {
300  cerr << "PAL[ ";
301  for (unsigned i = 0; i < getNumSlots(); ++i) {
302    const AttributeWithIndex &PAWI = getSlot(i);
303    cerr << "{" << PAWI.Index << "," << PAWI.Attrs << "} ";
304  }
305
306  cerr << "]\n";
307}
308