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::NoRedZone
)
63 Result
+= "noredzone ";
64 if (Attrs
& Attribute::NoImplicitFloat
)
65 Result
+= "noimplicitfloat ";
66 if (Attrs
& Attribute::Naked
)
68 if (Attrs
& Attribute::Alignment
) {
70 Result
+= utostr(Attribute::getAlignmentFromAttrs(Attrs
));
73 // Trim the trailing space.
74 assert(!Result
.empty() && "Unknown attribute!");
75 Result
.erase(Result
.end()-1);
79 Attributes
Attribute::typeIncompatible(const Type
*Ty
) {
80 Attributes Incompatible
= None
;
83 // Attributes that only apply to integers.
84 Incompatible
|= SExt
| ZExt
;
86 if (!isa
<PointerType
>(Ty
))
87 // Attributes that only apply to pointers.
88 Incompatible
|= ByVal
| Nest
| NoAlias
| StructRet
| NoCapture
;
93 //===----------------------------------------------------------------------===//
94 // AttributeListImpl Definition
95 //===----------------------------------------------------------------------===//
98 class AttributeListImpl
: public FoldingSetNode
{
101 // AttributesList is uniqued, these should not be publicly available.
102 void operator=(const AttributeListImpl
&); // Do not implement
103 AttributeListImpl(const AttributeListImpl
&); // Do not implement
104 ~AttributeListImpl(); // Private implementation
106 SmallVector
<AttributeWithIndex
, 4> Attrs
;
108 AttributeListImpl(const AttributeWithIndex
*Attr
, unsigned NumAttrs
)
109 : Attrs(Attr
, Attr
+NumAttrs
) {
113 void AddRef() { ++RefCount
; }
114 void DropRef() { if (--RefCount
== 0) delete this; }
116 void Profile(FoldingSetNodeID
&ID
) const {
117 Profile(ID
, Attrs
.data(), Attrs
.size());
119 static void Profile(FoldingSetNodeID
&ID
, const AttributeWithIndex
*Attr
,
121 for (unsigned i
= 0; i
!= NumAttrs
; ++i
)
122 ID
.AddInteger(uint64_t(Attr
[i
].Attrs
) << 32 | unsigned(Attr
[i
].Index
));
127 static ManagedStatic
<FoldingSet
<AttributeListImpl
> > AttributesLists
;
129 AttributeListImpl::~AttributeListImpl() {
130 AttributesLists
->RemoveNode(this);
134 AttrListPtr
AttrListPtr::get(const AttributeWithIndex
*Attrs
, unsigned NumAttrs
) {
135 // If there are no attributes then return a null AttributesList pointer.
137 return AttrListPtr();
140 for (unsigned i
= 0; i
!= NumAttrs
; ++i
) {
141 assert(Attrs
[i
].Attrs
!= Attribute::None
&&
142 "Pointless attribute!");
143 assert((!i
|| Attrs
[i
-1].Index
< Attrs
[i
].Index
) &&
144 "Misordered AttributesList!");
148 // Otherwise, build a key to look up the existing attributes.
150 AttributeListImpl::Profile(ID
, Attrs
, NumAttrs
);
152 AttributeListImpl
*PAL
=
153 AttributesLists
->FindNodeOrInsertPos(ID
, InsertPos
);
155 // If we didn't find any existing attributes of the same shape then
156 // create a new one and insert it.
158 PAL
= new AttributeListImpl(Attrs
, NumAttrs
);
159 AttributesLists
->InsertNode(PAL
, InsertPos
);
162 // Return the AttributesList that we found or created.
163 return AttrListPtr(PAL
);
167 //===----------------------------------------------------------------------===//
168 // AttrListPtr Method Implementations
169 //===----------------------------------------------------------------------===//
171 AttrListPtr::AttrListPtr(AttributeListImpl
*LI
) : AttrList(LI
) {
172 if (LI
) LI
->AddRef();
175 AttrListPtr::AttrListPtr(const AttrListPtr
&P
) : AttrList(P
.AttrList
) {
176 if (AttrList
) AttrList
->AddRef();
179 const AttrListPtr
&AttrListPtr::operator=(const AttrListPtr
&RHS
) {
180 if (AttrList
== RHS
.AttrList
) return *this;
181 if (AttrList
) AttrList
->DropRef();
182 AttrList
= RHS
.AttrList
;
183 if (AttrList
) AttrList
->AddRef();
187 AttrListPtr::~AttrListPtr() {
188 if (AttrList
) AttrList
->DropRef();
191 /// getNumSlots - Return the number of slots used in this attribute list.
192 /// This is the number of arguments that have an attribute set on them
193 /// (including the function itself).
194 unsigned AttrListPtr::getNumSlots() const {
195 return AttrList
? AttrList
->Attrs
.size() : 0;
198 /// getSlot - Return the AttributeWithIndex at the specified slot. This
199 /// holds a number plus a set of attributes.
200 const AttributeWithIndex
&AttrListPtr::getSlot(unsigned Slot
) const {
201 assert(AttrList
&& Slot
< AttrList
->Attrs
.size() && "Slot # out of range!");
202 return AttrList
->Attrs
[Slot
];
206 /// getAttributes - The attributes for the specified index are
207 /// returned. Attributes for the result are denoted with Idx = 0.
208 /// Function notes are denoted with idx = ~0.
209 Attributes
AttrListPtr::getAttributes(unsigned Idx
) const {
210 if (AttrList
== 0) return Attribute::None
;
212 const SmallVector
<AttributeWithIndex
, 4> &Attrs
= AttrList
->Attrs
;
213 for (unsigned i
= 0, e
= Attrs
.size(); i
!= e
&& Attrs
[i
].Index
<= Idx
; ++i
)
214 if (Attrs
[i
].Index
== Idx
)
215 return Attrs
[i
].Attrs
;
216 return Attribute::None
;
219 /// hasAttrSomewhere - Return true if the specified attribute is set for at
220 /// least one parameter or for the return value.
221 bool AttrListPtr::hasAttrSomewhere(Attributes Attr
) const {
222 if (AttrList
== 0) return false;
224 const SmallVector
<AttributeWithIndex
, 4> &Attrs
= AttrList
->Attrs
;
225 for (unsigned i
= 0, e
= Attrs
.size(); i
!= e
; ++i
)
226 if (Attrs
[i
].Attrs
& Attr
)
232 AttrListPtr
AttrListPtr::addAttr(unsigned Idx
, Attributes Attrs
) const {
233 Attributes OldAttrs
= getAttributes(Idx
);
235 // FIXME it is not obvious how this should work for alignment.
236 // For now, say we can't change a known alignment.
237 Attributes OldAlign
= OldAttrs
& Attribute::Alignment
;
238 Attributes NewAlign
= Attrs
& Attribute::Alignment
;
239 assert((!OldAlign
|| !NewAlign
|| OldAlign
== NewAlign
) &&
240 "Attempt to change alignment!");
243 Attributes NewAttrs
= OldAttrs
| Attrs
;
244 if (NewAttrs
== OldAttrs
)
247 SmallVector
<AttributeWithIndex
, 8> NewAttrList
;
249 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
251 const SmallVector
<AttributeWithIndex
, 4> &OldAttrList
= AttrList
->Attrs
;
252 unsigned i
= 0, e
= OldAttrList
.size();
253 // Copy attributes for arguments before this one.
254 for (; i
!= e
&& OldAttrList
[i
].Index
< Idx
; ++i
)
255 NewAttrList
.push_back(OldAttrList
[i
]);
257 // If there are attributes already at this index, merge them in.
258 if (i
!= e
&& OldAttrList
[i
].Index
== Idx
) {
259 Attrs
|= OldAttrList
[i
].Attrs
;
263 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
265 // Copy attributes for arguments after this one.
266 NewAttrList
.insert(NewAttrList
.end(),
267 OldAttrList
.begin()+i
, OldAttrList
.end());
270 return get(NewAttrList
.data(), NewAttrList
.size());
273 AttrListPtr
AttrListPtr::removeAttr(unsigned Idx
, Attributes Attrs
) const {
275 // FIXME it is not obvious how this should work for alignment.
276 // For now, say we can't pass in alignment, which no current use does.
277 assert(!(Attrs
& Attribute::Alignment
) && "Attempt to exclude alignment!");
279 if (AttrList
== 0) return AttrListPtr();
281 Attributes OldAttrs
= getAttributes(Idx
);
282 Attributes NewAttrs
= OldAttrs
& ~Attrs
;
283 if (NewAttrs
== OldAttrs
)
286 SmallVector
<AttributeWithIndex
, 8> NewAttrList
;
287 const SmallVector
<AttributeWithIndex
, 4> &OldAttrList
= AttrList
->Attrs
;
288 unsigned i
= 0, e
= OldAttrList
.size();
290 // Copy attributes for arguments before this one.
291 for (; i
!= e
&& OldAttrList
[i
].Index
< Idx
; ++i
)
292 NewAttrList
.push_back(OldAttrList
[i
]);
294 // If there are attributes already at this index, merge them in.
295 assert(OldAttrList
[i
].Index
== Idx
&& "Attribute isn't set?");
296 Attrs
= OldAttrList
[i
].Attrs
& ~Attrs
;
298 if (Attrs
) // If any attributes left for this parameter, add them.
299 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
301 // Copy attributes for arguments after this one.
302 NewAttrList
.insert(NewAttrList
.end(),
303 OldAttrList
.begin()+i
, OldAttrList
.end());
305 return get(NewAttrList
.data(), NewAttrList
.size());
308 void AttrListPtr::dump() const {
310 for (unsigned i
= 0; i
< getNumSlots(); ++i
) {
311 const AttributeWithIndex
&PAWI
= getSlot(i
);
312 cerr
<< "{" << PAWI
.Index
<< "," << PAWI
.Attrs
<< "} ";