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 "LLVMContextImpl.h"
16 #include "llvm/Type.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/FoldingSet.h"
19 #include "llvm/Support/Atomic.h"
20 #include "llvm/Support/Mutex.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/ManagedStatic.h"
23 #include "llvm/Support/raw_ostream.h"
26 //===----------------------------------------------------------------------===//
27 // Attributes Implementation
28 //===----------------------------------------------------------------------===//
30 Attributes::Attributes(uint64_t Val) : Attrs(Val) {}
32 Attributes::Attributes(LLVMContext &C, AttrVal Val)
33 : Attrs(Attributes::get(Attributes::Builder().addAttribute(Val)).Attrs) {}
35 Attributes::Attributes(AttributesImpl *A) : Attrs(A->Bits) {}
37 Attributes::Attributes(const Attributes &A) : Attrs(A.Attrs) {}
39 // FIXME: This is temporary until we have implemented the uniquified version of
41 Attributes Attributes::get(Attributes::Builder &B) {
42 return Attributes(B.Bits);
45 Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) {
46 // If there are no attributes, return an empty Attributes class.
50 // Otherwise, build a key to look up the existing attributes.
51 LLVMContextImpl *pImpl = Context.pImpl;
53 ID.AddInteger(B.Bits);
56 AttributesImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
59 // If we didn't find any existing attributes of the same shape then create a
60 // new one and insert it.
61 PA = new AttributesImpl(B.Bits);
62 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
65 // Return the AttributesList that we found or created.
66 return Attributes(PA);
69 bool Attributes::hasAttribute(AttrVal Val) const {
70 return Attrs.hasAttribute(Val);
73 bool Attributes::hasAttributes(const Attributes &A) const {
74 return Attrs.hasAttributes(A);
77 /// This returns the alignment field of an attribute as a byte alignment value.
78 unsigned Attributes::getAlignment() const {
79 if (!hasAttribute(Attributes::Alignment))
81 return 1U << ((Attrs.getAlignment() >> 16) - 1);
84 /// This returns the stack alignment field of an attribute as a byte alignment
86 unsigned Attributes::getStackAlignment() const {
87 if (!hasAttribute(Attributes::StackAlignment))
89 return 1U << ((Attrs.getStackAlignment() >> 26) - 1);
92 bool Attributes::isEmptyOrSingleton() const {
93 return Attrs.isEmptyOrSingleton();
96 Attributes Attributes::operator & (const Attributes &A) const {
97 return Attributes(Raw() & A.Raw());
99 Attributes &Attributes::operator |= (const Attributes &A) {
100 Attrs.Bits |= A.Raw();
103 Attributes &Attributes::operator &= (const Attributes &A) {
104 Attrs.Bits &= A.Raw();
108 uint64_t Attributes::Raw() const {
112 Attributes Attributes::typeIncompatible(Type *Ty) {
113 Attributes::Builder Incompatible;
115 if (!Ty->isIntegerTy())
116 // Attributes that only apply to integers.
117 Incompatible.addAttribute(Attributes::SExt)
118 .addAttribute(Attributes::ZExt);
120 if (!Ty->isPointerTy())
121 // Attributes that only apply to pointers.
122 Incompatible.addAttribute(Attributes::ByVal)
123 .addAttribute(Attributes::Nest)
124 .addAttribute(Attributes::NoAlias)
125 .addAttribute(Attributes::NoCapture)
126 .addAttribute(Attributes::StructRet);
128 return Attributes(Incompatible.Bits); // FIXME: Use Attributes::get().
131 std::string Attributes::getAsString() const {
133 if (hasAttribute(Attributes::ZExt))
134 Result += "zeroext ";
135 if (hasAttribute(Attributes::SExt))
136 Result += "signext ";
137 if (hasAttribute(Attributes::NoReturn))
138 Result += "noreturn ";
139 if (hasAttribute(Attributes::NoUnwind))
140 Result += "nounwind ";
141 if (hasAttribute(Attributes::UWTable))
142 Result += "uwtable ";
143 if (hasAttribute(Attributes::ReturnsTwice))
144 Result += "returns_twice ";
145 if (hasAttribute(Attributes::InReg))
147 if (hasAttribute(Attributes::NoAlias))
148 Result += "noalias ";
149 if (hasAttribute(Attributes::NoCapture))
150 Result += "nocapture ";
151 if (hasAttribute(Attributes::StructRet))
153 if (hasAttribute(Attributes::ByVal))
155 if (hasAttribute(Attributes::Nest))
157 if (hasAttribute(Attributes::ReadNone))
158 Result += "readnone ";
159 if (hasAttribute(Attributes::ReadOnly))
160 Result += "readonly ";
161 if (hasAttribute(Attributes::OptimizeForSize))
162 Result += "optsize ";
163 if (hasAttribute(Attributes::NoInline))
164 Result += "noinline ";
165 if (hasAttribute(Attributes::InlineHint))
166 Result += "inlinehint ";
167 if (hasAttribute(Attributes::AlwaysInline))
168 Result += "alwaysinline ";
169 if (hasAttribute(Attributes::StackProtect))
171 if (hasAttribute(Attributes::StackProtectReq))
173 if (hasAttribute(Attributes::NoRedZone))
174 Result += "noredzone ";
175 if (hasAttribute(Attributes::NoImplicitFloat))
176 Result += "noimplicitfloat ";
177 if (hasAttribute(Attributes::Naked))
179 if (hasAttribute(Attributes::NonLazyBind))
180 Result += "nonlazybind ";
181 if (hasAttribute(Attributes::AddressSafety))
182 Result += "address_safety ";
183 if (hasAttribute(Attributes::StackAlignment)) {
184 Result += "alignstack(";
185 Result += utostr(getStackAlignment());
188 if (hasAttribute(Attributes::Alignment)) {
190 Result += utostr(getAlignment());
193 // Trim the trailing space.
194 assert(!Result.empty() && "Unknown attribute!");
195 Result.erase(Result.end()-1);
199 //===----------------------------------------------------------------------===//
200 // Attributes::Builder Implementation
201 //===----------------------------------------------------------------------===//
203 Attributes::Builder &Attributes::Builder::
204 addAttribute(Attributes::AttrVal Val) {
205 Bits |= AttributesImpl::getAttrMask(Val);
209 Attributes::Builder &Attributes::Builder::addRawValue(uint64_t Val) {
214 Attributes::Builder &Attributes::Builder::addAlignmentAttr(unsigned Align) {
215 if (Align == 0) return *this;
216 assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
217 assert(Align <= 0x40000000 && "Alignment too large.");
218 Bits |= (Log2_32(Align) + 1) << 16;
221 Attributes::Builder &Attributes::Builder::addStackAlignmentAttr(unsigned Align){
222 // Default alignment, allow the target to define how to align it.
223 if (Align == 0) return *this;
224 assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
225 assert(Align <= 0x100 && "Alignment too large.");
226 Bits |= (Log2_32(Align) + 1) << 26;
230 Attributes::Builder &Attributes::Builder::
231 removeAttribute(Attributes::AttrVal Val) {
232 Bits &= ~AttributesImpl::getAttrMask(Val);
236 Attributes::Builder &Attributes::Builder::addAttributes(const Attributes &A) {
241 Attributes::Builder &Attributes::Builder::removeAttributes(const Attributes &A){
246 bool Attributes::Builder::hasAttribute(Attributes::AttrVal A) const {
247 return Bits & AttributesImpl::getAttrMask(A);
250 bool Attributes::Builder::hasAttributes() const {
253 bool Attributes::Builder::hasAttributes(const Attributes &A) const {
254 return Bits & A.Raw();
256 bool Attributes::Builder::hasAlignmentAttr() const {
257 return Bits & AttributesImpl::getAttrMask(Attributes::Alignment);
260 uint64_t Attributes::Builder::getAlignment() const {
261 if (!hasAlignmentAttr())
264 (((Bits & AttributesImpl::getAttrMask(Attributes::Alignment)) >> 16) - 1);
267 uint64_t Attributes::Builder::getStackAlignment() const {
268 if (!hasAlignmentAttr())
271 (((Bits & AttributesImpl::getAttrMask(Attributes::StackAlignment))>>26)-1);
274 //===----------------------------------------------------------------------===//
275 // AttributeImpl Definition
276 //===----------------------------------------------------------------------===//
278 uint64_t AttributesImpl::getAttrMask(uint64_t Val) {
280 case Attributes::None: return 0;
281 case Attributes::ZExt: return 1 << 0;
282 case Attributes::SExt: return 1 << 1;
283 case Attributes::NoReturn: return 1 << 2;
284 case Attributes::InReg: return 1 << 3;
285 case Attributes::StructRet: return 1 << 4;
286 case Attributes::NoUnwind: return 1 << 5;
287 case Attributes::NoAlias: return 1 << 6;
288 case Attributes::ByVal: return 1 << 7;
289 case Attributes::Nest: return 1 << 8;
290 case Attributes::ReadNone: return 1 << 9;
291 case Attributes::ReadOnly: return 1 << 10;
292 case Attributes::NoInline: return 1 << 11;
293 case Attributes::AlwaysInline: return 1 << 12;
294 case Attributes::OptimizeForSize: return 1 << 13;
295 case Attributes::StackProtect: return 1 << 14;
296 case Attributes::StackProtectReq: return 1 << 15;
297 case Attributes::Alignment: return 31 << 16;
298 case Attributes::NoCapture: return 1 << 21;
299 case Attributes::NoRedZone: return 1 << 22;
300 case Attributes::NoImplicitFloat: return 1 << 23;
301 case Attributes::Naked: return 1 << 24;
302 case Attributes::InlineHint: return 1 << 25;
303 case Attributes::StackAlignment: return 7 << 26;
304 case Attributes::ReturnsTwice: return 1 << 29;
305 case Attributes::UWTable: return 1 << 30;
306 case Attributes::NonLazyBind: return 1U << 31;
307 case Attributes::AddressSafety: return 1ULL << 32;
309 llvm_unreachable("Unsupported attribute type");
312 bool AttributesImpl::hasAttribute(uint64_t A) const {
313 return (Bits & getAttrMask(A)) != 0;
316 bool AttributesImpl::hasAttributes() const {
320 bool AttributesImpl::hasAttributes(const Attributes &A) const {
321 return Bits & A.Raw(); // FIXME: Raw() won't work here in the future.
324 uint64_t AttributesImpl::getAlignment() const {
325 return Bits & getAttrMask(Attributes::Alignment);
328 uint64_t AttributesImpl::getStackAlignment() const {
329 return Bits & getAttrMask(Attributes::StackAlignment);
332 bool AttributesImpl::isEmptyOrSingleton() const {
333 return (Bits & (Bits - 1)) == 0;
336 //===----------------------------------------------------------------------===//
337 // AttributeListImpl Definition
338 //===----------------------------------------------------------------------===//
341 class AttributeListImpl;
344 static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists;
347 static ManagedStatic<sys::SmartMutex<true> > ALMutex;
349 class AttributeListImpl : public FoldingSetNode {
350 sys::cas_flag RefCount;
352 // AttributesList is uniqued, these should not be publicly available.
353 void operator=(const AttributeListImpl &) LLVM_DELETED_FUNCTION;
354 AttributeListImpl(const AttributeListImpl &) LLVM_DELETED_FUNCTION;
355 ~AttributeListImpl(); // Private implementation
357 SmallVector<AttributeWithIndex, 4> Attrs;
359 AttributeListImpl(ArrayRef<AttributeWithIndex> attrs)
360 : Attrs(attrs.begin(), attrs.end()) {
365 sys::SmartScopedLock<true> Lock(*ALMutex);
369 sys::SmartScopedLock<true> Lock(*ALMutex);
370 if (!AttributesLists.isConstructed())
372 sys::cas_flag new_val = --RefCount;
377 void Profile(FoldingSetNodeID &ID) const {
380 static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeWithIndex> Attrs){
381 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
382 ID.AddInteger(Attrs[i].Attrs.Raw());
383 ID.AddInteger(Attrs[i].Index);
389 AttributeListImpl::~AttributeListImpl() {
390 // NOTE: Lock must be acquired by caller.
391 AttributesLists->RemoveNode(this);
395 AttrListPtr AttrListPtr::get(ArrayRef<AttributeWithIndex> Attrs) {
396 // If there are no attributes then return a null AttributesList pointer.
398 return AttrListPtr();
401 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
402 assert(Attrs[i].Attrs.hasAttributes() &&
403 "Pointless attribute!");
404 assert((!i || Attrs[i-1].Index < Attrs[i].Index) &&
405 "Misordered AttributesList!");
409 // Otherwise, build a key to look up the existing attributes.
411 AttributeListImpl::Profile(ID, Attrs);
414 sys::SmartScopedLock<true> Lock(*ALMutex);
416 AttributeListImpl *PAL =
417 AttributesLists->FindNodeOrInsertPos(ID, InsertPos);
419 // If we didn't find any existing attributes of the same shape then
420 // create a new one and insert it.
422 PAL = new AttributeListImpl(Attrs);
423 AttributesLists->InsertNode(PAL, InsertPos);
426 // Return the AttributesList that we found or created.
427 return AttrListPtr(PAL);
431 //===----------------------------------------------------------------------===//
432 // AttrListPtr Method Implementations
433 //===----------------------------------------------------------------------===//
435 AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) {
436 if (LI) LI->AddRef();
439 AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) {
440 if (AttrList) AttrList->AddRef();
443 const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) {
444 sys::SmartScopedLock<true> Lock(*ALMutex);
445 if (AttrList == RHS.AttrList) return *this;
446 if (AttrList) AttrList->DropRef();
447 AttrList = RHS.AttrList;
448 if (AttrList) AttrList->AddRef();
452 AttrListPtr::~AttrListPtr() {
453 if (AttrList) AttrList->DropRef();
456 /// getNumSlots - Return the number of slots used in this attribute list.
457 /// This is the number of arguments that have an attribute set on them
458 /// (including the function itself).
459 unsigned AttrListPtr::getNumSlots() const {
460 return AttrList ? AttrList->Attrs.size() : 0;
463 /// getSlot - Return the AttributeWithIndex at the specified slot. This
464 /// holds a number plus a set of attributes.
465 const AttributeWithIndex &AttrListPtr::getSlot(unsigned Slot) const {
466 assert(AttrList && Slot < AttrList->Attrs.size() && "Slot # out of range!");
467 return AttrList->Attrs[Slot];
471 /// getAttributes - The attributes for the specified index are
472 /// returned. Attributes for the result are denoted with Idx = 0.
473 /// Function notes are denoted with idx = ~0.
474 Attributes AttrListPtr::getAttributes(unsigned Idx) const {
475 if (AttrList == 0) return Attributes();
477 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
478 for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i)
479 if (Attrs[i].Index == Idx)
480 return Attrs[i].Attrs;
485 /// hasAttrSomewhere - Return true if the specified attribute is set for at
486 /// least one parameter or for the return value.
487 bool AttrListPtr::hasAttrSomewhere(Attributes::AttrVal Attr) const {
488 if (AttrList == 0) return false;
490 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
491 for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
492 if (Attrs[i].Attrs.hasAttribute(Attr))
497 unsigned AttrListPtr::getNumAttrs() const {
498 return AttrList ? AttrList->Attrs.size() : 0;
501 Attributes &AttrListPtr::getAttributesAtIndex(unsigned i) const {
502 assert(AttrList && "Trying to get an attribute from an empty list!");
503 assert(i < AttrList->Attrs.size() && "Index out of range!");
504 return AttrList->Attrs[i].Attrs;
507 AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const {
508 Attributes OldAttrs = getAttributes(Idx);
510 // FIXME it is not obvious how this should work for alignment.
511 // For now, say we can't change a known alignment.
512 unsigned OldAlign = OldAttrs.getAlignment();
513 unsigned NewAlign = Attrs.getAlignment();
514 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
515 "Attempt to change alignment!");
518 Attributes::Builder NewAttrs =
519 Attributes::Builder(OldAttrs).addAttributes(Attrs);
520 if (NewAttrs == Attributes::Builder(OldAttrs))
523 SmallVector<AttributeWithIndex, 8> NewAttrList;
525 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
527 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
528 unsigned i = 0, e = OldAttrList.size();
529 // Copy attributes for arguments before this one.
530 for (; i != e && OldAttrList[i].Index < Idx; ++i)
531 NewAttrList.push_back(OldAttrList[i]);
533 // If there are attributes already at this index, merge them in.
534 if (i != e && OldAttrList[i].Index == Idx) {
535 Attrs |= OldAttrList[i].Attrs;
539 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
541 // Copy attributes for arguments after this one.
542 NewAttrList.insert(NewAttrList.end(),
543 OldAttrList.begin()+i, OldAttrList.end());
546 return get(NewAttrList);
549 AttrListPtr AttrListPtr::removeAttr(LLVMContext &C, unsigned Idx,
550 Attributes Attrs) const {
552 // FIXME it is not obvious how this should work for alignment.
553 // For now, say we can't pass in alignment, which no current use does.
554 assert(!Attrs.hasAttribute(Attributes::Alignment) &&
555 "Attempt to exclude alignment!");
557 if (AttrList == 0) return AttrListPtr();
559 Attributes OldAttrs = getAttributes(Idx);
560 Attributes::Builder NewAttrs =
561 Attributes::Builder(OldAttrs).removeAttributes(Attrs);
562 if (NewAttrs == Attributes::Builder(OldAttrs))
565 SmallVector<AttributeWithIndex, 8> NewAttrList;
566 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
567 unsigned i = 0, e = OldAttrList.size();
569 // Copy attributes for arguments before this one.
570 for (; i != e && OldAttrList[i].Index < Idx; ++i)
571 NewAttrList.push_back(OldAttrList[i]);
573 // If there are attributes already at this index, merge them in.
574 assert(OldAttrList[i].Index == Idx && "Attribute isn't set?");
575 Attrs = Attributes::get(C, Attributes::Builder(OldAttrList[i].Attrs).
576 removeAttributes(Attrs));
578 if (Attrs) // If any attributes left for this parameter, add them.
579 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
581 // Copy attributes for arguments after this one.
582 NewAttrList.insert(NewAttrList.end(),
583 OldAttrList.begin()+i, OldAttrList.end());
585 return get(NewAttrList);
588 void AttrListPtr::dump() const {
590 for (unsigned i = 0; i < getNumSlots(); ++i) {
591 const AttributeWithIndex &PAWI = getSlot(i);
592 dbgs() << "{" << PAWI.Index << "," << PAWI.Attrs << "} ";