12f0699c02a3e7b22a8011151a939099778172db
[oota-llvm.git] / lib / VMCore / Attributes.cpp
1 //===-- Attributes.cpp - Implement AttributesList -------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the AttributesList class and Attribute utilities.
11 //
12 //===----------------------------------------------------------------------===//
13
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"
25 using namespace llvm;
26
27 //===----------------------------------------------------------------------===//
28 // Attribute Function Definitions
29 //===----------------------------------------------------------------------===//
30
31 bool Attributes::hasAddressSafetyAttr() const {
32   return Bits & Attribute::AddressSafety_i;
33 }
34 bool Attributes::hasAlignmentAttr() const {
35   return Bits & Attribute::Alignment_i;
36 }
37 bool Attributes::hasAlwaysInlineAttr() const {
38   return Bits & Attribute::AlwaysInline_i;
39 }
40 bool Attributes::hasByValAttr() const {
41   return Bits & Attribute::ByVal_i;
42 }
43 bool Attributes::hasInlineHintAttr() const {
44   return Bits & Attribute::InlineHint_i;
45 }
46 bool Attributes::hasInRegAttr() const {
47   return Bits & Attribute::InReg_i;
48 }
49 bool Attributes::hasNakedAttr() const {
50   return Bits & Attribute::Naked_i;
51 }
52 bool Attributes::hasNestAttr() const {
53   return Bits & Attribute::Nest_i;
54 }
55 bool Attributes::hasNoAliasAttr() const {
56   return Bits & Attribute::NoAlias_i;
57 }
58 bool Attributes::hasNoCaptureAttr() const {
59   return Bits & Attribute::NoCapture_i;
60 }
61 bool Attributes::hasNoImplicitFloatAttr() const {
62   return Bits & Attribute::NoImplicitFloat_i;
63 }
64 bool Attributes::hasNoInlineAttr() const {
65   return Bits & Attribute::NoInline_i;
66 }
67 bool Attributes::hasNonLazyBindAttr() const {
68   return Bits & Attribute::NonLazyBind_i;
69 }
70 bool Attributes::hasNoRedZoneAttr() const {
71   return Bits & Attribute::NoRedZone_i;
72 }
73 bool Attributes::hasNoReturnAttr() const {
74   return Bits & Attribute::NoReturn_i;
75 }
76 bool Attributes::hasNoUnwindAttr() const {
77   return Bits & Attribute::NoUnwind_i;
78 }
79 bool Attributes::hasOptimizeForSizeAttr() const {
80   return Bits & Attribute::OptimizeForSize_i;
81 }
82 bool Attributes::hasReadNoneAttr() const {
83   return Bits & Attribute::ReadNone_i;
84 }
85 bool Attributes::hasReadOnlyAttr() const {
86   return Bits & Attribute::ReadOnly_i;
87 }
88 bool Attributes::hasReturnsTwiceAttr() const {
89   return Bits & Attribute::ReturnsTwice_i;
90 }
91 bool Attributes::hasSExtAttr() const {
92   return Bits & Attribute::SExt_i;
93 }
94 bool Attributes::hasStackAlignmentAttr() const {
95   return Bits & Attribute::StackAlignment_i;
96 }
97 bool Attributes::hasStackProtectAttr() const {
98   return Bits & Attribute::StackProtect_i;
99 }
100 bool Attributes::hasStackProtectReqAttr() const {
101   return Bits & Attribute::StackProtectReq_i;
102 }
103 bool Attributes::hasStructRetAttr() const {
104   return Bits & Attribute::StructRet_i;
105 }
106 bool Attributes::hasUWTableAttr() const {
107   return Bits & Attribute::UWTable_i;
108 }
109 bool Attributes::hasZExtAttr() const {
110   return Bits & Attribute::ZExt_i;
111 }
112
113 /// This returns the alignment field of an attribute as a byte alignment value.
114 unsigned Attributes::getAlignment() const {
115   if (!hasAlignmentAttr())
116     return 0;
117   return 1U << (((Bits & Attribute::Alignment_i) >> 16) - 1);
118 }
119
120 /// This returns the stack alignment field of an attribute as a byte alignment
121 /// value.
122 unsigned Attributes::getStackAlignment() const {
123   if (!hasStackAlignmentAttr())
124     return 0;
125   return 1U << (((Bits & Attribute::StackAlignment_i) >> 26) - 1);
126 }
127
128 Attributes Attributes::typeIncompatible(Type *Ty) {
129   Attributes::Builder Incompatible;
130   
131   if (!Ty->isIntegerTy()) {
132     // Attributes that only apply to integers.
133     Incompatible.addSExtAttr();
134     Incompatible.addZExtAttr();
135   }
136   
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();
144   }
145   
146   return Attributes(Incompatible.Bits); // FIXME: Use Attributes::get().
147 }
148
149 std::string Attributes::getAsString() const {
150   std::string Result;
151   if (hasZExtAttr())
152     Result += "zeroext ";
153   if (hasSExtAttr())
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 ";
163   if (hasInRegAttr())
164     Result += "inreg ";
165   if (hasNoAliasAttr())
166     Result += "noalias ";
167   if (hasNoCaptureAttr())
168     Result += "nocapture ";
169   if (hasStructRetAttr())
170     Result += "sret ";
171   if (hasByValAttr())
172     Result += "byval ";
173   if (hasNestAttr())
174     Result += "nest ";
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())
188     Result += "ssp ";
189   if (hasStackProtectReqAttr())
190     Result += "sspreq ";
191   if (hasNoRedZoneAttr())
192     Result += "noredzone ";
193   if (hasNoImplicitFloatAttr())
194     Result += "noimplicitfloat ";
195   if (hasNakedAttr())
196     Result += "naked ";
197   if (hasNonLazyBindAttr())
198     Result += "nonlazybind ";
199   if (hasAddressSafetyAttr())
200     Result += "address_safety ";
201   if (hasStackAlignmentAttr()) {
202     Result += "alignstack(";
203     Result += utostr(getStackAlignment());
204     Result += ") ";
205   }
206   if (hasAlignmentAttr()) {
207     Result += "align ";
208     Result += utostr(getAlignment());
209     Result += " ";
210   }
211   // Trim the trailing space.
212   assert(!Result.empty() && "Unknown attribute!");
213   Result.erase(Result.end()-1);
214   return Result;
215 }
216
217 //===----------------------------------------------------------------------===//
218 // Attributes::Builder Implementation
219 //===----------------------------------------------------------------------===//
220
221 void Attributes::Builder::addAddressSafetyAttr() {
222   Bits |= Attribute::AddressSafety_i;
223 }
224 void Attributes::Builder::addAlwaysInlineAttr() {
225   Bits |= Attribute::AlwaysInline_i;
226 }
227 void Attributes::Builder::addByValAttr() {
228   Bits |= Attribute::ByVal_i;
229 }
230 void Attributes::Builder::addInlineHintAttr() {
231   Bits |= Attribute::InlineHint_i;
232 }
233 void Attributes::Builder::addInRegAttr() {
234   Bits |= Attribute::InReg_i;
235 }
236 void Attributes::Builder::addNakedAttr() {
237   Bits |= Attribute::Naked_i;
238 }
239 void Attributes::Builder::addNestAttr() {
240   Bits |= Attribute::Nest_i;
241 }
242 void Attributes::Builder::addNoAliasAttr() {
243   Bits |= Attribute::NoAlias_i;
244 }
245 void Attributes::Builder::addNoCaptureAttr() {
246   Bits |= Attribute::NoCapture_i;
247 }
248 void Attributes::Builder::addNoImplicitFloatAttr() {
249   Bits |= Attribute::NoImplicitFloat_i;
250 }
251 void Attributes::Builder::addNoInlineAttr() {
252   Bits |= Attribute::NoInline_i;
253 }
254 void Attributes::Builder::addNonLazyBindAttr() {
255   Bits |= Attribute::NonLazyBind_i;
256 }
257 void Attributes::Builder::addNoRedZoneAttr() {
258   Bits |= Attribute::NoRedZone_i;
259 }
260 void Attributes::Builder::addNoReturnAttr() {
261   Bits |= Attribute::NoReturn_i;
262 }
263 void Attributes::Builder::addNoUnwindAttr() {
264   Bits |= Attribute::NoUnwind_i;
265 }
266 void Attributes::Builder::addOptimizeForSizeAttr() {
267   Bits |= Attribute::OptimizeForSize_i;
268 }
269 void Attributes::Builder::addReadNoneAttr() {
270   Bits |= Attribute::ReadNone_i;
271 }
272 void Attributes::Builder::addReadOnlyAttr() {
273   Bits |= Attribute::ReadOnly_i;
274 }
275 void Attributes::Builder::addReturnsTwiceAttr() {
276   Bits |= Attribute::ReturnsTwice_i;
277 }
278 void Attributes::Builder::addSExtAttr() {
279   Bits |= Attribute::SExt_i;
280 }
281 void Attributes::Builder::addStackProtectAttr() {
282   Bits |= Attribute::StackProtect_i;
283 }
284 void Attributes::Builder::addStackProtectReqAttr() {
285   Bits |= Attribute::StackProtectReq_i;
286 }
287 void Attributes::Builder::addStructRetAttr() {
288   Bits |= Attribute::StructRet_i;
289 }
290 void Attributes::Builder::addUWTableAttr() {
291   Bits |= Attribute::UWTable_i;
292 }
293 void Attributes::Builder::addZExtAttr() {
294   Bits |= Attribute::ZExt_i;
295 }
296
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;
302 }
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;
309 }
310
311 //===----------------------------------------------------------------------===//
312 // AttributeImpl Definition
313 //===----------------------------------------------------------------------===//
314
315 Attributes::Attributes(AttributesImpl *A) : Bits(0) {}
316
317 Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) {
318   // If there are no attributes, return an empty Attributes class.
319   if (B.Bits == 0)
320     return Attributes();
321
322   // Otherwise, build a key to look up the existing attributes.
323   LLVMContextImpl *pImpl = Context.pImpl;
324   FoldingSetNodeID ID;
325   ID.AddInteger(B.Bits);
326
327   void *InsertPoint;
328   AttributesImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
329
330   if (!PA) {
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);
335   }
336
337   // Return the AttributesList that we found or created.
338   return Attributes(PA);
339 }
340
341 //===----------------------------------------------------------------------===//
342 // AttributeListImpl Definition
343 //===----------------------------------------------------------------------===//
344
345 namespace llvm {
346   class AttributeListImpl;
347 }
348
349 static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists;
350
351 namespace llvm {
352 static ManagedStatic<sys::SmartMutex<true> > ALMutex;
353
354 class AttributeListImpl : public FoldingSetNode {
355   sys::cas_flag RefCount;
356   
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
361 public:
362   SmallVector<AttributeWithIndex, 4> Attrs;
363   
364   AttributeListImpl(ArrayRef<AttributeWithIndex> attrs)
365     : Attrs(attrs.begin(), attrs.end()) {
366     RefCount = 0;
367   }
368   
369   void AddRef() {
370     sys::SmartScopedLock<true> Lock(*ALMutex);
371     ++RefCount;
372   }
373   void DropRef() {
374     sys::SmartScopedLock<true> Lock(*ALMutex);
375     if (!AttributesLists.isConstructed())
376       return;
377     sys::cas_flag new_val = --RefCount;
378     if (new_val == 0)
379       delete this;
380   }
381   
382   void Profile(FoldingSetNodeID &ID) const {
383     Profile(ID, Attrs);
384   }
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);
389     }
390   }
391 };
392 }
393
394 AttributeListImpl::~AttributeListImpl() {
395   // NOTE: Lock must be acquired by caller.
396   AttributesLists->RemoveNode(this);
397 }
398
399
400 AttrListPtr AttrListPtr::get(ArrayRef<AttributeWithIndex> Attrs) {
401   // If there are no attributes then return a null AttributesList pointer.
402   if (Attrs.empty())
403     return AttrListPtr();
404   
405 #ifndef NDEBUG
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!");
411   }
412 #endif
413   
414   // Otherwise, build a key to look up the existing attributes.
415   FoldingSetNodeID ID;
416   AttributeListImpl::Profile(ID, Attrs);
417   void *InsertPos;
418   
419   sys::SmartScopedLock<true> Lock(*ALMutex);
420   
421   AttributeListImpl *PAL =
422     AttributesLists->FindNodeOrInsertPos(ID, InsertPos);
423   
424   // If we didn't find any existing attributes of the same shape then
425   // create a new one and insert it.
426   if (!PAL) {
427     PAL = new AttributeListImpl(Attrs);
428     AttributesLists->InsertNode(PAL, InsertPos);
429   }
430   
431   // Return the AttributesList that we found or created.
432   return AttrListPtr(PAL);
433 }
434
435
436 //===----------------------------------------------------------------------===//
437 // AttrListPtr Method Implementations
438 //===----------------------------------------------------------------------===//
439
440 AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) {
441   if (LI) LI->AddRef();
442 }
443
444 AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) {
445   if (AttrList) AttrList->AddRef();  
446 }
447
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();
454   return *this;
455 }
456
457 AttrListPtr::~AttrListPtr() {
458   if (AttrList) AttrList->DropRef();
459 }
460
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;
466 }
467
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];
473 }
474
475
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();
481   
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;
486
487   return Attributes();
488 }
489
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;
494   
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))
498       return true;
499   return false;
500 }
501
502
503 AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const {
504   Attributes OldAttrs = getAttributes(Idx);
505 #ifndef NDEBUG
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!");
512 #endif
513   
514   Attributes NewAttrs = OldAttrs | Attrs;
515   if (NewAttrs == OldAttrs)
516     return *this;
517   
518   SmallVector<AttributeWithIndex, 8> NewAttrList;
519   if (AttrList == 0)
520     NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
521   else {
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]);
527
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;
531       ++i;
532     }
533     
534     NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
535     
536     // Copy attributes for arguments after this one.
537     NewAttrList.insert(NewAttrList.end(), 
538                        OldAttrList.begin()+i, OldAttrList.end());
539   }
540   
541   return get(NewAttrList);
542 }
543
544 AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const {
545 #ifndef NDEBUG
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!");
549 #endif
550   if (AttrList == 0) return AttrListPtr();
551   
552   Attributes OldAttrs = getAttributes(Idx);
553   Attributes NewAttrs = OldAttrs & ~Attrs;
554   if (NewAttrs == OldAttrs)
555     return *this;
556
557   SmallVector<AttributeWithIndex, 8> NewAttrList;
558   const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
559   unsigned i = 0, e = OldAttrList.size();
560   
561   // Copy attributes for arguments before this one.
562   for (; i != e && OldAttrList[i].Index < Idx; ++i)
563     NewAttrList.push_back(OldAttrList[i]);
564   
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;
568   ++i;
569   if (Attrs)  // If any attributes left for this parameter, add them.
570     NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
571   
572   // Copy attributes for arguments after this one.
573   NewAttrList.insert(NewAttrList.end(), 
574                      OldAttrList.begin()+i, OldAttrList.end());
575   
576   return get(NewAttrList);
577 }
578
579 void AttrListPtr::dump() const {
580   dbgs() << "PAL[ ";
581   for (unsigned i = 0; i < getNumSlots(); ++i) {
582     const AttributeWithIndex &PAWI = getSlot(i);
583     dbgs() << "{" << PAWI.Index << "," << PAWI.Attrs << "} ";
584   }
585   
586   dbgs() << "]\n";
587 }