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