Begin the transition to using the AttributesImpl object for the Attributes ivar.
[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 "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"
24 using namespace llvm;
25
26 //===----------------------------------------------------------------------===//
27 // Attributes Implementation
28 //===----------------------------------------------------------------------===//
29
30 Attributes::Attributes(uint64_t Val) : Attrs(Val) {}
31
32 Attributes::Attributes(Attribute::AttrConst Val) : Attrs(Val.v) {}
33
34 Attributes::Attributes(AttributesImpl *A) : Attrs(A->Bits) {}
35
36 Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) {
37   // If there are no attributes, return an empty Attributes class.
38   if (B.Bits == 0)
39     return Attributes();
40
41   // Otherwise, build a key to look up the existing attributes.
42   LLVMContextImpl *pImpl = Context.pImpl;
43   FoldingSetNodeID ID;
44   ID.AddInteger(B.Bits);
45
46   void *InsertPoint;
47   AttributesImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
48
49   if (!PA) {
50     // If we didn't find any existing attributes of the same shape then create a
51     // new one and insert it.
52     PA = new AttributesImpl(B.Bits);
53     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
54   }
55
56   // Return the AttributesList that we found or created.
57   return Attributes(PA);
58 }
59
60 bool Attributes::hasAttributes(const Attributes &A) const {
61   return Attrs.hasAttributes(A);
62 }
63 bool Attributes::hasAddressSafetyAttr() const {
64   return Attrs.hasAttribute(Attribute::AddressSafety_i);
65 }
66 bool Attributes::hasAlignmentAttr() const {
67   return Attrs.hasAttribute(Attribute::Alignment_i);
68 }
69 bool Attributes::hasAlwaysInlineAttr() const {
70   return Attrs.hasAttribute(Attribute::AlwaysInline_i);
71 }
72 bool Attributes::hasByValAttr() const {
73   return Attrs.hasAttribute(Attribute::ByVal_i);
74 }
75 bool Attributes::hasInlineHintAttr() const {
76   return Attrs.hasAttribute(Attribute::InlineHint_i);
77 }
78 bool Attributes::hasInRegAttr() const {
79   return Attrs.hasAttribute(Attribute::InReg_i);
80 }
81 bool Attributes::hasNakedAttr() const {
82   return Attrs.hasAttribute(Attribute::Naked_i);
83 }
84 bool Attributes::hasNestAttr() const {
85   return Attrs.hasAttribute(Attribute::Nest_i);
86 }
87 bool Attributes::hasNoAliasAttr() const {
88   return Attrs.hasAttribute(Attribute::NoAlias_i);
89 }
90 bool Attributes::hasNoCaptureAttr() const {
91   return Attrs.hasAttribute(Attribute::NoCapture_i);
92 }
93 bool Attributes::hasNoImplicitFloatAttr() const {
94   return Attrs.hasAttribute(Attribute::NoImplicitFloat_i);
95 }
96 bool Attributes::hasNoInlineAttr() const {
97   return Attrs.hasAttribute(Attribute::NoInline_i);
98 }
99 bool Attributes::hasNonLazyBindAttr() const {
100   return Attrs.hasAttribute(Attribute::NonLazyBind_i);
101 }
102 bool Attributes::hasNoRedZoneAttr() const {
103   return Attrs.hasAttribute(Attribute::NoRedZone_i);
104 }
105 bool Attributes::hasNoReturnAttr() const {
106   return Attrs.hasAttribute(Attribute::NoReturn_i);
107 }
108 bool Attributes::hasNoUnwindAttr() const {
109   return Attrs.hasAttribute(Attribute::NoUnwind_i);
110 }
111 bool Attributes::hasOptimizeForSizeAttr() const {
112   return Attrs.hasAttribute(Attribute::OptimizeForSize_i);
113 }
114 bool Attributes::hasReadNoneAttr() const {
115   return Attrs.hasAttribute(Attribute::ReadNone_i);
116 }
117 bool Attributes::hasReadOnlyAttr() const {
118   return Attrs.hasAttribute(Attribute::ReadOnly_i);
119 }
120 bool Attributes::hasReturnsTwiceAttr() const {
121   return Attrs.hasAttribute(Attribute::ReturnsTwice_i);
122 }
123 bool Attributes::hasSExtAttr() const {
124   return Attrs.hasAttribute(Attribute::SExt_i);
125 }
126 bool Attributes::hasStackAlignmentAttr() const {
127   return Attrs.hasAttribute(Attribute::StackAlignment_i);
128 }
129 bool Attributes::hasStackProtectAttr() const {
130   return Attrs.hasAttribute(Attribute::StackProtect_i);
131 }
132 bool Attributes::hasStackProtectReqAttr() const {
133   return Attrs.hasAttribute(Attribute::StackProtectReq_i);
134 }
135 bool Attributes::hasStructRetAttr() const {
136   return Attrs.hasAttribute(Attribute::StructRet_i);
137 }
138 bool Attributes::hasUWTableAttr() const {
139   return Attrs.hasAttribute(Attribute::UWTable_i);
140 }
141 bool Attributes::hasZExtAttr() const {
142   return Attrs.hasAttribute(Attribute::ZExt_i);
143 }
144
145 /// This returns the alignment field of an attribute as a byte alignment value.
146 unsigned Attributes::getAlignment() const {
147   if (!hasAlignmentAttr())
148     return 0;
149   return 1U << ((Attrs.getAlignment() >> 16) - 1);
150 }
151
152 /// This returns the stack alignment field of an attribute as a byte alignment
153 /// value.
154 unsigned Attributes::getStackAlignment() const {
155   if (!hasStackAlignmentAttr())
156     return 0;
157   return 1U << ((Attrs.getStackAlignment() >> 26) - 1);
158 }
159
160 bool Attributes::isEmptyOrSingleton() const {
161   return Attrs.isEmptyOrSingleton();
162 }
163
164 Attributes Attributes::operator | (const Attributes &A) const {
165   return Attributes(Raw() | A.Raw());
166 }
167 Attributes Attributes::operator & (const Attributes &A) const {
168   return Attributes(Raw() & A.Raw());
169 }
170 Attributes Attributes::operator ^ (const Attributes &A) const {
171   return Attributes(Raw() ^ A.Raw());
172 }
173 Attributes &Attributes::operator |= (const Attributes &A) {
174   Attrs.Bits |= A.Raw();
175   return *this;
176 }
177 Attributes &Attributes::operator &= (const Attributes &A) {
178   Attrs.Bits &= A.Raw();
179   return *this;
180 }
181 Attributes Attributes::operator ~ () const {
182   return Attributes(~Raw());
183 }
184
185 uint64_t Attributes::Raw() const {
186   return Attrs.Bits;
187 }
188
189 Attributes Attributes::typeIncompatible(Type *Ty) {
190   Attributes::Builder Incompatible;
191   
192   if (!Ty->isIntegerTy()) {
193     // Attributes that only apply to integers.
194     Incompatible.addSExtAttr();
195     Incompatible.addZExtAttr();
196   }
197   
198   if (!Ty->isPointerTy()) {
199     // Attributes that only apply to pointers.
200     Incompatible.addByValAttr();
201     Incompatible.addNestAttr();
202     Incompatible.addNoAliasAttr();
203     Incompatible.addNoCaptureAttr();
204     Incompatible.addStructRetAttr();
205   }
206   
207   return Attributes(Incompatible.Bits); // FIXME: Use Attributes::get().
208 }
209
210 std::string Attributes::getAsString() const {
211   std::string Result;
212   if (hasZExtAttr())
213     Result += "zeroext ";
214   if (hasSExtAttr())
215     Result += "signext ";
216   if (hasNoReturnAttr())
217     Result += "noreturn ";
218   if (hasNoUnwindAttr())
219     Result += "nounwind ";
220   if (hasUWTableAttr())
221     Result += "uwtable ";
222   if (hasReturnsTwiceAttr())
223     Result += "returns_twice ";
224   if (hasInRegAttr())
225     Result += "inreg ";
226   if (hasNoAliasAttr())
227     Result += "noalias ";
228   if (hasNoCaptureAttr())
229     Result += "nocapture ";
230   if (hasStructRetAttr())
231     Result += "sret ";
232   if (hasByValAttr())
233     Result += "byval ";
234   if (hasNestAttr())
235     Result += "nest ";
236   if (hasReadNoneAttr())
237     Result += "readnone ";
238   if (hasReadOnlyAttr())
239     Result += "readonly ";
240   if (hasOptimizeForSizeAttr())
241     Result += "optsize ";
242   if (hasNoInlineAttr())
243     Result += "noinline ";
244   if (hasInlineHintAttr())
245     Result += "inlinehint ";
246   if (hasAlwaysInlineAttr())
247     Result += "alwaysinline ";
248   if (hasStackProtectAttr())
249     Result += "ssp ";
250   if (hasStackProtectReqAttr())
251     Result += "sspreq ";
252   if (hasNoRedZoneAttr())
253     Result += "noredzone ";
254   if (hasNoImplicitFloatAttr())
255     Result += "noimplicitfloat ";
256   if (hasNakedAttr())
257     Result += "naked ";
258   if (hasNonLazyBindAttr())
259     Result += "nonlazybind ";
260   if (hasAddressSafetyAttr())
261     Result += "address_safety ";
262   if (hasStackAlignmentAttr()) {
263     Result += "alignstack(";
264     Result += utostr(getStackAlignment());
265     Result += ") ";
266   }
267   if (hasAlignmentAttr()) {
268     Result += "align ";
269     Result += utostr(getAlignment());
270     Result += " ";
271   }
272   // Trim the trailing space.
273   assert(!Result.empty() && "Unknown attribute!");
274   Result.erase(Result.end()-1);
275   return Result;
276 }
277
278 //===----------------------------------------------------------------------===//
279 // Attributes::Builder Implementation
280 //===----------------------------------------------------------------------===//
281
282 void Attributes::Builder::addAddressSafetyAttr() {
283   Bits |= Attribute::AddressSafety_i;
284 }
285 void Attributes::Builder::addAlwaysInlineAttr() {
286   Bits |= Attribute::AlwaysInline_i;
287 }
288 void Attributes::Builder::addByValAttr() {
289   Bits |= Attribute::ByVal_i;
290 }
291 void Attributes::Builder::addInlineHintAttr() {
292   Bits |= Attribute::InlineHint_i;
293 }
294 void Attributes::Builder::addInRegAttr() {
295   Bits |= Attribute::InReg_i;
296 }
297 void Attributes::Builder::addNakedAttr() {
298   Bits |= Attribute::Naked_i;
299 }
300 void Attributes::Builder::addNestAttr() {
301   Bits |= Attribute::Nest_i;
302 }
303 void Attributes::Builder::addNoAliasAttr() {
304   Bits |= Attribute::NoAlias_i;
305 }
306 void Attributes::Builder::addNoCaptureAttr() {
307   Bits |= Attribute::NoCapture_i;
308 }
309 void Attributes::Builder::addNoImplicitFloatAttr() {
310   Bits |= Attribute::NoImplicitFloat_i;
311 }
312 void Attributes::Builder::addNoInlineAttr() {
313   Bits |= Attribute::NoInline_i;
314 }
315 void Attributes::Builder::addNonLazyBindAttr() {
316   Bits |= Attribute::NonLazyBind_i;
317 }
318 void Attributes::Builder::addNoRedZoneAttr() {
319   Bits |= Attribute::NoRedZone_i;
320 }
321 void Attributes::Builder::addNoReturnAttr() {
322   Bits |= Attribute::NoReturn_i;
323 }
324 void Attributes::Builder::addNoUnwindAttr() {
325   Bits |= Attribute::NoUnwind_i;
326 }
327 void Attributes::Builder::addOptimizeForSizeAttr() {
328   Bits |= Attribute::OptimizeForSize_i;
329 }
330 void Attributes::Builder::addReadNoneAttr() {
331   Bits |= Attribute::ReadNone_i;
332 }
333 void Attributes::Builder::addReadOnlyAttr() {
334   Bits |= Attribute::ReadOnly_i;
335 }
336 void Attributes::Builder::addReturnsTwiceAttr() {
337   Bits |= Attribute::ReturnsTwice_i;
338 }
339 void Attributes::Builder::addSExtAttr() {
340   Bits |= Attribute::SExt_i;
341 }
342 void Attributes::Builder::addStackProtectAttr() {
343   Bits |= Attribute::StackProtect_i;
344 }
345 void Attributes::Builder::addStackProtectReqAttr() {
346   Bits |= Attribute::StackProtectReq_i;
347 }
348 void Attributes::Builder::addStructRetAttr() {
349   Bits |= Attribute::StructRet_i;
350 }
351 void Attributes::Builder::addUWTableAttr() {
352   Bits |= Attribute::UWTable_i;
353 }
354 void Attributes::Builder::addZExtAttr() {
355   Bits |= Attribute::ZExt_i;
356 }
357
358 void Attributes::Builder::addAlignmentAttr(unsigned Align) {
359   if (Align == 0) return;
360   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
361   assert(Align <= 0x40000000 && "Alignment too large.");
362   Bits |= (Log2_32(Align) + 1) << 16;
363 }
364 void Attributes::Builder::addStackAlignmentAttr(unsigned Align) {
365   // Default alignment, allow the target to define how to align it.
366   if (Align == 0) return;
367   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
368   assert(Align <= 0x100 && "Alignment too large.");
369   Bits |= (Log2_32(Align) + 1) << 26;
370 }
371
372 void Attributes::Builder::removeAddressSafetyAttr() {
373   Bits &= ~Attribute::AddressSafety_i;
374 }
375 void Attributes::Builder::removeAlwaysInlineAttr() {
376   Bits &= ~Attribute::AlwaysInline_i;
377 }
378 void Attributes::Builder::removeByValAttr() {
379   Bits &= ~Attribute::ByVal_i;
380 }
381 void Attributes::Builder::removeInlineHintAttr() {
382   Bits &= ~Attribute::InlineHint_i;
383 }
384 void Attributes::Builder::removeInRegAttr() {
385   Bits &= ~Attribute::InReg_i;
386 }
387 void Attributes::Builder::removeNakedAttr() {
388   Bits &= ~Attribute::Naked_i;
389 }
390 void Attributes::Builder::removeNestAttr() {
391   Bits &= ~Attribute::Nest_i;
392 }
393 void Attributes::Builder::removeNoAliasAttr() {
394   Bits &= ~Attribute::NoAlias_i;
395 }
396 void Attributes::Builder::removeNoCaptureAttr() {
397   Bits &= ~Attribute::NoCapture_i;
398 }
399 void Attributes::Builder::removeNoImplicitFloatAttr() {
400   Bits &= ~Attribute::NoImplicitFloat_i;
401 }
402 void Attributes::Builder::removeNoInlineAttr() {
403   Bits &= ~Attribute::NoInline_i;
404 }
405 void Attributes::Builder::removeNonLazyBindAttr() {
406   Bits &= ~Attribute::NonLazyBind_i;
407 }
408 void Attributes::Builder::removeNoRedZoneAttr() {
409   Bits &= ~Attribute::NoRedZone_i;
410 }
411 void Attributes::Builder::removeNoReturnAttr() {
412   Bits &= ~Attribute::NoReturn_i;
413 }
414 void Attributes::Builder::removeNoUnwindAttr() {
415   Bits &= ~Attribute::NoUnwind_i;
416 }
417 void Attributes::Builder::removeOptimizeForSizeAttr() {
418   Bits &= ~Attribute::OptimizeForSize_i;
419 }
420 void Attributes::Builder::removeReadNoneAttr() {
421   Bits &= ~Attribute::ReadNone_i;
422 }
423 void Attributes::Builder::removeReadOnlyAttr() {
424   Bits &= ~Attribute::ReadOnly_i;
425 }
426 void Attributes::Builder::removeReturnsTwiceAttr() {
427   Bits &= ~Attribute::ReturnsTwice_i;
428 }
429 void Attributes::Builder::removeSExtAttr() {
430   Bits &= ~Attribute::SExt_i;
431 }
432 void Attributes::Builder::removeStackProtectAttr() {
433   Bits &= ~Attribute::StackProtect_i;
434 }
435 void Attributes::Builder::removeStackProtectReqAttr() {
436   Bits &= ~Attribute::StackProtectReq_i;
437 }
438 void Attributes::Builder::removeStructRetAttr() {
439   Bits &= ~Attribute::StructRet_i;
440 }
441 void Attributes::Builder::removeUWTableAttr() {
442   Bits &= ~Attribute::UWTable_i;
443 }
444 void Attributes::Builder::removeZExtAttr() {
445   Bits &= ~Attribute::ZExt_i;
446 }
447
448 //===----------------------------------------------------------------------===//
449 // AttributeImpl Definition
450 //===----------------------------------------------------------------------===//
451
452 bool AttributesImpl::hasAttribute(uint64_t A) const {
453   return (Bits & A) != 0;
454 }
455
456 bool AttributesImpl::hasAttributes() const {
457   return Bits != 0;
458 }
459
460 bool AttributesImpl::hasAttributes(const Attributes &A) const {
461   return Bits & A.Raw();        // FIXME: Raw() won't work here in the future.
462 }
463
464 uint64_t AttributesImpl::getAlignment() const {
465   return Bits & Attribute::Alignment_i;
466 }
467
468 uint64_t AttributesImpl::getStackAlignment() const {
469   return Bits & Attribute::StackAlignment_i;
470 }
471
472 bool AttributesImpl::isEmptyOrSingleton() const {
473   return (Bits & (Bits - 1)) == 0;
474 }
475
476 //===----------------------------------------------------------------------===//
477 // AttributeListImpl Definition
478 //===----------------------------------------------------------------------===//
479
480 namespace llvm {
481   class AttributeListImpl;
482 }
483
484 static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists;
485
486 namespace llvm {
487 static ManagedStatic<sys::SmartMutex<true> > ALMutex;
488
489 class AttributeListImpl : public FoldingSetNode {
490   sys::cas_flag RefCount;
491   
492   // AttributesList is uniqued, these should not be publicly available.
493   void operator=(const AttributeListImpl &) LLVM_DELETED_FUNCTION;
494   AttributeListImpl(const AttributeListImpl &) LLVM_DELETED_FUNCTION;
495   ~AttributeListImpl();                        // Private implementation
496 public:
497   SmallVector<AttributeWithIndex, 4> Attrs;
498   
499   AttributeListImpl(ArrayRef<AttributeWithIndex> attrs)
500     : Attrs(attrs.begin(), attrs.end()) {
501     RefCount = 0;
502   }
503   
504   void AddRef() {
505     sys::SmartScopedLock<true> Lock(*ALMutex);
506     ++RefCount;
507   }
508   void DropRef() {
509     sys::SmartScopedLock<true> Lock(*ALMutex);
510     if (!AttributesLists.isConstructed())
511       return;
512     sys::cas_flag new_val = --RefCount;
513     if (new_val == 0)
514       delete this;
515   }
516   
517   void Profile(FoldingSetNodeID &ID) const {
518     Profile(ID, Attrs);
519   }
520   static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeWithIndex> Attrs){
521     for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
522       ID.AddInteger(Attrs[i].Attrs.Raw());
523       ID.AddInteger(Attrs[i].Index);
524     }
525   }
526 };
527 }
528
529 AttributeListImpl::~AttributeListImpl() {
530   // NOTE: Lock must be acquired by caller.
531   AttributesLists->RemoveNode(this);
532 }
533
534
535 AttrListPtr AttrListPtr::get(ArrayRef<AttributeWithIndex> Attrs) {
536   // If there are no attributes then return a null AttributesList pointer.
537   if (Attrs.empty())
538     return AttrListPtr();
539   
540 #ifndef NDEBUG
541   for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
542     assert(Attrs[i].Attrs.hasAttributes() && 
543            "Pointless attribute!");
544     assert((!i || Attrs[i-1].Index < Attrs[i].Index) &&
545            "Misordered AttributesList!");
546   }
547 #endif
548   
549   // Otherwise, build a key to look up the existing attributes.
550   FoldingSetNodeID ID;
551   AttributeListImpl::Profile(ID, Attrs);
552   void *InsertPos;
553   
554   sys::SmartScopedLock<true> Lock(*ALMutex);
555   
556   AttributeListImpl *PAL =
557     AttributesLists->FindNodeOrInsertPos(ID, InsertPos);
558   
559   // If we didn't find any existing attributes of the same shape then
560   // create a new one and insert it.
561   if (!PAL) {
562     PAL = new AttributeListImpl(Attrs);
563     AttributesLists->InsertNode(PAL, InsertPos);
564   }
565   
566   // Return the AttributesList that we found or created.
567   return AttrListPtr(PAL);
568 }
569
570
571 //===----------------------------------------------------------------------===//
572 // AttrListPtr Method Implementations
573 //===----------------------------------------------------------------------===//
574
575 AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) {
576   if (LI) LI->AddRef();
577 }
578
579 AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) {
580   if (AttrList) AttrList->AddRef();  
581 }
582
583 const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) {
584   sys::SmartScopedLock<true> Lock(*ALMutex);
585   if (AttrList == RHS.AttrList) return *this;
586   if (AttrList) AttrList->DropRef();
587   AttrList = RHS.AttrList;
588   if (AttrList) AttrList->AddRef();
589   return *this;
590 }
591
592 AttrListPtr::~AttrListPtr() {
593   if (AttrList) AttrList->DropRef();
594 }
595
596 /// getNumSlots - Return the number of slots used in this attribute list. 
597 /// This is the number of arguments that have an attribute set on them
598 /// (including the function itself).
599 unsigned AttrListPtr::getNumSlots() const {
600   return AttrList ? AttrList->Attrs.size() : 0;
601 }
602
603 /// getSlot - Return the AttributeWithIndex at the specified slot.  This
604 /// holds a number plus a set of attributes.
605 const AttributeWithIndex &AttrListPtr::getSlot(unsigned Slot) const {
606   assert(AttrList && Slot < AttrList->Attrs.size() && "Slot # out of range!");
607   return AttrList->Attrs[Slot];
608 }
609
610
611 /// getAttributes - The attributes for the specified index are
612 /// returned.  Attributes for the result are denoted with Idx = 0.
613 /// Function notes are denoted with idx = ~0.
614 Attributes AttrListPtr::getAttributes(unsigned Idx) const {
615   if (AttrList == 0) return Attributes();
616   
617   const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
618   for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i)
619     if (Attrs[i].Index == Idx)
620       return Attrs[i].Attrs;
621
622   return Attributes();
623 }
624
625 /// hasAttrSomewhere - Return true if the specified attribute is set for at
626 /// least one parameter or for the return value.
627 bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const {
628   if (AttrList == 0) return false;
629   
630   const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
631   for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
632     if (Attrs[i].Attrs.hasAttributes(Attr))
633       return true;
634   return false;
635 }
636
637
638 AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const {
639   Attributes OldAttrs = getAttributes(Idx);
640 #ifndef NDEBUG
641   // FIXME it is not obvious how this should work for alignment.
642   // For now, say we can't change a known alignment.
643   unsigned OldAlign = OldAttrs.getAlignment();
644   unsigned NewAlign = Attrs.getAlignment();
645   assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
646          "Attempt to change alignment!");
647 #endif
648   
649   Attributes NewAttrs = OldAttrs | Attrs;
650   if (NewAttrs == OldAttrs)
651     return *this;
652   
653   SmallVector<AttributeWithIndex, 8> NewAttrList;
654   if (AttrList == 0)
655     NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
656   else {
657     const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
658     unsigned i = 0, e = OldAttrList.size();
659     // Copy attributes for arguments before this one.
660     for (; i != e && OldAttrList[i].Index < Idx; ++i)
661       NewAttrList.push_back(OldAttrList[i]);
662
663     // If there are attributes already at this index, merge them in.
664     if (i != e && OldAttrList[i].Index == Idx) {
665       Attrs |= OldAttrList[i].Attrs;
666       ++i;
667     }
668     
669     NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
670     
671     // Copy attributes for arguments after this one.
672     NewAttrList.insert(NewAttrList.end(), 
673                        OldAttrList.begin()+i, OldAttrList.end());
674   }
675   
676   return get(NewAttrList);
677 }
678
679 AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const {
680 #ifndef NDEBUG
681   // FIXME it is not obvious how this should work for alignment.
682   // For now, say we can't pass in alignment, which no current use does.
683   assert(!Attrs.hasAlignmentAttr() && "Attempt to exclude alignment!");
684 #endif
685   if (AttrList == 0) return AttrListPtr();
686   
687   Attributes OldAttrs = getAttributes(Idx);
688   Attributes NewAttrs = OldAttrs & ~Attrs;
689   if (NewAttrs == OldAttrs)
690     return *this;
691
692   SmallVector<AttributeWithIndex, 8> NewAttrList;
693   const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
694   unsigned i = 0, e = OldAttrList.size();
695   
696   // Copy attributes for arguments before this one.
697   for (; i != e && OldAttrList[i].Index < Idx; ++i)
698     NewAttrList.push_back(OldAttrList[i]);
699   
700   // If there are attributes already at this index, merge them in.
701   assert(OldAttrList[i].Index == Idx && "Attribute isn't set?");
702   Attrs = OldAttrList[i].Attrs & ~Attrs;
703   ++i;
704   if (Attrs)  // If any attributes left for this parameter, add them.
705     NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
706   
707   // Copy attributes for arguments after this one.
708   NewAttrList.insert(NewAttrList.end(), 
709                      OldAttrList.begin()+i, OldAttrList.end());
710   
711   return get(NewAttrList);
712 }
713
714 void AttrListPtr::dump() const {
715   dbgs() << "PAL[ ";
716   for (unsigned i = 0; i < getNumSlots(); ++i) {
717     const AttributeWithIndex &PAWI = getSlot(i);
718     dbgs() << "{" << PAWI.Index << "," << PAWI.Attrs << "} ";
719   }
720   
721   dbgs() << "]\n";
722 }