1 //===-- Attributes.cpp - Implement AttributesList -------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the AttributesList class and Attribute utilities.
12 //===----------------------------------------------------------------------===//
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"
22 //===----------------------------------------------------------------------===//
23 // Attribute Function Definitions
24 //===----------------------------------------------------------------------===//
26 std::string
Attribute::getAsString(Attributes Attrs
) {
28 if (Attrs
& Attribute::ZExt
)
30 if (Attrs
& Attribute::SExt
)
32 if (Attrs
& Attribute::NoReturn
)
33 Result
+= "noreturn ";
34 if (Attrs
& Attribute::NoUnwind
)
35 Result
+= "nounwind ";
36 if (Attrs
& Attribute::InReg
)
38 if (Attrs
& Attribute::NoAlias
)
40 if (Attrs
& Attribute::NoCapture
)
41 Result
+= "nocapture ";
42 if (Attrs
& Attribute::StructRet
)
44 if (Attrs
& Attribute::ByVal
)
46 if (Attrs
& Attribute::Nest
)
48 if (Attrs
& Attribute::ReadNone
)
49 Result
+= "readnone ";
50 if (Attrs
& Attribute::ReadOnly
)
51 Result
+= "readonly ";
52 if (Attrs
& Attribute::OptimizeForSize
)
54 if (Attrs
& Attribute::NoInline
)
55 Result
+= "noinline ";
56 if (Attrs
& Attribute::AlwaysInline
)
57 Result
+= "alwaysinline ";
58 if (Attrs
& Attribute::StackProtect
)
60 if (Attrs
& Attribute::StackProtectReq
)
62 if (Attrs
& Attribute::Alignment
) {
64 Result
+= utostr(Attribute::getAlignmentFromAttrs(Attrs
));
67 // Trim the trailing space.
68 assert(!Result
.empty() && "Unknown attribute!");
69 Result
.erase(Result
.end()-1);
73 Attributes
Attribute::typeIncompatible(const Type
*Ty
) {
74 Attributes Incompatible
= None
;
77 // Attributes that only apply to integers.
78 Incompatible
|= SExt
| ZExt
;
80 if (!isa
<PointerType
>(Ty
))
81 // Attributes that only apply to pointers.
82 Incompatible
|= ByVal
| Nest
| NoAlias
| StructRet
| NoCapture
;
87 //===----------------------------------------------------------------------===//
88 // AttributeListImpl Definition
89 //===----------------------------------------------------------------------===//
92 class AttributeListImpl
: public FoldingSetNode
{
95 // AttributesList is uniqued, these should not be publicly available.
96 void operator=(const AttributeListImpl
&); // Do not implement
97 AttributeListImpl(const AttributeListImpl
&); // Do not implement
98 ~AttributeListImpl(); // Private implementation
100 SmallVector
<AttributeWithIndex
, 4> Attrs
;
102 AttributeListImpl(const AttributeWithIndex
*Attr
, unsigned NumAttrs
)
103 : Attrs(Attr
, Attr
+NumAttrs
) {
107 void AddRef() { ++RefCount
; }
108 void DropRef() { if (--RefCount
== 0) delete this; }
110 void Profile(FoldingSetNodeID
&ID
) const {
111 Profile(ID
, &Attrs
[0], Attrs
.size());
113 static void Profile(FoldingSetNodeID
&ID
, const AttributeWithIndex
*Attr
,
115 for (unsigned i
= 0; i
!= NumAttrs
; ++i
)
116 ID
.AddInteger(uint64_t(Attr
[i
].Attrs
) << 32 | unsigned(Attr
[i
].Index
));
121 static ManagedStatic
<FoldingSet
<AttributeListImpl
> > AttributesLists
;
123 AttributeListImpl::~AttributeListImpl() {
124 AttributesLists
->RemoveNode(this);
128 AttrListPtr
AttrListPtr::get(const AttributeWithIndex
*Attrs
, unsigned NumAttrs
) {
129 // If there are no attributes then return a null AttributesList pointer.
131 return AttrListPtr();
134 for (unsigned i
= 0; i
!= NumAttrs
; ++i
) {
135 assert(Attrs
[i
].Attrs
!= Attribute::None
&&
136 "Pointless attribute!");
137 assert((!i
|| Attrs
[i
-1].Index
< Attrs
[i
].Index
) &&
138 "Misordered AttributesList!");
142 // Otherwise, build a key to look up the existing attributes.
144 AttributeListImpl::Profile(ID
, Attrs
, NumAttrs
);
146 AttributeListImpl
*PAL
=
147 AttributesLists
->FindNodeOrInsertPos(ID
, InsertPos
);
149 // If we didn't find any existing attributes of the same shape then
150 // create a new one and insert it.
152 PAL
= new AttributeListImpl(Attrs
, NumAttrs
);
153 AttributesLists
->InsertNode(PAL
, InsertPos
);
156 // Return the AttributesList that we found or created.
157 return AttrListPtr(PAL
);
161 //===----------------------------------------------------------------------===//
162 // AttrListPtr Method Implementations
163 //===----------------------------------------------------------------------===//
165 AttrListPtr::AttrListPtr(AttributeListImpl
*LI
) : AttrList(LI
) {
166 if (LI
) LI
->AddRef();
169 AttrListPtr::AttrListPtr(const AttrListPtr
&P
) : AttrList(P
.AttrList
) {
170 if (AttrList
) AttrList
->AddRef();
173 const AttrListPtr
&AttrListPtr::operator=(const AttrListPtr
&RHS
) {
174 if (AttrList
== RHS
.AttrList
) return *this;
175 if (AttrList
) AttrList
->DropRef();
176 AttrList
= RHS
.AttrList
;
177 if (AttrList
) AttrList
->AddRef();
181 AttrListPtr::~AttrListPtr() {
182 if (AttrList
) AttrList
->DropRef();
185 /// getNumSlots - Return the number of slots used in this attribute list.
186 /// This is the number of arguments that have an attribute set on them
187 /// (including the function itself).
188 unsigned AttrListPtr::getNumSlots() const {
189 return AttrList
? AttrList
->Attrs
.size() : 0;
192 /// getSlot - Return the AttributeWithIndex at the specified slot. This
193 /// holds a number plus a set of attributes.
194 const AttributeWithIndex
&AttrListPtr::getSlot(unsigned Slot
) const {
195 assert(AttrList
&& Slot
< AttrList
->Attrs
.size() && "Slot # out of range!");
196 return AttrList
->Attrs
[Slot
];
200 /// getAttributes - The attributes for the specified index are
201 /// returned. Attributes for the result are denoted with Idx = 0.
202 /// Function notes are denoted with idx = ~0.
203 Attributes
AttrListPtr::getAttributes(unsigned Idx
) const {
204 if (AttrList
== 0) return Attribute::None
;
206 const SmallVector
<AttributeWithIndex
, 4> &Attrs
= AttrList
->Attrs
;
207 for (unsigned i
= 0, e
= Attrs
.size(); i
!= e
&& Attrs
[i
].Index
<= Idx
; ++i
)
208 if (Attrs
[i
].Index
== Idx
)
209 return Attrs
[i
].Attrs
;
210 return Attribute::None
;
213 /// hasAttrSomewhere - Return true if the specified attribute is set for at
214 /// least one parameter or for the return value.
215 bool AttrListPtr::hasAttrSomewhere(Attributes Attr
) const {
216 if (AttrList
== 0) return false;
218 const SmallVector
<AttributeWithIndex
, 4> &Attrs
= AttrList
->Attrs
;
219 for (unsigned i
= 0, e
= Attrs
.size(); i
!= e
; ++i
)
220 if (Attrs
[i
].Attrs
& Attr
)
226 AttrListPtr
AttrListPtr::addAttr(unsigned Idx
, Attributes Attrs
) const {
227 Attributes OldAttrs
= getAttributes(Idx
);
229 // FIXME it is not obvious how this should work for alignment.
230 // For now, say we can't change a known alignment.
231 Attributes OldAlign
= OldAttrs
& Attribute::Alignment
;
232 Attributes NewAlign
= Attrs
& Attribute::Alignment
;
233 assert((!OldAlign
|| !NewAlign
|| OldAlign
== NewAlign
) &&
234 "Attempt to change alignment!");
237 Attributes NewAttrs
= OldAttrs
| Attrs
;
238 if (NewAttrs
== OldAttrs
)
241 SmallVector
<AttributeWithIndex
, 8> NewAttrList
;
243 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
245 const SmallVector
<AttributeWithIndex
, 4> &OldAttrList
= AttrList
->Attrs
;
246 unsigned i
= 0, e
= OldAttrList
.size();
247 // Copy attributes for arguments before this one.
248 for (; i
!= e
&& OldAttrList
[i
].Index
< Idx
; ++i
)
249 NewAttrList
.push_back(OldAttrList
[i
]);
251 // If there are attributes already at this index, merge them in.
252 if (i
!= e
&& OldAttrList
[i
].Index
== Idx
) {
253 Attrs
|= OldAttrList
[i
].Attrs
;
257 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
259 // Copy attributes for arguments after this one.
260 NewAttrList
.insert(NewAttrList
.end(),
261 OldAttrList
.begin()+i
, OldAttrList
.end());
264 return get(&NewAttrList
[0], NewAttrList
.size());
267 AttrListPtr
AttrListPtr::removeAttr(unsigned Idx
, Attributes Attrs
) const {
269 // FIXME it is not obvious how this should work for alignment.
270 // For now, say we can't pass in alignment, which no current use does.
271 assert(!(Attrs
& Attribute::Alignment
) && "Attempt to exclude alignment!");
273 if (AttrList
== 0) return AttrListPtr();
275 Attributes OldAttrs
= getAttributes(Idx
);
276 Attributes NewAttrs
= OldAttrs
& ~Attrs
;
277 if (NewAttrs
== OldAttrs
)
280 SmallVector
<AttributeWithIndex
, 8> NewAttrList
;
281 const SmallVector
<AttributeWithIndex
, 4> &OldAttrList
= AttrList
->Attrs
;
282 unsigned i
= 0, e
= OldAttrList
.size();
284 // Copy attributes for arguments before this one.
285 for (; i
!= e
&& OldAttrList
[i
].Index
< Idx
; ++i
)
286 NewAttrList
.push_back(OldAttrList
[i
]);
288 // If there are attributes already at this index, merge them in.
289 assert(OldAttrList
[i
].Index
== Idx
&& "Attribute isn't set?");
290 Attrs
= OldAttrList
[i
].Attrs
& ~Attrs
;
292 if (Attrs
) // If any attributes left for this parameter, add them.
293 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
295 // Copy attributes for arguments after this one.
296 NewAttrList
.insert(NewAttrList
.end(),
297 OldAttrList
.begin()+i
, OldAttrList
.end());
299 return get(&NewAttrList
[0], NewAttrList
.size());
302 void AttrListPtr::dump() const {
304 for (unsigned i
= 0; i
< getNumSlots(); ++i
) {
305 const AttributeWithIndex
&PAWI
= getSlot(i
);
306 cerr
<< "{" << PAWI
.Index
<< "," << PAWI
.Attrs
<< "} ";