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