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 "AttributesImpl.h"
16 #include "LLVMContextImpl.h"
17 #include "llvm/Type.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/FoldingSet.h"
20 #include "llvm/Support/Atomic.h"
21 #include "llvm/Support/Mutex.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/ManagedStatic.h"
24 #include "llvm/Support/raw_ostream.h"
27 //===----------------------------------------------------------------------===//
28 // Attribute Function Definitions
29 //===----------------------------------------------------------------------===//
31 bool Attributes::hasAddressSafetyAttr() const {
32 return Bits & Attribute::AddressSafety_i;
34 bool Attributes::hasAlignmentAttr() const {
35 return Bits & Attribute::Alignment_i;
37 bool Attributes::hasAlwaysInlineAttr() const {
38 return Bits & Attribute::AlwaysInline_i;
40 bool Attributes::hasByValAttr() const {
41 return Bits & Attribute::ByVal_i;
43 bool Attributes::hasInlineHintAttr() const {
44 return Bits & Attribute::InlineHint_i;
46 bool Attributes::hasInRegAttr() const {
47 return Bits & Attribute::InReg_i;
49 bool Attributes::hasNakedAttr() const {
50 return Bits & Attribute::Naked_i;
52 bool Attributes::hasNestAttr() const {
53 return Bits & Attribute::Nest_i;
55 bool Attributes::hasNoAliasAttr() const {
56 return Bits & Attribute::NoAlias_i;
58 bool Attributes::hasNoCaptureAttr() const {
59 return Bits & Attribute::NoCapture_i;
61 bool Attributes::hasNoImplicitFloatAttr() const {
62 return Bits & Attribute::NoImplicitFloat_i;
64 bool Attributes::hasNoInlineAttr() const {
65 return Bits & Attribute::NoInline_i;
67 bool Attributes::hasNonLazyBindAttr() const {
68 return Bits & Attribute::NonLazyBind_i;
70 bool Attributes::hasNoRedZoneAttr() const {
71 return Bits & Attribute::NoRedZone_i;
73 bool Attributes::hasNoReturnAttr() const {
74 return Bits & Attribute::NoReturn_i;
76 bool Attributes::hasNoUnwindAttr() const {
77 return Bits & Attribute::NoUnwind_i;
79 bool Attributes::hasOptimizeForSizeAttr() const {
80 return Bits & Attribute::OptimizeForSize_i;
82 bool Attributes::hasReadNoneAttr() const {
83 return Bits & Attribute::ReadNone_i;
85 bool Attributes::hasReadOnlyAttr() const {
86 return Bits & Attribute::ReadOnly_i;
88 bool Attributes::hasReturnsTwiceAttr() const {
89 return Bits & Attribute::ReturnsTwice_i;
91 bool Attributes::hasSExtAttr() const {
92 return Bits & Attribute::SExt_i;
94 bool Attributes::hasStackAlignmentAttr() const {
95 return Bits & Attribute::StackAlignment_i;
97 bool Attributes::hasStackProtectAttr() const {
98 return Bits & Attribute::StackProtect_i;
100 bool Attributes::hasStackProtectReqAttr() const {
101 return Bits & Attribute::StackProtectReq_i;
103 bool Attributes::hasStructRetAttr() const {
104 return Bits & Attribute::StructRet_i;
106 bool Attributes::hasUWTableAttr() const {
107 return Bits & Attribute::UWTable_i;
109 bool Attributes::hasZExtAttr() const {
110 return Bits & Attribute::ZExt_i;
113 /// This returns the alignment field of an attribute as a byte alignment value.
114 unsigned Attributes::getAlignment() const {
115 if (!hasAlignmentAttr())
117 return 1U << (((Bits & Attribute::Alignment_i) >> 16) - 1);
120 /// This returns the stack alignment field of an attribute as a byte alignment
122 unsigned Attributes::getStackAlignment() const {
123 if (!hasStackAlignmentAttr())
125 return 1U << (((Bits & Attribute::StackAlignment_i) >> 26) - 1);
128 Attributes Attributes::typeIncompatible(Type *Ty) {
129 Attributes::Builder Incompatible;
131 if (!Ty->isIntegerTy()) {
132 // Attributes that only apply to integers.
133 Incompatible.addSExtAttr();
134 Incompatible.addZExtAttr();
137 if (!Ty->isPointerTy()) {
138 // Attributes that only apply to pointers.
139 Incompatible.addByValAttr();
140 Incompatible.addNestAttr();
141 Incompatible.addNoAliasAttr();
142 Incompatible.addNoCaptureAttr();
143 Incompatible.addStructRetAttr();
146 return Attributes(Incompatible.Bits); // FIXME: Use Attributes::get().
149 std::string Attributes::getAsString() const {
152 Result += "zeroext ";
154 Result += "signext ";
155 if (hasNoReturnAttr())
156 Result += "noreturn ";
157 if (hasNoUnwindAttr())
158 Result += "nounwind ";
159 if (hasUWTableAttr())
160 Result += "uwtable ";
161 if (hasReturnsTwiceAttr())
162 Result += "returns_twice ";
165 if (hasNoAliasAttr())
166 Result += "noalias ";
167 if (hasNoCaptureAttr())
168 Result += "nocapture ";
169 if (hasStructRetAttr())
175 if (hasReadNoneAttr())
176 Result += "readnone ";
177 if (hasReadOnlyAttr())
178 Result += "readonly ";
179 if (hasOptimizeForSizeAttr())
180 Result += "optsize ";
181 if (hasNoInlineAttr())
182 Result += "noinline ";
183 if (hasInlineHintAttr())
184 Result += "inlinehint ";
185 if (hasAlwaysInlineAttr())
186 Result += "alwaysinline ";
187 if (hasStackProtectAttr())
189 if (hasStackProtectReqAttr())
191 if (hasNoRedZoneAttr())
192 Result += "noredzone ";
193 if (hasNoImplicitFloatAttr())
194 Result += "noimplicitfloat ";
197 if (hasNonLazyBindAttr())
198 Result += "nonlazybind ";
199 if (hasAddressSafetyAttr())
200 Result += "address_safety ";
201 if (hasStackAlignmentAttr()) {
202 Result += "alignstack(";
203 Result += utostr(getStackAlignment());
206 if (hasAlignmentAttr()) {
208 Result += utostr(getAlignment());
211 // Trim the trailing space.
212 assert(!Result.empty() && "Unknown attribute!");
213 Result.erase(Result.end()-1);
217 //===----------------------------------------------------------------------===//
218 // Attributes::Builder Implementation
219 //===----------------------------------------------------------------------===//
221 void Attributes::Builder::addAddressSafetyAttr() {
222 Bits |= Attribute::AddressSafety_i;
224 void Attributes::Builder::addAlwaysInlineAttr() {
225 Bits |= Attribute::AlwaysInline_i;
227 void Attributes::Builder::addByValAttr() {
228 Bits |= Attribute::ByVal_i;
230 void Attributes::Builder::addInlineHintAttr() {
231 Bits |= Attribute::InlineHint_i;
233 void Attributes::Builder::addInRegAttr() {
234 Bits |= Attribute::InReg_i;
236 void Attributes::Builder::addNakedAttr() {
237 Bits |= Attribute::Naked_i;
239 void Attributes::Builder::addNestAttr() {
240 Bits |= Attribute::Nest_i;
242 void Attributes::Builder::addNoAliasAttr() {
243 Bits |= Attribute::NoAlias_i;
245 void Attributes::Builder::addNoCaptureAttr() {
246 Bits |= Attribute::NoCapture_i;
248 void Attributes::Builder::addNoImplicitFloatAttr() {
249 Bits |= Attribute::NoImplicitFloat_i;
251 void Attributes::Builder::addNoInlineAttr() {
252 Bits |= Attribute::NoInline_i;
254 void Attributes::Builder::addNonLazyBindAttr() {
255 Bits |= Attribute::NonLazyBind_i;
257 void Attributes::Builder::addNoRedZoneAttr() {
258 Bits |= Attribute::NoRedZone_i;
260 void Attributes::Builder::addNoReturnAttr() {
261 Bits |= Attribute::NoReturn_i;
263 void Attributes::Builder::addNoUnwindAttr() {
264 Bits |= Attribute::NoUnwind_i;
266 void Attributes::Builder::addOptimizeForSizeAttr() {
267 Bits |= Attribute::OptimizeForSize_i;
269 void Attributes::Builder::addReadNoneAttr() {
270 Bits |= Attribute::ReadNone_i;
272 void Attributes::Builder::addReadOnlyAttr() {
273 Bits |= Attribute::ReadOnly_i;
275 void Attributes::Builder::addReturnsTwiceAttr() {
276 Bits |= Attribute::ReturnsTwice_i;
278 void Attributes::Builder::addSExtAttr() {
279 Bits |= Attribute::SExt_i;
281 void Attributes::Builder::addStackProtectAttr() {
282 Bits |= Attribute::StackProtect_i;
284 void Attributes::Builder::addStackProtectReqAttr() {
285 Bits |= Attribute::StackProtectReq_i;
287 void Attributes::Builder::addStructRetAttr() {
288 Bits |= Attribute::StructRet_i;
290 void Attributes::Builder::addUWTableAttr() {
291 Bits |= Attribute::UWTable_i;
293 void Attributes::Builder::addZExtAttr() {
294 Bits |= Attribute::ZExt_i;
297 void Attributes::Builder::addAlignmentAttr(unsigned Align) {
298 if (Align == 0) return;
299 assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
300 assert(Align <= 0x40000000 && "Alignment too large.");
301 Bits |= (Log2_32(Align) + 1) << 16;
303 void Attributes::Builder::addStackAlignmentAttr(unsigned Align) {
304 // Default alignment, allow the target to define how to align it.
305 if (Align == 0) return;
306 assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
307 assert(Align <= 0x100 && "Alignment too large.");
308 Bits |= (Log2_32(Align) + 1) << 26;
311 //===----------------------------------------------------------------------===//
312 // AttributeImpl Definition
313 //===----------------------------------------------------------------------===//
315 Attributes::Attributes(AttributesImpl *A) : Bits(0) {}
317 Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) {
318 // If there are no attributes, return an empty Attributes class.
322 // Otherwise, build a key to look up the existing attributes.
323 LLVMContextImpl *pImpl = Context.pImpl;
325 ID.AddInteger(B.Bits);
328 AttributesImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
331 // If we didn't find any existing attributes of the same shape then create a
332 // new one and insert it.
333 PA = new AttributesImpl(B.Bits);
334 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
337 // Return the AttributesList that we found or created.
338 return Attributes(PA);
341 //===----------------------------------------------------------------------===//
342 // AttributeListImpl Definition
343 //===----------------------------------------------------------------------===//
346 class AttributeListImpl;
349 static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists;
352 static ManagedStatic<sys::SmartMutex<true> > ALMutex;
354 class AttributeListImpl : public FoldingSetNode {
355 sys::cas_flag RefCount;
357 // AttributesList is uniqued, these should not be publicly available.
358 void operator=(const AttributeListImpl &) LLVM_DELETED_FUNCTION;
359 AttributeListImpl(const AttributeListImpl &) LLVM_DELETED_FUNCTION;
360 ~AttributeListImpl(); // Private implementation
362 SmallVector<AttributeWithIndex, 4> Attrs;
364 AttributeListImpl(ArrayRef<AttributeWithIndex> attrs)
365 : Attrs(attrs.begin(), attrs.end()) {
370 sys::SmartScopedLock<true> Lock(*ALMutex);
374 sys::SmartScopedLock<true> Lock(*ALMutex);
375 if (!AttributesLists.isConstructed())
377 sys::cas_flag new_val = --RefCount;
382 void Profile(FoldingSetNodeID &ID) const {
385 static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeWithIndex> Attrs){
386 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
387 ID.AddInteger(Attrs[i].Attrs.Raw());
388 ID.AddInteger(Attrs[i].Index);
394 AttributeListImpl::~AttributeListImpl() {
395 // NOTE: Lock must be acquired by caller.
396 AttributesLists->RemoveNode(this);
400 AttrListPtr AttrListPtr::get(ArrayRef<AttributeWithIndex> Attrs) {
401 // If there are no attributes then return a null AttributesList pointer.
403 return AttrListPtr();
406 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
407 assert(Attrs[i].Attrs.hasAttributes() &&
408 "Pointless attribute!");
409 assert((!i || Attrs[i-1].Index < Attrs[i].Index) &&
410 "Misordered AttributesList!");
414 // Otherwise, build a key to look up the existing attributes.
416 AttributeListImpl::Profile(ID, Attrs);
419 sys::SmartScopedLock<true> Lock(*ALMutex);
421 AttributeListImpl *PAL =
422 AttributesLists->FindNodeOrInsertPos(ID, InsertPos);
424 // If we didn't find any existing attributes of the same shape then
425 // create a new one and insert it.
427 PAL = new AttributeListImpl(Attrs);
428 AttributesLists->InsertNode(PAL, InsertPos);
431 // Return the AttributesList that we found or created.
432 return AttrListPtr(PAL);
436 //===----------------------------------------------------------------------===//
437 // AttrListPtr Method Implementations
438 //===----------------------------------------------------------------------===//
440 AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) {
441 if (LI) LI->AddRef();
444 AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) {
445 if (AttrList) AttrList->AddRef();
448 const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) {
449 sys::SmartScopedLock<true> Lock(*ALMutex);
450 if (AttrList == RHS.AttrList) return *this;
451 if (AttrList) AttrList->DropRef();
452 AttrList = RHS.AttrList;
453 if (AttrList) AttrList->AddRef();
457 AttrListPtr::~AttrListPtr() {
458 if (AttrList) AttrList->DropRef();
461 /// getNumSlots - Return the number of slots used in this attribute list.
462 /// This is the number of arguments that have an attribute set on them
463 /// (including the function itself).
464 unsigned AttrListPtr::getNumSlots() const {
465 return AttrList ? AttrList->Attrs.size() : 0;
468 /// getSlot - Return the AttributeWithIndex at the specified slot. This
469 /// holds a number plus a set of attributes.
470 const AttributeWithIndex &AttrListPtr::getSlot(unsigned Slot) const {
471 assert(AttrList && Slot < AttrList->Attrs.size() && "Slot # out of range!");
472 return AttrList->Attrs[Slot];
476 /// getAttributes - The attributes for the specified index are
477 /// returned. Attributes for the result are denoted with Idx = 0.
478 /// Function notes are denoted with idx = ~0.
479 Attributes AttrListPtr::getAttributes(unsigned Idx) const {
480 if (AttrList == 0) return Attributes();
482 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
483 for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i)
484 if (Attrs[i].Index == Idx)
485 return Attrs[i].Attrs;
490 /// hasAttrSomewhere - Return true if the specified attribute is set for at
491 /// least one parameter or for the return value.
492 bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const {
493 if (AttrList == 0) return false;
495 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
496 for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
497 if (Attrs[i].Attrs.hasAttributes(Attr))
503 AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const {
504 Attributes OldAttrs = getAttributes(Idx);
506 // FIXME it is not obvious how this should work for alignment.
507 // For now, say we can't change a known alignment.
508 unsigned OldAlign = OldAttrs.getAlignment();
509 unsigned NewAlign = Attrs.getAlignment();
510 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
511 "Attempt to change alignment!");
514 Attributes NewAttrs = OldAttrs | Attrs;
515 if (NewAttrs == OldAttrs)
518 SmallVector<AttributeWithIndex, 8> NewAttrList;
520 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
522 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
523 unsigned i = 0, e = OldAttrList.size();
524 // Copy attributes for arguments before this one.
525 for (; i != e && OldAttrList[i].Index < Idx; ++i)
526 NewAttrList.push_back(OldAttrList[i]);
528 // If there are attributes already at this index, merge them in.
529 if (i != e && OldAttrList[i].Index == Idx) {
530 Attrs |= OldAttrList[i].Attrs;
534 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
536 // Copy attributes for arguments after this one.
537 NewAttrList.insert(NewAttrList.end(),
538 OldAttrList.begin()+i, OldAttrList.end());
541 return get(NewAttrList);
544 AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const {
546 // FIXME it is not obvious how this should work for alignment.
547 // For now, say we can't pass in alignment, which no current use does.
548 assert(!Attrs.hasAlignmentAttr() && "Attempt to exclude alignment!");
550 if (AttrList == 0) return AttrListPtr();
552 Attributes OldAttrs = getAttributes(Idx);
553 Attributes NewAttrs = OldAttrs & ~Attrs;
554 if (NewAttrs == OldAttrs)
557 SmallVector<AttributeWithIndex, 8> NewAttrList;
558 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
559 unsigned i = 0, e = OldAttrList.size();
561 // Copy attributes for arguments before this one.
562 for (; i != e && OldAttrList[i].Index < Idx; ++i)
563 NewAttrList.push_back(OldAttrList[i]);
565 // If there are attributes already at this index, merge them in.
566 assert(OldAttrList[i].Index == Idx && "Attribute isn't set?");
567 Attrs = OldAttrList[i].Attrs & ~Attrs;
569 if (Attrs) // If any attributes left for this parameter, add them.
570 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
572 // Copy attributes for arguments after this one.
573 NewAttrList.insert(NewAttrList.end(),
574 OldAttrList.begin()+i, OldAttrList.end());
576 return get(NewAttrList);
579 void AttrListPtr::dump() const {
581 for (unsigned i = 0; i < getNumSlots(); ++i) {
582 const AttributeWithIndex &PAWI = getSlot(i);
583 dbgs() << "{" << PAWI.Index << "," << PAWI.Attrs << "} ";