Attributes.cpp revision 28d65722d6f283b327b5815914382077fe9c0ab4
1//===-- Attribute.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 Attribute, AttributeImpl, AttrBuilder,
11// AttributeSetImpl, and AttributeSet classes.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/IR/Attributes.h"
16#include "AttributeImpl.h"
17#include "LLVMContextImpl.h"
18#include "llvm/ADT/FoldingSet.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/IR/Type.h"
21#include "llvm/Support/Atomic.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/ManagedStatic.h"
24#include "llvm/Support/Mutex.h"
25#include "llvm/Support/raw_ostream.h"
26using namespace llvm;
27
28//===----------------------------------------------------------------------===//
29// Attribute Implementation
30//===----------------------------------------------------------------------===//
31
32Attribute Attribute::get(LLVMContext &Context, ArrayRef<AttrKind> Vals) {
33  AttrBuilder B;
34  for (ArrayRef<AttrKind>::iterator I = Vals.begin(), E = Vals.end();
35       I != E; ++I)
36    B.addAttribute(*I);
37  return Attribute::get(Context, B);
38}
39
40Attribute Attribute::get(LLVMContext &Context, AttrBuilder &B) {
41  // If there are no attributes, return an empty Attribute class.
42  if (!B.hasAttributes())
43    return Attribute();
44
45  // Otherwise, build a key to look up the existing attributes.
46  LLVMContextImpl *pImpl = Context.pImpl;
47  FoldingSetNodeID ID;
48  ID.AddInteger(B.Raw());
49
50  void *InsertPoint;
51  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
52
53  if (!PA) {
54    // If we didn't find any existing attributes of the same shape then create a
55    // new one and insert it.
56    PA = new AttributeImpl(Context, B.Raw());
57    pImpl->AttrsSet.InsertNode(PA, InsertPoint);
58  }
59
60  // Return the AttributesList that we found or created.
61  return Attribute(PA);
62}
63
64bool Attribute::hasAttribute(AttrKind Val) const {
65  return pImpl && pImpl->hasAttribute(Val);
66}
67
68bool Attribute::hasAttributes() const {
69  return pImpl && pImpl->hasAttributes();
70}
71
72/// This returns the alignment field of an attribute as a byte alignment value.
73unsigned Attribute::getAlignment() const {
74  if (!hasAttribute(Attribute::Alignment))
75    return 0;
76  return 1U << ((pImpl->getAlignment() >> 16) - 1);
77}
78
79void Attribute::setAlignment(unsigned Align) {
80  assert(hasAttribute(Attribute::Alignment) &&
81         "Trying to set the alignment on a non-alignment attribute!");
82  pImpl->setAlignment(Align);
83}
84
85/// This returns the stack alignment field of an attribute as a byte alignment
86/// value.
87unsigned Attribute::getStackAlignment() const {
88  if (!hasAttribute(Attribute::StackAlignment))
89    return 0;
90  return 1U << ((pImpl->getStackAlignment() >> 26) - 1);
91}
92
93void Attribute::setStackAlignment(unsigned Align) {
94  assert(hasAttribute(Attribute::StackAlignment) &&
95         "Trying to set the stack alignment on a non-alignment attribute!");
96  pImpl->setStackAlignment(Align);
97}
98
99bool Attribute::operator==(AttrKind K) const {
100  return pImpl && *pImpl == K;
101}
102bool Attribute::operator!=(AttrKind K) const {
103  return !(*this == K);
104}
105
106uint64_t Attribute::Raw() const {
107  return pImpl ? pImpl->Raw() : 0;
108}
109
110Attribute Attribute::typeIncompatible(Type *Ty) {
111  AttrBuilder Incompatible;
112
113  if (!Ty->isIntegerTy())
114    // Attribute that only apply to integers.
115    Incompatible.addAttribute(Attribute::SExt)
116      .addAttribute(Attribute::ZExt);
117
118  if (!Ty->isPointerTy())
119    // Attribute that only apply to pointers.
120    Incompatible.addAttribute(Attribute::ByVal)
121      .addAttribute(Attribute::Nest)
122      .addAttribute(Attribute::NoAlias)
123      .addAttribute(Attribute::NoCapture)
124      .addAttribute(Attribute::StructRet);
125
126  return Attribute::get(Ty->getContext(), Incompatible);
127}
128
129/// encodeLLVMAttributesForBitcode - This returns an integer containing an
130/// encoding of all the LLVM attributes found in the given attribute bitset.
131/// Any change to this encoding is a breaking change to bitcode compatibility.
132uint64_t Attribute::encodeLLVMAttributesForBitcode(Attribute Attrs) {
133  // FIXME: It doesn't make sense to store the alignment information as an
134  // expanded out value, we should store it as a log2 value.  However, we can't
135  // just change that here without breaking bitcode compatibility.  If this ever
136  // becomes a problem in practice, we should introduce new tag numbers in the
137  // bitcode file and have those tags use a more efficiently encoded alignment
138  // field.
139
140  // Store the alignment in the bitcode as a 16-bit raw value instead of a 5-bit
141  // log2 encoded value. Shift the bits above the alignment up by 11 bits.
142  uint64_t EncodedAttrs = Attrs.Raw() & 0xffff;
143  if (Attrs.hasAttribute(Attribute::Alignment))
144    EncodedAttrs |= Attrs.getAlignment() << 16;
145  EncodedAttrs |= (Attrs.Raw() & (0xffffULL << 21)) << 11;
146  return EncodedAttrs;
147}
148
149/// decodeLLVMAttributesForBitcode - This returns an attribute bitset containing
150/// the LLVM attributes that have been decoded from the given integer.  This
151/// function must stay in sync with 'encodeLLVMAttributesForBitcode'.
152Attribute Attribute::decodeLLVMAttributesForBitcode(LLVMContext &C,
153                                                    uint64_t EncodedAttrs) {
154  // The alignment is stored as a 16-bit raw value from bits 31--16.  We shift
155  // the bits above 31 down by 11 bits.
156  unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16;
157  assert((!Alignment || isPowerOf2_32(Alignment)) &&
158         "Alignment must be a power of two.");
159
160  AttrBuilder B(EncodedAttrs & 0xffff);
161  if (Alignment)
162    B.addAlignmentAttr(Alignment);
163  B.addRawValue((EncodedAttrs & (0xffffULL << 32)) >> 11);
164  return Attribute::get(C, B);
165}
166
167std::string Attribute::getAsString() const {
168  std::string Result;
169  if (hasAttribute(Attribute::ZExt))
170    Result += "zeroext ";
171  if (hasAttribute(Attribute::SExt))
172    Result += "signext ";
173  if (hasAttribute(Attribute::NoReturn))
174    Result += "noreturn ";
175  if (hasAttribute(Attribute::NoUnwind))
176    Result += "nounwind ";
177  if (hasAttribute(Attribute::UWTable))
178    Result += "uwtable ";
179  if (hasAttribute(Attribute::ReturnsTwice))
180    Result += "returns_twice ";
181  if (hasAttribute(Attribute::InReg))
182    Result += "inreg ";
183  if (hasAttribute(Attribute::NoAlias))
184    Result += "noalias ";
185  if (hasAttribute(Attribute::NoCapture))
186    Result += "nocapture ";
187  if (hasAttribute(Attribute::StructRet))
188    Result += "sret ";
189  if (hasAttribute(Attribute::ByVal))
190    Result += "byval ";
191  if (hasAttribute(Attribute::Nest))
192    Result += "nest ";
193  if (hasAttribute(Attribute::ReadNone))
194    Result += "readnone ";
195  if (hasAttribute(Attribute::ReadOnly))
196    Result += "readonly ";
197  if (hasAttribute(Attribute::OptimizeForSize))
198    Result += "optsize ";
199  if (hasAttribute(Attribute::NoInline))
200    Result += "noinline ";
201  if (hasAttribute(Attribute::InlineHint))
202    Result += "inlinehint ";
203  if (hasAttribute(Attribute::AlwaysInline))
204    Result += "alwaysinline ";
205  if (hasAttribute(Attribute::StackProtect))
206    Result += "ssp ";
207  if (hasAttribute(Attribute::StackProtectReq))
208    Result += "sspreq ";
209  if (hasAttribute(Attribute::NoRedZone))
210    Result += "noredzone ";
211  if (hasAttribute(Attribute::NoImplicitFloat))
212    Result += "noimplicitfloat ";
213  if (hasAttribute(Attribute::Naked))
214    Result += "naked ";
215  if (hasAttribute(Attribute::NonLazyBind))
216    Result += "nonlazybind ";
217  if (hasAttribute(Attribute::AddressSafety))
218    Result += "address_safety ";
219  if (hasAttribute(Attribute::MinSize))
220    Result += "minsize ";
221  if (hasAttribute(Attribute::StackAlignment)) {
222    Result += "alignstack(";
223    Result += utostr(getStackAlignment());
224    Result += ") ";
225  }
226  if (hasAttribute(Attribute::Alignment)) {
227    Result += "align ";
228    Result += utostr(getAlignment());
229    Result += " ";
230  }
231  if (hasAttribute(Attribute::NoDuplicate))
232    Result += "noduplicate ";
233  // Trim the trailing space.
234  assert(!Result.empty() && "Unknown attribute!");
235  Result.erase(Result.end()-1);
236  return Result;
237}
238
239//===----------------------------------------------------------------------===//
240// AttrBuilder Method Implementations
241//===----------------------------------------------------------------------===//
242
243AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Idx)
244  : Alignment(0), StackAlignment(0) {
245  AttributeSetImpl *pImpl = AS.AttrList;
246  if (!pImpl) return;
247
248  ArrayRef<AttributeWithIndex> AttrList = pImpl->getAttributes();
249  const AttributeWithIndex *AWI = 0;
250  for (unsigned I = 0, E = AttrList.size(); I != E; ++I)
251    if (AttrList[I].Index == Idx) {
252      AWI = &AttrList[I];
253      break;
254    }
255
256  if (!AWI) return;
257
258  uint64_t Mask = AWI->Attrs.Raw();
259
260  for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
261       I = Attribute::AttrKind(I + 1)) {
262    if (uint64_t A = (Mask & AttributeImpl::getAttrMask(I))) {
263      Attrs.insert(I);
264
265      if (I == Attribute::Alignment)
266        Alignment = 1ULL << ((A >> 16) - 1);
267      else if (I == Attribute::StackAlignment)
268        StackAlignment = 1ULL << ((A >> 26)-1);
269    }
270  }
271}
272
273void AttrBuilder::clear() {
274  Attrs.clear();
275  Alignment = StackAlignment = 0;
276}
277
278AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
279  Attrs.insert(Val);
280  return *this;
281}
282
283AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
284  Attrs.erase(Val);
285  if (Val == Attribute::Alignment)
286    Alignment = 0;
287  else if (Val == Attribute::StackAlignment)
288    StackAlignment = 0;
289
290  return *this;
291}
292
293AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
294  if (Align == 0) return *this;
295
296  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
297  assert(Align <= 0x40000000 && "Alignment too large.");
298
299  Attrs.insert(Attribute::Alignment);
300  Alignment = Align;
301  return *this;
302}
303
304AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) {
305  // Default alignment, allow the target to define how to align it.
306  if (Align == 0) return *this;
307
308  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
309  assert(Align <= 0x100 && "Alignment too large.");
310
311  Attrs.insert(Attribute::StackAlignment);
312  StackAlignment = Align;
313  return *this;
314}
315
316AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
317  for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
318       I = Attribute::AttrKind(I + 1)) {
319    if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {
320      Attrs.insert(I);
321
322      if (I == Attribute::Alignment)
323        Alignment = 1ULL << ((A >> 16) - 1);
324      else if (I == Attribute::StackAlignment)
325        StackAlignment = 1ULL << ((A >> 26)-1);
326    }
327  }
328
329  return *this;
330}
331
332AttrBuilder &AttrBuilder::addAttributes(const Attribute &Attr) {
333  uint64_t Mask = Attr.Raw();
334
335  for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
336       I = Attribute::AttrKind(I + 1))
337    if ((Mask & AttributeImpl::getAttrMask(I)) != 0)
338      Attrs.insert(I);
339
340  if (Attr.getAlignment())
341    Alignment = Attr.getAlignment();
342  if (Attr.getStackAlignment())
343    StackAlignment = Attr.getStackAlignment();
344  return *this;
345}
346
347AttrBuilder &AttrBuilder::removeAttributes(const Attribute &A){
348  uint64_t Mask = A.Raw();
349
350  for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
351       I = Attribute::AttrKind(I + 1)) {
352    if (Mask & AttributeImpl::getAttrMask(I)) {
353      Attrs.erase(I);
354
355      if (I == Attribute::Alignment)
356        Alignment = 0;
357      else if (I == Attribute::StackAlignment)
358        StackAlignment = 0;
359    }
360  }
361
362  return *this;
363}
364
365bool AttrBuilder::contains(Attribute::AttrKind A) const {
366  return Attrs.count(A);
367}
368
369bool AttrBuilder::hasAttributes() const {
370  return !Attrs.empty();
371}
372
373bool AttrBuilder::hasAttributes(const Attribute &A) const {
374  return Raw() & A.Raw();
375}
376
377bool AttrBuilder::hasAlignmentAttr() const {
378  return Alignment != 0;
379}
380
381uint64_t AttrBuilder::Raw() const {
382  uint64_t Mask = 0;
383
384  for (DenseSet<Attribute::AttrKind>::const_iterator I = Attrs.begin(),
385         E = Attrs.end(); I != E; ++I) {
386    Attribute::AttrKind Kind = *I;
387
388    if (Kind == Attribute::Alignment)
389      Mask |= (Log2_32(Alignment) + 1) << 16;
390    else if (Kind == Attribute::StackAlignment)
391      Mask |= (Log2_32(StackAlignment) + 1) << 26;
392    else
393      Mask |= AttributeImpl::getAttrMask(Kind);
394  }
395
396  return Mask;
397}
398
399bool AttrBuilder::operator==(const AttrBuilder &B) {
400  SmallVector<Attribute::AttrKind, 8> This(Attrs.begin(), Attrs.end());
401  SmallVector<Attribute::AttrKind, 8> That(B.Attrs.begin(), B.Attrs.end());
402  return This == That;
403}
404
405//===----------------------------------------------------------------------===//
406// AttributeImpl Definition
407//===----------------------------------------------------------------------===//
408
409AttributeImpl::AttributeImpl(LLVMContext &C, uint64_t data)
410  : Context(C) {
411  Data = ConstantInt::get(Type::getInt64Ty(C), data);
412}
413AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind data)
414  : Context(C) {
415  Data = ConstantInt::get(Type::getInt64Ty(C), data);
416}
417AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind data,
418                             ArrayRef<Constant*> values)
419  : Context(C) {
420  Data = ConstantInt::get(Type::getInt64Ty(C), data);
421  Vals.reserve(values.size());
422  Vals.append(values.begin(), values.end());
423}
424AttributeImpl::AttributeImpl(LLVMContext &C, StringRef data)
425  : Context(C) {
426  Data = ConstantDataArray::getString(C, data);
427}
428
429bool AttributeImpl::operator==(Attribute::AttrKind Kind) const {
430  if (ConstantInt *CI = dyn_cast<ConstantInt>(Data))
431    return CI->getZExtValue() == Kind;
432  return false;
433}
434bool AttributeImpl::operator!=(Attribute::AttrKind Kind) const {
435  return !(*this == Kind);
436}
437
438bool AttributeImpl::operator==(StringRef Kind) const {
439  if (ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(Data))
440    if (CDA->isString())
441      return CDA->getAsString() == Kind;
442  return false;
443}
444bool AttributeImpl::operator!=(StringRef Kind) const {
445  return !(*this == Kind);
446}
447
448uint64_t AttributeImpl::Raw() const {
449  // FIXME: Remove this.
450  return cast<ConstantInt>(Data)->getZExtValue();
451}
452
453uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
454  switch (Val) {
455  case Attribute::EndAttrKinds:
456  case Attribute::AttrKindEmptyKey:
457  case Attribute::AttrKindTombstoneKey:
458    llvm_unreachable("Synthetic enumerators which should never get here");
459
460  case Attribute::None:            return 0;
461  case Attribute::ZExt:            return 1 << 0;
462  case Attribute::SExt:            return 1 << 1;
463  case Attribute::NoReturn:        return 1 << 2;
464  case Attribute::InReg:           return 1 << 3;
465  case Attribute::StructRet:       return 1 << 4;
466  case Attribute::NoUnwind:        return 1 << 5;
467  case Attribute::NoAlias:         return 1 << 6;
468  case Attribute::ByVal:           return 1 << 7;
469  case Attribute::Nest:            return 1 << 8;
470  case Attribute::ReadNone:        return 1 << 9;
471  case Attribute::ReadOnly:        return 1 << 10;
472  case Attribute::NoInline:        return 1 << 11;
473  case Attribute::AlwaysInline:    return 1 << 12;
474  case Attribute::OptimizeForSize: return 1 << 13;
475  case Attribute::StackProtect:    return 1 << 14;
476  case Attribute::StackProtectReq: return 1 << 15;
477  case Attribute::Alignment:       return 31 << 16;
478  case Attribute::NoCapture:       return 1 << 21;
479  case Attribute::NoRedZone:       return 1 << 22;
480  case Attribute::NoImplicitFloat: return 1 << 23;
481  case Attribute::Naked:           return 1 << 24;
482  case Attribute::InlineHint:      return 1 << 25;
483  case Attribute::StackAlignment:  return 7 << 26;
484  case Attribute::ReturnsTwice:    return 1 << 29;
485  case Attribute::UWTable:         return 1 << 30;
486  case Attribute::NonLazyBind:     return 1U << 31;
487  case Attribute::AddressSafety:   return 1ULL << 32;
488  case Attribute::MinSize:         return 1ULL << 33;
489  case Attribute::NoDuplicate:     return 1ULL << 34;
490  }
491  llvm_unreachable("Unsupported attribute type");
492}
493
494bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
495  return (Raw() & getAttrMask(A)) != 0;
496}
497
498bool AttributeImpl::hasAttributes() const {
499  return Raw() != 0;
500}
501
502uint64_t AttributeImpl::getAlignment() const {
503  return Raw() & getAttrMask(Attribute::Alignment);
504}
505
506void AttributeImpl::setAlignment(unsigned Align) {
507  Vals.push_back(ConstantInt::get(Type::getInt64Ty(Context), Align));
508}
509
510uint64_t AttributeImpl::getStackAlignment() const {
511  return Raw() & getAttrMask(Attribute::StackAlignment);
512}
513
514void AttributeImpl::setStackAlignment(unsigned Align) {
515  Vals.push_back(ConstantInt::get(Type::getInt64Ty(Context), Align));
516}
517
518void AttributeImpl::Profile(FoldingSetNodeID &ID, Constant *Data,
519                            ArrayRef<Constant*> Vals) {
520  ID.AddInteger(cast<ConstantInt>(Data)->getZExtValue());
521#if 0
522  // FIXME: Not yet supported.
523  for (ArrayRef<Constant*>::iterator I = Vals.begin(), E = Vals.end();
524       I != E; ++I)
525    ID.AddPointer(*I);
526#endif
527}
528
529//===----------------------------------------------------------------------===//
530// AttributeWithIndex Definition
531//===----------------------------------------------------------------------===//
532
533AttributeWithIndex AttributeWithIndex::get(LLVMContext &C, unsigned Idx,
534                                           AttributeSet AS) {
535  // FIXME: This is temporary, but necessary for the conversion.
536  AttrBuilder B(AS, Idx);
537  return get(Idx, Attribute::get(C, B));
538}
539
540//===----------------------------------------------------------------------===//
541// AttributeSetImpl Definition
542//===----------------------------------------------------------------------===//
543
544AttributeSet AttributeSet::getParamAttributes(unsigned Idx) const {
545  // FIXME: Remove.
546  return AttrList && hasAttributes(Idx) ?
547    AttributeSet::get(AttrList->getContext(),
548                      AttributeWithIndex::get(Idx, getAttributes(Idx))) :
549    AttributeSet();
550}
551
552AttributeSet AttributeSet::getRetAttributes() const {
553  // FIXME: Remove.
554  return AttrList && hasAttributes(ReturnIndex) ?
555    AttributeSet::get(AttrList->getContext(),
556                      AttributeWithIndex::get(ReturnIndex,
557                                              getAttributes(ReturnIndex))) :
558    AttributeSet();
559}
560
561AttributeSet AttributeSet::getFnAttributes() const {
562  // FIXME: Remove.
563  return AttrList && hasAttributes(FunctionIndex) ?
564    AttributeSet::get(AttrList->getContext(),
565                      AttributeWithIndex::get(FunctionIndex,
566                                              getAttributes(FunctionIndex))) :
567    AttributeSet();
568}
569
570AttributeSet AttributeSet::get(LLVMContext &C,
571                               ArrayRef<AttributeWithIndex> Attrs) {
572  // If there are no attributes then return a null AttributesList pointer.
573  if (Attrs.empty())
574    return AttributeSet();
575
576#ifndef NDEBUG
577  for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
578    assert(Attrs[i].Attrs.hasAttributes() &&
579           "Pointless attribute!");
580    assert((!i || Attrs[i-1].Index < Attrs[i].Index) &&
581           "Misordered AttributesList!");
582  }
583#endif
584
585  // Otherwise, build a key to look up the existing attributes.
586  LLVMContextImpl *pImpl = C.pImpl;
587  FoldingSetNodeID ID;
588  AttributeSetImpl::Profile(ID, Attrs);
589
590  void *InsertPoint;
591  AttributeSetImpl *PA = pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
592
593  // If we didn't find any existing attributes of the same shape then
594  // create a new one and insert it.
595  if (!PA) {
596    PA = new AttributeSetImpl(C, Attrs);
597    pImpl->AttrsLists.InsertNode(PA, InsertPoint);
598  }
599
600  // Return the AttributesList that we found or created.
601  return AttributeSet(PA);
602}
603
604AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, AttrBuilder &B) {
605  // FIXME: This should be implemented as a loop that creates the
606  // AttributeWithIndexes that then are used to create the AttributeSet.
607  if (!B.hasAttributes())
608    return AttributeSet();
609  return get(C, AttributeWithIndex::get(Idx, Attribute::get(C, B)));
610}
611
612AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx,
613                               Attribute::AttrKind Kind) {
614  return get(C, AttributeWithIndex::get(Idx, Attribute::get(C, Kind)));
615}
616
617//===----------------------------------------------------------------------===//
618// AttributeSet Method Implementations
619//===----------------------------------------------------------------------===//
620
621const AttributeSet &AttributeSet::operator=(const AttributeSet &RHS) {
622  AttrList = RHS.AttrList;
623  return *this;
624}
625
626/// getNumSlots - Return the number of slots used in this attribute list.
627/// This is the number of arguments that have an attribute set on them
628/// (including the function itself).
629unsigned AttributeSet::getNumSlots() const {
630  return AttrList ? AttrList->getNumAttributes() : 0;
631}
632
633/// getSlot - Return the AttributeWithIndex at the specified slot.  This
634/// holds a number plus a set of attributes.
635const AttributeWithIndex &AttributeSet::getSlot(unsigned Slot) const {
636  assert(AttrList && Slot < AttrList->getNumAttributes() &&
637         "Slot # out of range!");
638  return AttrList->getAttributes()[Slot];
639}
640
641bool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{
642  return getAttributes(Index).hasAttribute(Kind);
643}
644
645bool AttributeSet::hasAttributes(unsigned Index) const {
646  return getAttributes(Index).hasAttributes();
647}
648
649std::string AttributeSet::getAsString(unsigned Index) const {
650  return getAttributes(Index).getAsString();
651}
652
653unsigned AttributeSet::getParamAlignment(unsigned Idx) const {
654  return getAttributes(Idx).getAlignment();
655}
656
657unsigned AttributeSet::getStackAlignment(unsigned Index) const {
658  return getAttributes(Index).getStackAlignment();
659}
660
661uint64_t AttributeSet::Raw(unsigned Index) const {
662  // FIXME: Remove this.
663  return getAttributes(Index).Raw();
664}
665
666/// getAttributes - The attributes for the specified index are returned.
667Attribute AttributeSet::getAttributes(unsigned Idx) const {
668  if (AttrList == 0) return Attribute();
669
670  ArrayRef<AttributeWithIndex> Attrs = AttrList->getAttributes();
671  for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i)
672    if (Attrs[i].Index == Idx)
673      return Attrs[i].Attrs;
674
675  return Attribute();
676}
677
678/// hasAttrSomewhere - Return true if the specified attribute is set for at
679/// least one parameter or for the return value.
680bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const {
681  if (AttrList == 0) return false;
682
683  ArrayRef<AttributeWithIndex> Attrs = AttrList->getAttributes();
684  for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
685    if (Attrs[i].Attrs.hasAttribute(Attr))
686      return true;
687
688  return false;
689}
690
691AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Idx,
692                                        Attribute::AttrKind Attr) const {
693  return addAttr(C, Idx, Attribute::get(C, Attr));
694}
695
696AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx,
697                                         AttributeSet Attrs) const {
698  return addAttr(C, Idx, Attrs.getAttributes(Idx));
699}
700
701AttributeSet AttributeSet::addAttr(LLVMContext &C, unsigned Idx,
702                                   Attribute Attrs) const {
703  Attribute OldAttrs = getAttributes(Idx);
704#ifndef NDEBUG
705  // FIXME it is not obvious how this should work for alignment.
706  // For now, say we can't change a known alignment.
707  unsigned OldAlign = OldAttrs.getAlignment();
708  unsigned NewAlign = Attrs.getAlignment();
709  assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
710         "Attempt to change alignment!");
711#endif
712
713  AttrBuilder NewAttrs =
714    AttrBuilder(OldAttrs).addAttributes(Attrs);
715  if (NewAttrs == AttrBuilder(OldAttrs))
716    return *this;
717
718  SmallVector<AttributeWithIndex, 8> NewAttrList;
719  if (AttrList == 0)
720    NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
721  else {
722    ArrayRef<AttributeWithIndex> OldAttrList = AttrList->getAttributes();
723    unsigned i = 0, e = OldAttrList.size();
724    // Copy attributes for arguments before this one.
725    for (; i != e && OldAttrList[i].Index < Idx; ++i)
726      NewAttrList.push_back(OldAttrList[i]);
727
728    // If there are attributes already at this index, merge them in.
729    if (i != e && OldAttrList[i].Index == Idx) {
730      Attrs =
731        Attribute::get(C, AttrBuilder(Attrs).
732                        addAttributes(OldAttrList[i].Attrs));
733      ++i;
734    }
735
736    NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
737
738    // Copy attributes for arguments after this one.
739    NewAttrList.insert(NewAttrList.end(),
740                       OldAttrList.begin()+i, OldAttrList.end());
741  }
742
743  return get(C, NewAttrList);
744}
745
746AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Idx,
747                                           Attribute::AttrKind Attr) const {
748  return removeAttr(C, Idx, Attribute::get(C, Attr));
749}
750
751AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx,
752                                            AttributeSet Attrs) const {
753  return removeAttr(C, Idx, Attrs.getAttributes(Idx));
754}
755
756AttributeSet AttributeSet::removeAttr(LLVMContext &C, unsigned Idx,
757                                      Attribute Attrs) const {
758#ifndef NDEBUG
759  // FIXME it is not obvious how this should work for alignment.
760  // For now, say we can't pass in alignment, which no current use does.
761  assert(!Attrs.hasAttribute(Attribute::Alignment) &&
762         "Attempt to exclude alignment!");
763#endif
764  if (AttrList == 0) return AttributeSet();
765
766  Attribute OldAttrs = getAttributes(Idx);
767  AttrBuilder NewAttrs =
768    AttrBuilder(OldAttrs).removeAttributes(Attrs);
769  if (NewAttrs == AttrBuilder(OldAttrs))
770    return *this;
771
772  SmallVector<AttributeWithIndex, 8> NewAttrList;
773  ArrayRef<AttributeWithIndex> OldAttrList = AttrList->getAttributes();
774  unsigned i = 0, e = OldAttrList.size();
775
776  // Copy attributes for arguments before this one.
777  for (; i != e && OldAttrList[i].Index < Idx; ++i)
778    NewAttrList.push_back(OldAttrList[i]);
779
780  // If there are attributes already at this index, merge them in.
781  assert(OldAttrList[i].Index == Idx && "Attribute isn't set?");
782  Attrs = Attribute::get(C, AttrBuilder(OldAttrList[i].Attrs).
783                          removeAttributes(Attrs));
784  ++i;
785  if (Attrs.hasAttributes()) // If any attributes left for this param, add them.
786    NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
787
788  // Copy attributes for arguments after this one.
789  NewAttrList.insert(NewAttrList.end(),
790                     OldAttrList.begin()+i, OldAttrList.end());
791
792  return get(C, NewAttrList);
793}
794
795void AttributeSet::dump() const {
796  dbgs() << "PAL[ ";
797  for (unsigned i = 0; i < getNumSlots(); ++i) {
798    const AttributeWithIndex &PAWI = getSlot(i);
799    dbgs() << "{ " << PAWI.Index << ", " << PAWI.Attrs.getAsString() << " } ";
800  }
801
802  dbgs() << "]\n";
803}
804