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/System/Atomic.h"
19 #include "llvm/System/Mutex.h"
20 #include "llvm/Support/ManagedStatic.h"
21 #include "llvm/Support/raw_ostream.h"
24 //===----------------------------------------------------------------------===//
25 // Attribute Function Definitions
26 //===----------------------------------------------------------------------===//
28 std::string
Attribute::getAsString(Attributes Attrs
) {
30 if (Attrs
& Attribute::ZExt
)
32 if (Attrs
& Attribute::SExt
)
34 if (Attrs
& Attribute::NoReturn
)
35 Result
+= "noreturn ";
36 if (Attrs
& Attribute::NoUnwind
)
37 Result
+= "nounwind ";
38 if (Attrs
& Attribute::InReg
)
40 if (Attrs
& Attribute::NoAlias
)
42 if (Attrs
& Attribute::NoCapture
)
43 Result
+= "nocapture ";
44 if (Attrs
& Attribute::StructRet
)
46 if (Attrs
& Attribute::ByVal
)
48 if (Attrs
& Attribute::Nest
)
50 if (Attrs
& Attribute::ReadNone
)
51 Result
+= "readnone ";
52 if (Attrs
& Attribute::ReadOnly
)
53 Result
+= "readonly ";
54 if (Attrs
& Attribute::OptimizeForSize
)
56 if (Attrs
& Attribute::NoInline
)
57 Result
+= "noinline ";
58 if (Attrs
& Attribute::InlineHint
)
59 Result
+= "inlinehint ";
60 if (Attrs
& Attribute::AlwaysInline
)
61 Result
+= "alwaysinline ";
62 if (Attrs
& Attribute::StackProtect
)
64 if (Attrs
& Attribute::StackProtectReq
)
66 if (Attrs
& Attribute::NoRedZone
)
67 Result
+= "noredzone ";
68 if (Attrs
& Attribute::NoImplicitFloat
)
69 Result
+= "noimplicitfloat ";
70 if (Attrs
& Attribute::Naked
)
72 if (Attrs
& Attribute::Alignment
) {
74 Result
+= utostr(Attribute::getAlignmentFromAttrs(Attrs
));
77 // Trim the trailing space.
78 assert(!Result
.empty() && "Unknown attribute!");
79 Result
.erase(Result
.end()-1);
83 Attributes
Attribute::typeIncompatible(const Type
*Ty
) {
84 Attributes Incompatible
= None
;
87 // Attributes that only apply to integers.
88 Incompatible
|= SExt
| ZExt
;
90 if (!isa
<PointerType
>(Ty
))
91 // Attributes that only apply to pointers.
92 Incompatible
|= ByVal
| Nest
| NoAlias
| StructRet
| NoCapture
;
97 //===----------------------------------------------------------------------===//
98 // AttributeListImpl Definition
99 //===----------------------------------------------------------------------===//
102 class AttributeListImpl
: public FoldingSetNode
{
103 sys::cas_flag RefCount
;
105 // AttributesList is uniqued, these should not be publicly available.
106 void operator=(const AttributeListImpl
&); // Do not implement
107 AttributeListImpl(const AttributeListImpl
&); // Do not implement
108 ~AttributeListImpl(); // Private implementation
110 SmallVector
<AttributeWithIndex
, 4> Attrs
;
112 AttributeListImpl(const AttributeWithIndex
*Attr
, unsigned NumAttrs
)
113 : Attrs(Attr
, Attr
+NumAttrs
) {
117 void AddRef() { sys::AtomicIncrement(&RefCount
); }
119 sys::cas_flag old
= sys::AtomicDecrement(&RefCount
);
120 if (old
== 0) delete this;
123 void Profile(FoldingSetNodeID
&ID
) const {
124 Profile(ID
, Attrs
.data(), Attrs
.size());
126 static void Profile(FoldingSetNodeID
&ID
, const AttributeWithIndex
*Attr
,
128 for (unsigned i
= 0; i
!= NumAttrs
; ++i
)
129 ID
.AddInteger(uint64_t(Attr
[i
].Attrs
) << 32 | unsigned(Attr
[i
].Index
));
134 static ManagedStatic
<sys::SmartMutex
<true> > ALMutex
;
135 static ManagedStatic
<FoldingSet
<AttributeListImpl
> > AttributesLists
;
137 AttributeListImpl::~AttributeListImpl() {
138 sys::SmartScopedLock
<true> Lock(*ALMutex
);
139 AttributesLists
->RemoveNode(this);
143 AttrListPtr
AttrListPtr::get(const AttributeWithIndex
*Attrs
, unsigned NumAttrs
) {
144 // If there are no attributes then return a null AttributesList pointer.
146 return AttrListPtr();
149 for (unsigned i
= 0; i
!= NumAttrs
; ++i
) {
150 assert(Attrs
[i
].Attrs
!= Attribute::None
&&
151 "Pointless attribute!");
152 assert((!i
|| Attrs
[i
-1].Index
< Attrs
[i
].Index
) &&
153 "Misordered AttributesList!");
157 // Otherwise, build a key to look up the existing attributes.
159 AttributeListImpl::Profile(ID
, Attrs
, NumAttrs
);
162 sys::SmartScopedLock
<true> Lock(*ALMutex
);
164 AttributeListImpl
*PAL
=
165 AttributesLists
->FindNodeOrInsertPos(ID
, InsertPos
);
167 // If we didn't find any existing attributes of the same shape then
168 // create a new one and insert it.
170 PAL
= new AttributeListImpl(Attrs
, NumAttrs
);
171 AttributesLists
->InsertNode(PAL
, InsertPos
);
174 // Return the AttributesList that we found or created.
175 return AttrListPtr(PAL
);
179 //===----------------------------------------------------------------------===//
180 // AttrListPtr Method Implementations
181 //===----------------------------------------------------------------------===//
183 AttrListPtr::AttrListPtr(AttributeListImpl
*LI
) : AttrList(LI
) {
184 if (LI
) LI
->AddRef();
187 AttrListPtr::AttrListPtr(const AttrListPtr
&P
) : AttrList(P
.AttrList
) {
188 if (AttrList
) AttrList
->AddRef();
191 const AttrListPtr
&AttrListPtr::operator=(const AttrListPtr
&RHS
) {
192 if (AttrList
== RHS
.AttrList
) return *this;
193 if (AttrList
) AttrList
->DropRef();
194 AttrList
= RHS
.AttrList
;
195 if (AttrList
) AttrList
->AddRef();
199 AttrListPtr::~AttrListPtr() {
200 if (AttrList
) AttrList
->DropRef();
203 /// getNumSlots - Return the number of slots used in this attribute list.
204 /// This is the number of arguments that have an attribute set on them
205 /// (including the function itself).
206 unsigned AttrListPtr::getNumSlots() const {
207 return AttrList
? AttrList
->Attrs
.size() : 0;
210 /// getSlot - Return the AttributeWithIndex at the specified slot. This
211 /// holds a number plus a set of attributes.
212 const AttributeWithIndex
&AttrListPtr::getSlot(unsigned Slot
) const {
213 assert(AttrList
&& Slot
< AttrList
->Attrs
.size() && "Slot # out of range!");
214 return AttrList
->Attrs
[Slot
];
218 /// getAttributes - The attributes for the specified index are
219 /// returned. Attributes for the result are denoted with Idx = 0.
220 /// Function notes are denoted with idx = ~0.
221 Attributes
AttrListPtr::getAttributes(unsigned Idx
) const {
222 if (AttrList
== 0) return Attribute::None
;
224 const SmallVector
<AttributeWithIndex
, 4> &Attrs
= AttrList
->Attrs
;
225 for (unsigned i
= 0, e
= Attrs
.size(); i
!= e
&& Attrs
[i
].Index
<= Idx
; ++i
)
226 if (Attrs
[i
].Index
== Idx
)
227 return Attrs
[i
].Attrs
;
228 return Attribute::None
;
231 /// hasAttrSomewhere - Return true if the specified attribute is set for at
232 /// least one parameter or for the return value.
233 bool AttrListPtr::hasAttrSomewhere(Attributes Attr
) const {
234 if (AttrList
== 0) return false;
236 const SmallVector
<AttributeWithIndex
, 4> &Attrs
= AttrList
->Attrs
;
237 for (unsigned i
= 0, e
= Attrs
.size(); i
!= e
; ++i
)
238 if (Attrs
[i
].Attrs
& Attr
)
244 AttrListPtr
AttrListPtr::addAttr(unsigned Idx
, Attributes Attrs
) const {
245 Attributes OldAttrs
= getAttributes(Idx
);
247 // FIXME it is not obvious how this should work for alignment.
248 // For now, say we can't change a known alignment.
249 Attributes OldAlign
= OldAttrs
& Attribute::Alignment
;
250 Attributes NewAlign
= Attrs
& Attribute::Alignment
;
251 assert((!OldAlign
|| !NewAlign
|| OldAlign
== NewAlign
) &&
252 "Attempt to change alignment!");
255 Attributes NewAttrs
= OldAttrs
| Attrs
;
256 if (NewAttrs
== OldAttrs
)
259 SmallVector
<AttributeWithIndex
, 8> NewAttrList
;
261 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
263 const SmallVector
<AttributeWithIndex
, 4> &OldAttrList
= AttrList
->Attrs
;
264 unsigned i
= 0, e
= OldAttrList
.size();
265 // Copy attributes for arguments before this one.
266 for (; i
!= e
&& OldAttrList
[i
].Index
< Idx
; ++i
)
267 NewAttrList
.push_back(OldAttrList
[i
]);
269 // If there are attributes already at this index, merge them in.
270 if (i
!= e
&& OldAttrList
[i
].Index
== Idx
) {
271 Attrs
|= OldAttrList
[i
].Attrs
;
275 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
277 // Copy attributes for arguments after this one.
278 NewAttrList
.insert(NewAttrList
.end(),
279 OldAttrList
.begin()+i
, OldAttrList
.end());
282 return get(NewAttrList
.data(), NewAttrList
.size());
285 AttrListPtr
AttrListPtr::removeAttr(unsigned Idx
, Attributes Attrs
) const {
287 // FIXME it is not obvious how this should work for alignment.
288 // For now, say we can't pass in alignment, which no current use does.
289 assert(!(Attrs
& Attribute::Alignment
) && "Attempt to exclude alignment!");
291 if (AttrList
== 0) return AttrListPtr();
293 Attributes OldAttrs
= getAttributes(Idx
);
294 Attributes NewAttrs
= OldAttrs
& ~Attrs
;
295 if (NewAttrs
== OldAttrs
)
298 SmallVector
<AttributeWithIndex
, 8> NewAttrList
;
299 const SmallVector
<AttributeWithIndex
, 4> &OldAttrList
= AttrList
->Attrs
;
300 unsigned i
= 0, e
= OldAttrList
.size();
302 // Copy attributes for arguments before this one.
303 for (; i
!= e
&& OldAttrList
[i
].Index
< Idx
; ++i
)
304 NewAttrList
.push_back(OldAttrList
[i
]);
306 // If there are attributes already at this index, merge them in.
307 assert(OldAttrList
[i
].Index
== Idx
&& "Attribute isn't set?");
308 Attrs
= OldAttrList
[i
].Attrs
& ~Attrs
;
310 if (Attrs
) // If any attributes left for this parameter, add them.
311 NewAttrList
.push_back(AttributeWithIndex::get(Idx
, Attrs
));
313 // Copy attributes for arguments after this one.
314 NewAttrList
.insert(NewAttrList
.end(),
315 OldAttrList
.begin()+i
, OldAttrList
.end());
317 return get(NewAttrList
.data(), NewAttrList
.size());
320 void AttrListPtr::dump() const {
322 for (unsigned i
= 0; i
< getNumSlots(); ++i
) {
323 const AttributeWithIndex
&PAWI
= getSlot(i
);
324 errs() << "{" << PAWI
.Index
<< "," << PAWI
.Attrs
<< "} ";