1249259Sdim//===-- Attributes.cpp - Implement AttributesList -------------------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// \file
11249259Sdim// \brief This file implements the Attribute, AttributeImpl, AttrBuilder,
12249259Sdim// AttributeSetImpl, and AttributeSet classes.
13249259Sdim//
14249259Sdim//===----------------------------------------------------------------------===//
15249259Sdim
16249259Sdim#include "llvm/IR/Attributes.h"
17296417Sdim#include "llvm/IR/Function.h"
18249259Sdim#include "AttributeImpl.h"
19249259Sdim#include "LLVMContextImpl.h"
20276479Sdim#include "llvm/ADT/STLExtras.h"
21249259Sdim#include "llvm/ADT/StringExtras.h"
22249259Sdim#include "llvm/IR/Type.h"
23249259Sdim#include "llvm/Support/Atomic.h"
24249259Sdim#include "llvm/Support/Debug.h"
25249259Sdim#include "llvm/Support/ManagedStatic.h"
26249259Sdim#include "llvm/Support/Mutex.h"
27249259Sdim#include "llvm/Support/raw_ostream.h"
28249259Sdim#include <algorithm>
29249259Sdimusing namespace llvm;
30249259Sdim
31249259Sdim//===----------------------------------------------------------------------===//
32249259Sdim// Attribute Construction Methods
33249259Sdim//===----------------------------------------------------------------------===//
34249259Sdim
35249259SdimAttribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
36249259Sdim                         uint64_t Val) {
37249259Sdim  LLVMContextImpl *pImpl = Context.pImpl;
38249259Sdim  FoldingSetNodeID ID;
39249259Sdim  ID.AddInteger(Kind);
40249259Sdim  if (Val) ID.AddInteger(Val);
41249259Sdim
42249259Sdim  void *InsertPoint;
43249259Sdim  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
44249259Sdim
45249259Sdim  if (!PA) {
46249259Sdim    // If we didn't find any existing attributes of the same shape then create a
47249259Sdim    // new one and insert it.
48261991Sdim    if (!Val)
49261991Sdim      PA = new EnumAttributeImpl(Kind);
50261991Sdim    else
51276479Sdim      PA = new IntAttributeImpl(Kind, Val);
52249259Sdim    pImpl->AttrsSet.InsertNode(PA, InsertPoint);
53249259Sdim  }
54249259Sdim
55249259Sdim  // Return the Attribute that we found or created.
56249259Sdim  return Attribute(PA);
57249259Sdim}
58249259Sdim
59249259SdimAttribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
60249259Sdim  LLVMContextImpl *pImpl = Context.pImpl;
61249259Sdim  FoldingSetNodeID ID;
62249259Sdim  ID.AddString(Kind);
63249259Sdim  if (!Val.empty()) ID.AddString(Val);
64249259Sdim
65249259Sdim  void *InsertPoint;
66249259Sdim  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
67249259Sdim
68249259Sdim  if (!PA) {
69249259Sdim    // If we didn't find any existing attributes of the same shape then create a
70249259Sdim    // new one and insert it.
71261991Sdim    PA = new StringAttributeImpl(Kind, Val);
72249259Sdim    pImpl->AttrsSet.InsertNode(PA, InsertPoint);
73249259Sdim  }
74249259Sdim
75249259Sdim  // Return the Attribute that we found or created.
76249259Sdim  return Attribute(PA);
77249259Sdim}
78249259Sdim
79249259SdimAttribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) {
80249259Sdim  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
81249259Sdim  assert(Align <= 0x40000000 && "Alignment too large.");
82249259Sdim  return get(Context, Alignment, Align);
83249259Sdim}
84249259Sdim
85249259SdimAttribute Attribute::getWithStackAlignment(LLVMContext &Context,
86249259Sdim                                           uint64_t Align) {
87249259Sdim  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
88249259Sdim  assert(Align <= 0x100 && "Alignment too large.");
89249259Sdim  return get(Context, StackAlignment, Align);
90249259Sdim}
91249259Sdim
92276479SdimAttribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
93276479Sdim                                                uint64_t Bytes) {
94276479Sdim  assert(Bytes && "Bytes must be non-zero.");
95276479Sdim  return get(Context, Dereferenceable, Bytes);
96276479Sdim}
97276479Sdim
98288943SdimAttribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
99288943Sdim                                                       uint64_t Bytes) {
100288943Sdim  assert(Bytes && "Bytes must be non-zero.");
101288943Sdim  return get(Context, DereferenceableOrNull, Bytes);
102288943Sdim}
103288943Sdim
104249259Sdim//===----------------------------------------------------------------------===//
105249259Sdim// Attribute Accessor Methods
106249259Sdim//===----------------------------------------------------------------------===//
107249259Sdim
108249259Sdimbool Attribute::isEnumAttribute() const {
109249259Sdim  return pImpl && pImpl->isEnumAttribute();
110249259Sdim}
111249259Sdim
112276479Sdimbool Attribute::isIntAttribute() const {
113276479Sdim  return pImpl && pImpl->isIntAttribute();
114249259Sdim}
115249259Sdim
116249259Sdimbool Attribute::isStringAttribute() const {
117249259Sdim  return pImpl && pImpl->isStringAttribute();
118249259Sdim}
119249259Sdim
120249259SdimAttribute::AttrKind Attribute::getKindAsEnum() const {
121261991Sdim  if (!pImpl) return None;
122276479Sdim  assert((isEnumAttribute() || isIntAttribute()) &&
123249259Sdim         "Invalid attribute type to get the kind as an enum!");
124296417Sdim  return pImpl->getKindAsEnum();
125249259Sdim}
126249259Sdim
127249259Sdimuint64_t Attribute::getValueAsInt() const {
128261991Sdim  if (!pImpl) return 0;
129276479Sdim  assert(isIntAttribute() &&
130276479Sdim         "Expected the attribute to be an integer attribute!");
131296417Sdim  return pImpl->getValueAsInt();
132249259Sdim}
133249259Sdim
134249259SdimStringRef Attribute::getKindAsString() const {
135261991Sdim  if (!pImpl) return StringRef();
136249259Sdim  assert(isStringAttribute() &&
137249259Sdim         "Invalid attribute type to get the kind as a string!");
138296417Sdim  return pImpl->getKindAsString();
139249259Sdim}
140249259Sdim
141249259SdimStringRef Attribute::getValueAsString() const {
142261991Sdim  if (!pImpl) return StringRef();
143249259Sdim  assert(isStringAttribute() &&
144249259Sdim         "Invalid attribute type to get the value as a string!");
145296417Sdim  return pImpl->getValueAsString();
146249259Sdim}
147249259Sdim
148249259Sdimbool Attribute::hasAttribute(AttrKind Kind) const {
149249259Sdim  return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
150249259Sdim}
151249259Sdim
152249259Sdimbool Attribute::hasAttribute(StringRef Kind) const {
153249259Sdim  if (!isStringAttribute()) return false;
154249259Sdim  return pImpl && pImpl->hasAttribute(Kind);
155249259Sdim}
156249259Sdim
157249259Sdim/// This returns the alignment field of an attribute as a byte alignment value.
158249259Sdimunsigned Attribute::getAlignment() const {
159249259Sdim  assert(hasAttribute(Attribute::Alignment) &&
160249259Sdim         "Trying to get alignment from non-alignment attribute!");
161249259Sdim  return pImpl->getValueAsInt();
162249259Sdim}
163249259Sdim
164249259Sdim/// This returns the stack alignment field of an attribute as a byte alignment
165249259Sdim/// value.
166249259Sdimunsigned Attribute::getStackAlignment() const {
167249259Sdim  assert(hasAttribute(Attribute::StackAlignment) &&
168249259Sdim         "Trying to get alignment from non-alignment attribute!");
169249259Sdim  return pImpl->getValueAsInt();
170249259Sdim}
171249259Sdim
172276479Sdim/// This returns the number of dereferenceable bytes.
173276479Sdimuint64_t Attribute::getDereferenceableBytes() const {
174276479Sdim  assert(hasAttribute(Attribute::Dereferenceable) &&
175276479Sdim         "Trying to get dereferenceable bytes from "
176276479Sdim         "non-dereferenceable attribute!");
177276479Sdim  return pImpl->getValueAsInt();
178276479Sdim}
179276479Sdim
180288943Sdimuint64_t Attribute::getDereferenceableOrNullBytes() const {
181288943Sdim  assert(hasAttribute(Attribute::DereferenceableOrNull) &&
182288943Sdim         "Trying to get dereferenceable bytes from "
183288943Sdim         "non-dereferenceable attribute!");
184288943Sdim  return pImpl->getValueAsInt();
185288943Sdim}
186288943Sdim
187249259Sdimstd::string Attribute::getAsString(bool InAttrGrp) const {
188249259Sdim  if (!pImpl) return "";
189249259Sdim
190249259Sdim  if (hasAttribute(Attribute::SanitizeAddress))
191249259Sdim    return "sanitize_address";
192249259Sdim  if (hasAttribute(Attribute::AlwaysInline))
193249259Sdim    return "alwaysinline";
194288943Sdim  if (hasAttribute(Attribute::ArgMemOnly))
195288943Sdim    return "argmemonly";
196261991Sdim  if (hasAttribute(Attribute::Builtin))
197261991Sdim    return "builtin";
198249259Sdim  if (hasAttribute(Attribute::ByVal))
199249259Sdim    return "byval";
200288943Sdim  if (hasAttribute(Attribute::Convergent))
201288943Sdim    return "convergent";
202296417Sdim  if (hasAttribute(Attribute::InaccessibleMemOnly))
203296417Sdim    return "inaccessiblememonly";
204296417Sdim  if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
205296417Sdim    return "inaccessiblemem_or_argmemonly";
206276479Sdim  if (hasAttribute(Attribute::InAlloca))
207276479Sdim    return "inalloca";
208249259Sdim  if (hasAttribute(Attribute::InlineHint))
209249259Sdim    return "inlinehint";
210249259Sdim  if (hasAttribute(Attribute::InReg))
211249259Sdim    return "inreg";
212276479Sdim  if (hasAttribute(Attribute::JumpTable))
213276479Sdim    return "jumptable";
214249259Sdim  if (hasAttribute(Attribute::MinSize))
215249259Sdim    return "minsize";
216249259Sdim  if (hasAttribute(Attribute::Naked))
217249259Sdim    return "naked";
218249259Sdim  if (hasAttribute(Attribute::Nest))
219249259Sdim    return "nest";
220249259Sdim  if (hasAttribute(Attribute::NoAlias))
221249259Sdim    return "noalias";
222249259Sdim  if (hasAttribute(Attribute::NoBuiltin))
223249259Sdim    return "nobuiltin";
224249259Sdim  if (hasAttribute(Attribute::NoCapture))
225249259Sdim    return "nocapture";
226249259Sdim  if (hasAttribute(Attribute::NoDuplicate))
227249259Sdim    return "noduplicate";
228249259Sdim  if (hasAttribute(Attribute::NoImplicitFloat))
229249259Sdim    return "noimplicitfloat";
230249259Sdim  if (hasAttribute(Attribute::NoInline))
231249259Sdim    return "noinline";
232249259Sdim  if (hasAttribute(Attribute::NonLazyBind))
233249259Sdim    return "nonlazybind";
234276479Sdim  if (hasAttribute(Attribute::NonNull))
235276479Sdim    return "nonnull";
236249259Sdim  if (hasAttribute(Attribute::NoRedZone))
237249259Sdim    return "noredzone";
238249259Sdim  if (hasAttribute(Attribute::NoReturn))
239249259Sdim    return "noreturn";
240296417Sdim  if (hasAttribute(Attribute::NoRecurse))
241296417Sdim    return "norecurse";
242249259Sdim  if (hasAttribute(Attribute::NoUnwind))
243249259Sdim    return "nounwind";
244261991Sdim  if (hasAttribute(Attribute::OptimizeNone))
245261991Sdim    return "optnone";
246249259Sdim  if (hasAttribute(Attribute::OptimizeForSize))
247249259Sdim    return "optsize";
248249259Sdim  if (hasAttribute(Attribute::ReadNone))
249249259Sdim    return "readnone";
250249259Sdim  if (hasAttribute(Attribute::ReadOnly))
251249259Sdim    return "readonly";
252251662Sdim  if (hasAttribute(Attribute::Returned))
253251662Sdim    return "returned";
254249259Sdim  if (hasAttribute(Attribute::ReturnsTwice))
255249259Sdim    return "returns_twice";
256249259Sdim  if (hasAttribute(Attribute::SExt))
257249259Sdim    return "signext";
258249259Sdim  if (hasAttribute(Attribute::StackProtect))
259249259Sdim    return "ssp";
260249259Sdim  if (hasAttribute(Attribute::StackProtectReq))
261249259Sdim    return "sspreq";
262249259Sdim  if (hasAttribute(Attribute::StackProtectStrong))
263249259Sdim    return "sspstrong";
264288943Sdim  if (hasAttribute(Attribute::SafeStack))
265288943Sdim    return "safestack";
266249259Sdim  if (hasAttribute(Attribute::StructRet))
267249259Sdim    return "sret";
268249259Sdim  if (hasAttribute(Attribute::SanitizeThread))
269249259Sdim    return "sanitize_thread";
270249259Sdim  if (hasAttribute(Attribute::SanitizeMemory))
271249259Sdim    return "sanitize_memory";
272249259Sdim  if (hasAttribute(Attribute::UWTable))
273249259Sdim    return "uwtable";
274249259Sdim  if (hasAttribute(Attribute::ZExt))
275249259Sdim    return "zeroext";
276261991Sdim  if (hasAttribute(Attribute::Cold))
277261991Sdim    return "cold";
278249259Sdim
279249259Sdim  // FIXME: These should be output like this:
280249259Sdim  //
281249259Sdim  //   align=4
282249259Sdim  //   alignstack=8
283249259Sdim  //
284249259Sdim  if (hasAttribute(Attribute::Alignment)) {
285249259Sdim    std::string Result;
286249259Sdim    Result += "align";
287249259Sdim    Result += (InAttrGrp) ? "=" : " ";
288249259Sdim    Result += utostr(getValueAsInt());
289249259Sdim    return Result;
290249259Sdim  }
291249259Sdim
292288943Sdim  auto AttrWithBytesToString = [&](const char *Name) {
293249259Sdim    std::string Result;
294288943Sdim    Result += Name;
295249259Sdim    if (InAttrGrp) {
296249259Sdim      Result += "=";
297249259Sdim      Result += utostr(getValueAsInt());
298249259Sdim    } else {
299249259Sdim      Result += "(";
300249259Sdim      Result += utostr(getValueAsInt());
301249259Sdim      Result += ")";
302249259Sdim    }
303249259Sdim    return Result;
304288943Sdim  };
305249259Sdim
306288943Sdim  if (hasAttribute(Attribute::StackAlignment))
307288943Sdim    return AttrWithBytesToString("alignstack");
308276479Sdim
309288943Sdim  if (hasAttribute(Attribute::Dereferenceable))
310288943Sdim    return AttrWithBytesToString("dereferenceable");
311288943Sdim
312288943Sdim  if (hasAttribute(Attribute::DereferenceableOrNull))
313288943Sdim    return AttrWithBytesToString("dereferenceable_or_null");
314288943Sdim
315249259Sdim  // Convert target-dependent attributes to strings of the form:
316249259Sdim  //
317249259Sdim  //   "kind"
318249259Sdim  //   "kind" = "value"
319249259Sdim  //
320249259Sdim  if (isStringAttribute()) {
321249259Sdim    std::string Result;
322288943Sdim    Result += (Twine('"') + getKindAsString() + Twine('"')).str();
323249259Sdim
324249259Sdim    StringRef Val = pImpl->getValueAsString();
325249259Sdim    if (Val.empty()) return Result;
326249259Sdim
327288943Sdim    Result += ("=\"" + Val + Twine('"')).str();
328249259Sdim    return Result;
329249259Sdim  }
330249259Sdim
331249259Sdim  llvm_unreachable("Unknown attribute");
332249259Sdim}
333249259Sdim
334249259Sdimbool Attribute::operator<(Attribute A) const {
335249259Sdim  if (!pImpl && !A.pImpl) return false;
336249259Sdim  if (!pImpl) return true;
337249259Sdim  if (!A.pImpl) return false;
338249259Sdim  return *pImpl < *A.pImpl;
339249259Sdim}
340249259Sdim
341249259Sdim//===----------------------------------------------------------------------===//
342249259Sdim// AttributeImpl Definition
343249259Sdim//===----------------------------------------------------------------------===//
344249259Sdim
345276479Sdim// Pin the vtables to this file.
346261991SdimAttributeImpl::~AttributeImpl() {}
347261991Sdimvoid EnumAttributeImpl::anchor() {}
348276479Sdimvoid IntAttributeImpl::anchor() {}
349261991Sdimvoid StringAttributeImpl::anchor() {}
350249259Sdim
351249259Sdimbool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
352249259Sdim  if (isStringAttribute()) return false;
353249259Sdim  return getKindAsEnum() == A;
354249259Sdim}
355249259Sdim
356249259Sdimbool AttributeImpl::hasAttribute(StringRef Kind) const {
357249259Sdim  if (!isStringAttribute()) return false;
358249259Sdim  return getKindAsString() == Kind;
359249259Sdim}
360249259Sdim
361249259SdimAttribute::AttrKind AttributeImpl::getKindAsEnum() const {
362276479Sdim  assert(isEnumAttribute() || isIntAttribute());
363261991Sdim  return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
364249259Sdim}
365249259Sdim
366249259Sdimuint64_t AttributeImpl::getValueAsInt() const {
367276479Sdim  assert(isIntAttribute());
368276479Sdim  return static_cast<const IntAttributeImpl *>(this)->getValue();
369249259Sdim}
370249259Sdim
371249259SdimStringRef AttributeImpl::getKindAsString() const {
372261991Sdim  assert(isStringAttribute());
373261991Sdim  return static_cast<const StringAttributeImpl *>(this)->getStringKind();
374249259Sdim}
375249259Sdim
376249259SdimStringRef AttributeImpl::getValueAsString() const {
377261991Sdim  assert(isStringAttribute());
378261991Sdim  return static_cast<const StringAttributeImpl *>(this)->getStringValue();
379249259Sdim}
380249259Sdim
381249259Sdimbool AttributeImpl::operator<(const AttributeImpl &AI) const {
382249259Sdim  // This sorts the attributes with Attribute::AttrKinds coming first (sorted
383249259Sdim  // relative to their enum value) and then strings.
384249259Sdim  if (isEnumAttribute()) {
385249259Sdim    if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();
386276479Sdim    if (AI.isIntAttribute()) return true;
387249259Sdim    if (AI.isStringAttribute()) return true;
388249259Sdim  }
389249259Sdim
390276479Sdim  if (isIntAttribute()) {
391249259Sdim    if (AI.isEnumAttribute()) return false;
392276479Sdim    if (AI.isIntAttribute()) return getValueAsInt() < AI.getValueAsInt();
393249259Sdim    if (AI.isStringAttribute()) return true;
394249259Sdim  }
395249259Sdim
396249259Sdim  if (AI.isEnumAttribute()) return false;
397276479Sdim  if (AI.isIntAttribute()) return false;
398249259Sdim  if (getKindAsString() == AI.getKindAsString())
399249259Sdim    return getValueAsString() < AI.getValueAsString();
400249259Sdim  return getKindAsString() < AI.getKindAsString();
401249259Sdim}
402249259Sdim
403249259Sdimuint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
404249259Sdim  // FIXME: Remove this.
405249259Sdim  switch (Val) {
406249259Sdim  case Attribute::EndAttrKinds:
407249259Sdim    llvm_unreachable("Synthetic enumerators which should never get here");
408249259Sdim
409249259Sdim  case Attribute::None:            return 0;
410249259Sdim  case Attribute::ZExt:            return 1 << 0;
411249259Sdim  case Attribute::SExt:            return 1 << 1;
412249259Sdim  case Attribute::NoReturn:        return 1 << 2;
413249259Sdim  case Attribute::InReg:           return 1 << 3;
414249259Sdim  case Attribute::StructRet:       return 1 << 4;
415249259Sdim  case Attribute::NoUnwind:        return 1 << 5;
416249259Sdim  case Attribute::NoAlias:         return 1 << 6;
417249259Sdim  case Attribute::ByVal:           return 1 << 7;
418249259Sdim  case Attribute::Nest:            return 1 << 8;
419249259Sdim  case Attribute::ReadNone:        return 1 << 9;
420249259Sdim  case Attribute::ReadOnly:        return 1 << 10;
421249259Sdim  case Attribute::NoInline:        return 1 << 11;
422249259Sdim  case Attribute::AlwaysInline:    return 1 << 12;
423249259Sdim  case Attribute::OptimizeForSize: return 1 << 13;
424249259Sdim  case Attribute::StackProtect:    return 1 << 14;
425249259Sdim  case Attribute::StackProtectReq: return 1 << 15;
426249259Sdim  case Attribute::Alignment:       return 31 << 16;
427249259Sdim  case Attribute::NoCapture:       return 1 << 21;
428249259Sdim  case Attribute::NoRedZone:       return 1 << 22;
429249259Sdim  case Attribute::NoImplicitFloat: return 1 << 23;
430249259Sdim  case Attribute::Naked:           return 1 << 24;
431249259Sdim  case Attribute::InlineHint:      return 1 << 25;
432249259Sdim  case Attribute::StackAlignment:  return 7 << 26;
433249259Sdim  case Attribute::ReturnsTwice:    return 1 << 29;
434249259Sdim  case Attribute::UWTable:         return 1 << 30;
435249259Sdim  case Attribute::NonLazyBind:     return 1U << 31;
436249259Sdim  case Attribute::SanitizeAddress: return 1ULL << 32;
437249259Sdim  case Attribute::MinSize:         return 1ULL << 33;
438249259Sdim  case Attribute::NoDuplicate:     return 1ULL << 34;
439249259Sdim  case Attribute::StackProtectStrong: return 1ULL << 35;
440249259Sdim  case Attribute::SanitizeThread:  return 1ULL << 36;
441249259Sdim  case Attribute::SanitizeMemory:  return 1ULL << 37;
442249259Sdim  case Attribute::NoBuiltin:       return 1ULL << 38;
443251662Sdim  case Attribute::Returned:        return 1ULL << 39;
444261991Sdim  case Attribute::Cold:            return 1ULL << 40;
445261991Sdim  case Attribute::Builtin:         return 1ULL << 41;
446261991Sdim  case Attribute::OptimizeNone:    return 1ULL << 42;
447276479Sdim  case Attribute::InAlloca:        return 1ULL << 43;
448276479Sdim  case Attribute::NonNull:         return 1ULL << 44;
449276479Sdim  case Attribute::JumpTable:       return 1ULL << 45;
450288943Sdim  case Attribute::Convergent:      return 1ULL << 46;
451288943Sdim  case Attribute::SafeStack:       return 1ULL << 47;
452296417Sdim  case Attribute::NoRecurse:       return 1ULL << 48;
453296417Sdim  case Attribute::InaccessibleMemOnly:         return 1ULL << 49;
454296417Sdim  case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50;
455276479Sdim  case Attribute::Dereferenceable:
456276479Sdim    llvm_unreachable("dereferenceable attribute not supported in raw format");
457288943Sdim    break;
458288943Sdim  case Attribute::DereferenceableOrNull:
459288943Sdim    llvm_unreachable("dereferenceable_or_null attribute not supported in raw "
460288943Sdim                     "format");
461288943Sdim    break;
462288943Sdim  case Attribute::ArgMemOnly:
463288943Sdim    llvm_unreachable("argmemonly attribute not supported in raw format");
464288943Sdim    break;
465249259Sdim  }
466249259Sdim  llvm_unreachable("Unsupported attribute type");
467249259Sdim}
468249259Sdim
469249259Sdim//===----------------------------------------------------------------------===//
470249259Sdim// AttributeSetNode Definition
471249259Sdim//===----------------------------------------------------------------------===//
472249259Sdim
473249259SdimAttributeSetNode *AttributeSetNode::get(LLVMContext &C,
474249259Sdim                                        ArrayRef<Attribute> Attrs) {
475249259Sdim  if (Attrs.empty())
476276479Sdim    return nullptr;
477249259Sdim
478249259Sdim  // Otherwise, build a key to look up the existing attributes.
479249259Sdim  LLVMContextImpl *pImpl = C.pImpl;
480249259Sdim  FoldingSetNodeID ID;
481249259Sdim
482249259Sdim  SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
483249259Sdim  array_pod_sort(SortedAttrs.begin(), SortedAttrs.end());
484249259Sdim
485296417Sdim  for (Attribute Attr : SortedAttrs)
486296417Sdim    Attr.Profile(ID);
487249259Sdim
488249259Sdim  void *InsertPoint;
489249259Sdim  AttributeSetNode *PA =
490249259Sdim    pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
491249259Sdim
492249259Sdim  // If we didn't find any existing attributes of the same shape then create a
493249259Sdim  // new one and insert it.
494249259Sdim  if (!PA) {
495261991Sdim    // Coallocate entries after the AttributeSetNode itself.
496296417Sdim    void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
497261991Sdim    PA = new (Mem) AttributeSetNode(SortedAttrs);
498249259Sdim    pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
499249259Sdim  }
500249259Sdim
501249259Sdim  // Return the AttributesListNode that we found or created.
502249259Sdim  return PA;
503249259Sdim}
504249259Sdim
505249259Sdimbool AttributeSetNode::hasAttribute(Attribute::AttrKind Kind) const {
506261991Sdim  for (iterator I = begin(), E = end(); I != E; ++I)
507249259Sdim    if (I->hasAttribute(Kind))
508249259Sdim      return true;
509249259Sdim  return false;
510249259Sdim}
511249259Sdim
512249259Sdimbool AttributeSetNode::hasAttribute(StringRef Kind) const {
513261991Sdim  for (iterator I = begin(), E = end(); I != E; ++I)
514249259Sdim    if (I->hasAttribute(Kind))
515249259Sdim      return true;
516249259Sdim  return false;
517249259Sdim}
518249259Sdim
519249259SdimAttribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
520261991Sdim  for (iterator I = begin(), E = end(); I != E; ++I)
521249259Sdim    if (I->hasAttribute(Kind))
522249259Sdim      return *I;
523249259Sdim  return Attribute();
524249259Sdim}
525249259Sdim
526249259SdimAttribute AttributeSetNode::getAttribute(StringRef Kind) const {
527261991Sdim  for (iterator I = begin(), E = end(); I != E; ++I)
528249259Sdim    if (I->hasAttribute(Kind))
529249259Sdim      return *I;
530249259Sdim  return Attribute();
531249259Sdim}
532249259Sdim
533249259Sdimunsigned AttributeSetNode::getAlignment() const {
534261991Sdim  for (iterator I = begin(), E = end(); I != E; ++I)
535249259Sdim    if (I->hasAttribute(Attribute::Alignment))
536249259Sdim      return I->getAlignment();
537249259Sdim  return 0;
538249259Sdim}
539249259Sdim
540249259Sdimunsigned AttributeSetNode::getStackAlignment() const {
541261991Sdim  for (iterator I = begin(), E = end(); I != E; ++I)
542249259Sdim    if (I->hasAttribute(Attribute::StackAlignment))
543249259Sdim      return I->getStackAlignment();
544249259Sdim  return 0;
545249259Sdim}
546249259Sdim
547276479Sdimuint64_t AttributeSetNode::getDereferenceableBytes() const {
548276479Sdim  for (iterator I = begin(), E = end(); I != E; ++I)
549276479Sdim    if (I->hasAttribute(Attribute::Dereferenceable))
550276479Sdim      return I->getDereferenceableBytes();
551276479Sdim  return 0;
552276479Sdim}
553276479Sdim
554288943Sdimuint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
555288943Sdim  for (iterator I = begin(), E = end(); I != E; ++I)
556288943Sdim    if (I->hasAttribute(Attribute::DereferenceableOrNull))
557288943Sdim      return I->getDereferenceableOrNullBytes();
558288943Sdim  return 0;
559288943Sdim}
560288943Sdim
561249259Sdimstd::string AttributeSetNode::getAsString(bool InAttrGrp) const {
562251662Sdim  std::string Str;
563261991Sdim  for (iterator I = begin(), E = end(); I != E; ++I) {
564261991Sdim    if (I != begin())
565251662Sdim      Str += ' ';
566249259Sdim    Str += I->getAsString(InAttrGrp);
567249259Sdim  }
568249259Sdim  return Str;
569249259Sdim}
570249259Sdim
571249259Sdim//===----------------------------------------------------------------------===//
572249259Sdim// AttributeSetImpl Definition
573249259Sdim//===----------------------------------------------------------------------===//
574249259Sdim
575251662Sdimuint64_t AttributeSetImpl::Raw(unsigned Index) const {
576249259Sdim  for (unsigned I = 0, E = getNumAttributes(); I != E; ++I) {
577249259Sdim    if (getSlotIndex(I) != Index) continue;
578261991Sdim    const AttributeSetNode *ASN = getSlotNode(I);
579249259Sdim    uint64_t Mask = 0;
580249259Sdim
581261991Sdim    for (AttributeSetNode::iterator II = ASN->begin(),
582249259Sdim           IE = ASN->end(); II != IE; ++II) {
583249259Sdim      Attribute Attr = *II;
584249259Sdim
585249259Sdim      // This cannot handle string attributes.
586249259Sdim      if (Attr.isStringAttribute()) continue;
587249259Sdim
588249259Sdim      Attribute::AttrKind Kind = Attr.getKindAsEnum();
589249259Sdim
590249259Sdim      if (Kind == Attribute::Alignment)
591249259Sdim        Mask |= (Log2_32(ASN->getAlignment()) + 1) << 16;
592249259Sdim      else if (Kind == Attribute::StackAlignment)
593249259Sdim        Mask |= (Log2_32(ASN->getStackAlignment()) + 1) << 26;
594276479Sdim      else if (Kind == Attribute::Dereferenceable)
595276479Sdim        llvm_unreachable("dereferenceable not supported in bit mask");
596249259Sdim      else
597249259Sdim        Mask |= AttributeImpl::getAttrMask(Kind);
598249259Sdim    }
599249259Sdim
600249259Sdim    return Mask;
601249259Sdim  }
602249259Sdim
603249259Sdim  return 0;
604249259Sdim}
605249259Sdim
606261991Sdimvoid AttributeSetImpl::dump() const {
607261991Sdim  AttributeSet(const_cast<AttributeSetImpl *>(this)).dump();
608261991Sdim}
609261991Sdim
610249259Sdim//===----------------------------------------------------------------------===//
611249259Sdim// AttributeSet Construction and Mutation Methods
612249259Sdim//===----------------------------------------------------------------------===//
613249259Sdim
614249259SdimAttributeSet
615249259SdimAttributeSet::getImpl(LLVMContext &C,
616249259Sdim                      ArrayRef<std::pair<unsigned, AttributeSetNode*> > Attrs) {
617249259Sdim  LLVMContextImpl *pImpl = C.pImpl;
618249259Sdim  FoldingSetNodeID ID;
619249259Sdim  AttributeSetImpl::Profile(ID, Attrs);
620249259Sdim
621249259Sdim  void *InsertPoint;
622249259Sdim  AttributeSetImpl *PA = pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
623249259Sdim
624249259Sdim  // If we didn't find any existing attributes of the same shape then
625249259Sdim  // create a new one and insert it.
626249259Sdim  if (!PA) {
627261991Sdim    // Coallocate entries after the AttributeSetImpl itself.
628296417Sdim    void *Mem = ::operator new(
629296417Sdim        AttributeSetImpl::totalSizeToAlloc<IndexAttrPair>(Attrs.size()));
630261991Sdim    PA = new (Mem) AttributeSetImpl(C, Attrs);
631249259Sdim    pImpl->AttrsLists.InsertNode(PA, InsertPoint);
632249259Sdim  }
633249259Sdim
634249259Sdim  // Return the AttributesList that we found or created.
635249259Sdim  return AttributeSet(PA);
636249259Sdim}
637249259Sdim
638249259SdimAttributeSet AttributeSet::get(LLVMContext &C,
639249259Sdim                               ArrayRef<std::pair<unsigned, Attribute> > Attrs){
640249259Sdim  // If there are no attributes then return a null AttributesList pointer.
641249259Sdim  if (Attrs.empty())
642249259Sdim    return AttributeSet();
643249259Sdim
644296417Sdim  assert(std::is_sorted(Attrs.begin(), Attrs.end(),
645296417Sdim                        [](const std::pair<unsigned, Attribute> &LHS,
646296417Sdim                           const std::pair<unsigned, Attribute> &RHS) {
647296417Sdim                          return LHS.first < RHS.first;
648296417Sdim                        }) && "Misordered Attributes list!");
649296417Sdim  assert(std::none_of(Attrs.begin(), Attrs.end(),
650296417Sdim                      [](const std::pair<unsigned, Attribute> &Pair) {
651296417Sdim                        return Pair.second.hasAttribute(Attribute::None);
652296417Sdim                      }) && "Pointless attribute!");
653249259Sdim
654249259Sdim  // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
655249259Sdim  // list.
656249259Sdim  SmallVector<std::pair<unsigned, AttributeSetNode*>, 8> AttrPairVec;
657249259Sdim  for (ArrayRef<std::pair<unsigned, Attribute> >::iterator I = Attrs.begin(),
658249259Sdim         E = Attrs.end(); I != E; ) {
659249259Sdim    unsigned Index = I->first;
660249259Sdim    SmallVector<Attribute, 4> AttrVec;
661249259Sdim    while (I != E && I->first == Index) {
662249259Sdim      AttrVec.push_back(I->second);
663249259Sdim      ++I;
664249259Sdim    }
665249259Sdim
666249259Sdim    AttrPairVec.push_back(std::make_pair(Index,
667249259Sdim                                         AttributeSetNode::get(C, AttrVec)));
668249259Sdim  }
669249259Sdim
670249259Sdim  return getImpl(C, AttrPairVec);
671249259Sdim}
672249259Sdim
673249259SdimAttributeSet AttributeSet::get(LLVMContext &C,
674249259Sdim                               ArrayRef<std::pair<unsigned,
675249259Sdim                                                  AttributeSetNode*> > Attrs) {
676249259Sdim  // If there are no attributes then return a null AttributesList pointer.
677249259Sdim  if (Attrs.empty())
678249259Sdim    return AttributeSet();
679249259Sdim
680249259Sdim  return getImpl(C, Attrs);
681249259Sdim}
682249259Sdim
683276479SdimAttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
684276479Sdim                               const AttrBuilder &B) {
685249259Sdim  if (!B.hasAttributes())
686249259Sdim    return AttributeSet();
687249259Sdim
688249259Sdim  // Add target-independent attributes.
689249259Sdim  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
690249259Sdim  for (Attribute::AttrKind Kind = Attribute::None;
691249259Sdim       Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
692249259Sdim    if (!B.contains(Kind))
693249259Sdim      continue;
694249259Sdim
695296417Sdim    Attribute Attr;
696296417Sdim    switch (Kind) {
697296417Sdim    case Attribute::Alignment:
698296417Sdim      Attr = Attribute::getWithAlignment(C, B.getAlignment());
699296417Sdim      break;
700296417Sdim    case Attribute::StackAlignment:
701296417Sdim      Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment());
702296417Sdim      break;
703296417Sdim    case Attribute::Dereferenceable:
704296417Sdim      Attr = Attribute::getWithDereferenceableBytes(
705296417Sdim          C, B.getDereferenceableBytes());
706296417Sdim      break;
707296417Sdim    case Attribute::DereferenceableOrNull:
708296417Sdim      Attr = Attribute::getWithDereferenceableOrNullBytes(
709296417Sdim          C, B.getDereferenceableOrNullBytes());
710296417Sdim      break;
711296417Sdim    default:
712296417Sdim      Attr = Attribute::get(C, Kind);
713296417Sdim    }
714296417Sdim    Attrs.push_back(std::make_pair(Index, Attr));
715249259Sdim  }
716249259Sdim
717249259Sdim  // Add target-dependent (string) attributes.
718276479Sdim  for (const AttrBuilder::td_type &TDA : B.td_attrs())
719276479Sdim    Attrs.push_back(
720276479Sdim        std::make_pair(Index, Attribute::get(C, TDA.first, TDA.second)));
721249259Sdim
722249259Sdim  return get(C, Attrs);
723249259Sdim}
724249259Sdim
725251662SdimAttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
726249259Sdim                               ArrayRef<Attribute::AttrKind> Kind) {
727249259Sdim  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
728296417Sdim  for (Attribute::AttrKind K : Kind)
729296417Sdim    Attrs.push_back(std::make_pair(Index, Attribute::get(C, K)));
730249259Sdim  return get(C, Attrs);
731249259Sdim}
732249259Sdim
733249259SdimAttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) {
734249259Sdim  if (Attrs.empty()) return AttributeSet();
735261991Sdim  if (Attrs.size() == 1) return Attrs[0];
736249259Sdim
737249259Sdim  SmallVector<std::pair<unsigned, AttributeSetNode*>, 8> AttrNodeVec;
738261991Sdim  AttributeSetImpl *A0 = Attrs[0].pImpl;
739261991Sdim  if (A0)
740261991Sdim    AttrNodeVec.append(A0->getNode(0), A0->getNode(A0->getNumAttributes()));
741261991Sdim  // Copy all attributes from Attrs into AttrNodeVec while keeping AttrNodeVec
742261991Sdim  // ordered by index.  Because we know that each list in Attrs is ordered by
743261991Sdim  // index we only need to merge each successive list in rather than doing a
744261991Sdim  // full sort.
745261991Sdim  for (unsigned I = 1, E = Attrs.size(); I != E; ++I) {
746261991Sdim    AttributeSetImpl *AS = Attrs[I].pImpl;
747261991Sdim    if (!AS) continue;
748261991Sdim    SmallVector<std::pair<unsigned, AttributeSetNode *>, 8>::iterator
749261991Sdim      ANVI = AttrNodeVec.begin(), ANVE;
750296417Sdim    for (const IndexAttrPair *AI = AS->getNode(0),
751296417Sdim                             *AE = AS->getNode(AS->getNumAttributes());
752261991Sdim         AI != AE; ++AI) {
753261991Sdim      ANVE = AttrNodeVec.end();
754261991Sdim      while (ANVI != ANVE && ANVI->first <= AI->first)
755261991Sdim        ++ANVI;
756261991Sdim      ANVI = AttrNodeVec.insert(ANVI, *AI) + 1;
757261991Sdim    }
758249259Sdim  }
759249259Sdim
760249259Sdim  return getImpl(C, AttrNodeVec);
761249259Sdim}
762249259Sdim
763251662SdimAttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
764249259Sdim                                        Attribute::AttrKind Attr) const {
765251662Sdim  if (hasAttribute(Index, Attr)) return *this;
766251662Sdim  return addAttributes(C, Index, AttributeSet::get(C, Index, Attr));
767249259Sdim}
768249259Sdim
769251662SdimAttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
770249259Sdim                                        StringRef Kind) const {
771249259Sdim  llvm::AttrBuilder B;
772249259Sdim  B.addAttribute(Kind);
773251662Sdim  return addAttributes(C, Index, AttributeSet::get(C, Index, B));
774249259Sdim}
775249259Sdim
776261991SdimAttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
777261991Sdim                                        StringRef Kind, StringRef Value) const {
778261991Sdim  llvm::AttrBuilder B;
779261991Sdim  B.addAttribute(Kind, Value);
780261991Sdim  return addAttributes(C, Index, AttributeSet::get(C, Index, B));
781261991Sdim}
782261991Sdim
783296417SdimAttributeSet AttributeSet::addAttribute(LLVMContext &C,
784296417Sdim                                        ArrayRef<unsigned> Indices,
785296417Sdim                                        Attribute A) const {
786296417Sdim  unsigned I = 0, E = pImpl ? pImpl->getNumAttributes() : 0;
787296417Sdim  auto IdxI = Indices.begin(), IdxE = Indices.end();
788296417Sdim  SmallVector<AttributeSet, 4> AttrSet;
789296417Sdim
790296417Sdim  while (I != E && IdxI != IdxE) {
791296417Sdim    if (getSlotIndex(I) < *IdxI)
792296417Sdim      AttrSet.emplace_back(getSlotAttributes(I++));
793296417Sdim    else if (getSlotIndex(I) > *IdxI)
794296417Sdim      AttrSet.emplace_back(AttributeSet::get(C, std::make_pair(*IdxI++, A)));
795296417Sdim    else {
796296417Sdim      AttrBuilder B(getSlotAttributes(I), *IdxI);
797296417Sdim      B.addAttribute(A);
798296417Sdim      AttrSet.emplace_back(AttributeSet::get(C, *IdxI, B));
799296417Sdim      ++I;
800296417Sdim      ++IdxI;
801296417Sdim    }
802296417Sdim  }
803296417Sdim
804296417Sdim  while (I != E)
805296417Sdim    AttrSet.emplace_back(getSlotAttributes(I++));
806296417Sdim
807296417Sdim  while (IdxI != IdxE)
808296417Sdim    AttrSet.emplace_back(AttributeSet::get(C, std::make_pair(*IdxI++, A)));
809296417Sdim
810296417Sdim  return get(C, AttrSet);
811296417Sdim}
812296417Sdim
813251662SdimAttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index,
814249259Sdim                                         AttributeSet Attrs) const {
815249259Sdim  if (!pImpl) return Attrs;
816249259Sdim  if (!Attrs.pImpl) return *this;
817249259Sdim
818249259Sdim#ifndef NDEBUG
819249259Sdim  // FIXME it is not obvious how this should work for alignment. For now, say
820249259Sdim  // we can't change a known alignment.
821251662Sdim  unsigned OldAlign = getParamAlignment(Index);
822251662Sdim  unsigned NewAlign = Attrs.getParamAlignment(Index);
823249259Sdim  assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
824249259Sdim         "Attempt to change alignment!");
825249259Sdim#endif
826249259Sdim
827249259Sdim  // Add the attribute slots before the one we're trying to add.
828249259Sdim  SmallVector<AttributeSet, 4> AttrSet;
829249259Sdim  uint64_t NumAttrs = pImpl->getNumAttributes();
830249259Sdim  AttributeSet AS;
831249259Sdim  uint64_t LastIndex = 0;
832249259Sdim  for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
833251662Sdim    if (getSlotIndex(I) >= Index) {
834251662Sdim      if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++);
835249259Sdim      break;
836249259Sdim    }
837249259Sdim    LastIndex = I + 1;
838249259Sdim    AttrSet.push_back(getSlotAttributes(I));
839249259Sdim  }
840249259Sdim
841249259Sdim  // Now add the attribute into the correct slot. There may already be an
842249259Sdim  // AttributeSet there.
843251662Sdim  AttrBuilder B(AS, Index);
844249259Sdim
845249259Sdim  for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I)
846251662Sdim    if (Attrs.getSlotIndex(I) == Index) {
847261991Sdim      for (AttributeSetImpl::iterator II = Attrs.pImpl->begin(I),
848249259Sdim             IE = Attrs.pImpl->end(I); II != IE; ++II)
849249259Sdim        B.addAttribute(*II);
850249259Sdim      break;
851249259Sdim    }
852249259Sdim
853251662Sdim  AttrSet.push_back(AttributeSet::get(C, Index, B));
854249259Sdim
855249259Sdim  // Add the remaining attribute slots.
856249259Sdim  for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
857249259Sdim    AttrSet.push_back(getSlotAttributes(I));
858249259Sdim
859249259Sdim  return get(C, AttrSet);
860249259Sdim}
861249259Sdim
862251662SdimAttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Index,
863249259Sdim                                           Attribute::AttrKind Attr) const {
864251662Sdim  if (!hasAttribute(Index, Attr)) return *this;
865251662Sdim  return removeAttributes(C, Index, AttributeSet::get(C, Index, Attr));
866249259Sdim}
867249259Sdim
868251662SdimAttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
869249259Sdim                                            AttributeSet Attrs) const {
870249259Sdim  if (!pImpl) return AttributeSet();
871249259Sdim  if (!Attrs.pImpl) return *this;
872249259Sdim
873249259Sdim  // FIXME it is not obvious how this should work for alignment.
874249259Sdim  // For now, say we can't pass in alignment, which no current use does.
875251662Sdim  assert(!Attrs.hasAttribute(Index, Attribute::Alignment) &&
876249259Sdim         "Attempt to change alignment!");
877249259Sdim
878249259Sdim  // Add the attribute slots before the one we're trying to add.
879249259Sdim  SmallVector<AttributeSet, 4> AttrSet;
880249259Sdim  uint64_t NumAttrs = pImpl->getNumAttributes();
881249259Sdim  AttributeSet AS;
882249259Sdim  uint64_t LastIndex = 0;
883249259Sdim  for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
884251662Sdim    if (getSlotIndex(I) >= Index) {
885251662Sdim      if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++);
886249259Sdim      break;
887249259Sdim    }
888249259Sdim    LastIndex = I + 1;
889249259Sdim    AttrSet.push_back(getSlotAttributes(I));
890249259Sdim  }
891249259Sdim
892249259Sdim  // Now remove the attribute from the correct slot. There may already be an
893249259Sdim  // AttributeSet there.
894251662Sdim  AttrBuilder B(AS, Index);
895249259Sdim
896249259Sdim  for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I)
897251662Sdim    if (Attrs.getSlotIndex(I) == Index) {
898251662Sdim      B.removeAttributes(Attrs.pImpl->getSlotAttributes(I), Index);
899249259Sdim      break;
900249259Sdim    }
901249259Sdim
902251662Sdim  AttrSet.push_back(AttributeSet::get(C, Index, B));
903249259Sdim
904249259Sdim  // Add the remaining attribute slots.
905249259Sdim  for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
906249259Sdim    AttrSet.push_back(getSlotAttributes(I));
907249259Sdim
908249259Sdim  return get(C, AttrSet);
909249259Sdim}
910249259Sdim
911288943SdimAttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
912288943Sdim                                            const AttrBuilder &Attrs) const {
913288943Sdim  if (!pImpl) return AttributeSet();
914288943Sdim
915288943Sdim  // FIXME it is not obvious how this should work for alignment.
916288943Sdim  // For now, say we can't pass in alignment, which no current use does.
917288943Sdim  assert(!Attrs.hasAlignmentAttr() && "Attempt to change alignment!");
918288943Sdim
919288943Sdim  // Add the attribute slots before the one we're trying to add.
920288943Sdim  SmallVector<AttributeSet, 4> AttrSet;
921288943Sdim  uint64_t NumAttrs = pImpl->getNumAttributes();
922288943Sdim  AttributeSet AS;
923288943Sdim  uint64_t LastIndex = 0;
924288943Sdim  for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
925288943Sdim    if (getSlotIndex(I) >= Index) {
926288943Sdim      if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++);
927288943Sdim      break;
928288943Sdim    }
929288943Sdim    LastIndex = I + 1;
930288943Sdim    AttrSet.push_back(getSlotAttributes(I));
931288943Sdim  }
932288943Sdim
933288943Sdim  // Now remove the attribute from the correct slot. There may already be an
934288943Sdim  // AttributeSet there.
935288943Sdim  AttrBuilder B(AS, Index);
936288943Sdim  B.remove(Attrs);
937288943Sdim
938288943Sdim  AttrSet.push_back(AttributeSet::get(C, Index, B));
939288943Sdim
940288943Sdim  // Add the remaining attribute slots.
941288943Sdim  for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
942288943Sdim    AttrSet.push_back(getSlotAttributes(I));
943288943Sdim
944288943Sdim  return get(C, AttrSet);
945288943Sdim}
946288943Sdim
947288943SdimAttributeSet AttributeSet::addDereferenceableAttr(LLVMContext &C, unsigned Index,
948288943Sdim                                                  uint64_t Bytes) const {
949288943Sdim  llvm::AttrBuilder B;
950288943Sdim  B.addDereferenceableAttr(Bytes);
951288943Sdim  return addAttributes(C, Index, AttributeSet::get(C, Index, B));
952288943Sdim}
953288943Sdim
954288943SdimAttributeSet AttributeSet::addDereferenceableOrNullAttr(LLVMContext &C,
955288943Sdim                                                        unsigned Index,
956288943Sdim                                                        uint64_t Bytes) const {
957288943Sdim  llvm::AttrBuilder B;
958288943Sdim  B.addDereferenceableOrNullAttr(Bytes);
959288943Sdim  return addAttributes(C, Index, AttributeSet::get(C, Index, B));
960288943Sdim}
961288943Sdim
962249259Sdim//===----------------------------------------------------------------------===//
963249259Sdim// AttributeSet Accessor Methods
964249259Sdim//===----------------------------------------------------------------------===//
965249259Sdim
966249259SdimLLVMContext &AttributeSet::getContext() const {
967249259Sdim  return pImpl->getContext();
968249259Sdim}
969249259Sdim
970251662SdimAttributeSet AttributeSet::getParamAttributes(unsigned Index) const {
971251662Sdim  return pImpl && hasAttributes(Index) ?
972249259Sdim    AttributeSet::get(pImpl->getContext(),
973249259Sdim                      ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
974251662Sdim                        std::make_pair(Index, getAttributes(Index)))) :
975249259Sdim    AttributeSet();
976249259Sdim}
977249259Sdim
978249259SdimAttributeSet AttributeSet::getRetAttributes() const {
979249259Sdim  return pImpl && hasAttributes(ReturnIndex) ?
980249259Sdim    AttributeSet::get(pImpl->getContext(),
981249259Sdim                      ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
982249259Sdim                        std::make_pair(ReturnIndex,
983249259Sdim                                       getAttributes(ReturnIndex)))) :
984249259Sdim    AttributeSet();
985249259Sdim}
986249259Sdim
987249259SdimAttributeSet AttributeSet::getFnAttributes() const {
988249259Sdim  return pImpl && hasAttributes(FunctionIndex) ?
989249259Sdim    AttributeSet::get(pImpl->getContext(),
990249259Sdim                      ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
991249259Sdim                        std::make_pair(FunctionIndex,
992249259Sdim                                       getAttributes(FunctionIndex)))) :
993249259Sdim    AttributeSet();
994249259Sdim}
995249259Sdim
996249259Sdimbool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{
997249259Sdim  AttributeSetNode *ASN = getAttributes(Index);
998296417Sdim  return ASN && ASN->hasAttribute(Kind);
999249259Sdim}
1000249259Sdim
1001249259Sdimbool AttributeSet::hasAttribute(unsigned Index, StringRef Kind) const {
1002249259Sdim  AttributeSetNode *ASN = getAttributes(Index);
1003296417Sdim  return ASN && ASN->hasAttribute(Kind);
1004249259Sdim}
1005249259Sdim
1006249259Sdimbool AttributeSet::hasAttributes(unsigned Index) const {
1007249259Sdim  AttributeSetNode *ASN = getAttributes(Index);
1008296417Sdim  return ASN && ASN->hasAttributes();
1009249259Sdim}
1010249259Sdim
1011249259Sdim/// \brief Return true if the specified attribute is set for at least one
1012249259Sdim/// parameter or for the return value.
1013249259Sdimbool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const {
1014276479Sdim  if (!pImpl) return false;
1015249259Sdim
1016249259Sdim  for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I)
1017261991Sdim    for (AttributeSetImpl::iterator II = pImpl->begin(I),
1018249259Sdim           IE = pImpl->end(I); II != IE; ++II)
1019249259Sdim      if (II->hasAttribute(Attr))
1020249259Sdim        return true;
1021249259Sdim
1022249259Sdim  return false;
1023249259Sdim}
1024249259Sdim
1025249259SdimAttribute AttributeSet::getAttribute(unsigned Index,
1026249259Sdim                                     Attribute::AttrKind Kind) const {
1027249259Sdim  AttributeSetNode *ASN = getAttributes(Index);
1028249259Sdim  return ASN ? ASN->getAttribute(Kind) : Attribute();
1029249259Sdim}
1030249259Sdim
1031249259SdimAttribute AttributeSet::getAttribute(unsigned Index,
1032249259Sdim                                     StringRef Kind) const {
1033249259Sdim  AttributeSetNode *ASN = getAttributes(Index);
1034249259Sdim  return ASN ? ASN->getAttribute(Kind) : Attribute();
1035249259Sdim}
1036249259Sdim
1037249259Sdimunsigned AttributeSet::getParamAlignment(unsigned Index) const {
1038249259Sdim  AttributeSetNode *ASN = getAttributes(Index);
1039249259Sdim  return ASN ? ASN->getAlignment() : 0;
1040249259Sdim}
1041249259Sdim
1042249259Sdimunsigned AttributeSet::getStackAlignment(unsigned Index) const {
1043249259Sdim  AttributeSetNode *ASN = getAttributes(Index);
1044249259Sdim  return ASN ? ASN->getStackAlignment() : 0;
1045249259Sdim}
1046249259Sdim
1047276479Sdimuint64_t AttributeSet::getDereferenceableBytes(unsigned Index) const {
1048276479Sdim  AttributeSetNode *ASN = getAttributes(Index);
1049276479Sdim  return ASN ? ASN->getDereferenceableBytes() : 0;
1050276479Sdim}
1051276479Sdim
1052288943Sdimuint64_t AttributeSet::getDereferenceableOrNullBytes(unsigned Index) const {
1053288943Sdim  AttributeSetNode *ASN = getAttributes(Index);
1054288943Sdim  return ASN ? ASN->getDereferenceableOrNullBytes() : 0;
1055288943Sdim}
1056288943Sdim
1057249259Sdimstd::string AttributeSet::getAsString(unsigned Index,
1058249259Sdim                                      bool InAttrGrp) const {
1059249259Sdim  AttributeSetNode *ASN = getAttributes(Index);
1060249259Sdim  return ASN ? ASN->getAsString(InAttrGrp) : std::string("");
1061249259Sdim}
1062249259Sdim
1063249259Sdim/// \brief The attributes for the specified index are returned.
1064251662SdimAttributeSetNode *AttributeSet::getAttributes(unsigned Index) const {
1065276479Sdim  if (!pImpl) return nullptr;
1066249259Sdim
1067249259Sdim  // Loop through to find the attribute node we want.
1068249259Sdim  for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I)
1069251662Sdim    if (pImpl->getSlotIndex(I) == Index)
1070249259Sdim      return pImpl->getSlotNode(I);
1071249259Sdim
1072276479Sdim  return nullptr;
1073249259Sdim}
1074249259Sdim
1075251662SdimAttributeSet::iterator AttributeSet::begin(unsigned Slot) const {
1076249259Sdim  if (!pImpl)
1077249259Sdim    return ArrayRef<Attribute>().begin();
1078251662Sdim  return pImpl->begin(Slot);
1079249259Sdim}
1080249259Sdim
1081251662SdimAttributeSet::iterator AttributeSet::end(unsigned Slot) const {
1082249259Sdim  if (!pImpl)
1083249259Sdim    return ArrayRef<Attribute>().end();
1084251662Sdim  return pImpl->end(Slot);
1085249259Sdim}
1086249259Sdim
1087249259Sdim//===----------------------------------------------------------------------===//
1088249259Sdim// AttributeSet Introspection Methods
1089249259Sdim//===----------------------------------------------------------------------===//
1090249259Sdim
1091249259Sdim/// \brief Return the number of slots used in this attribute list.  This is the
1092249259Sdim/// number of arguments that have an attribute set on them (including the
1093249259Sdim/// function itself).
1094249259Sdimunsigned AttributeSet::getNumSlots() const {
1095249259Sdim  return pImpl ? pImpl->getNumAttributes() : 0;
1096249259Sdim}
1097249259Sdim
1098251662Sdimunsigned AttributeSet::getSlotIndex(unsigned Slot) const {
1099249259Sdim  assert(pImpl && Slot < pImpl->getNumAttributes() &&
1100249259Sdim         "Slot # out of range!");
1101249259Sdim  return pImpl->getSlotIndex(Slot);
1102249259Sdim}
1103249259Sdim
1104249259SdimAttributeSet AttributeSet::getSlotAttributes(unsigned Slot) const {
1105249259Sdim  assert(pImpl && Slot < pImpl->getNumAttributes() &&
1106249259Sdim         "Slot # out of range!");
1107249259Sdim  return pImpl->getSlotAttributes(Slot);
1108249259Sdim}
1109249259Sdim
1110249259Sdimuint64_t AttributeSet::Raw(unsigned Index) const {
1111249259Sdim  // FIXME: Remove this.
1112249259Sdim  return pImpl ? pImpl->Raw(Index) : 0;
1113249259Sdim}
1114249259Sdim
1115249259Sdimvoid AttributeSet::dump() const {
1116249259Sdim  dbgs() << "PAL[\n";
1117249259Sdim
1118249259Sdim  for (unsigned i = 0, e = getNumSlots(); i < e; ++i) {
1119249259Sdim    uint64_t Index = getSlotIndex(i);
1120249259Sdim    dbgs() << "  { ";
1121249259Sdim    if (Index == ~0U)
1122249259Sdim      dbgs() << "~0U";
1123249259Sdim    else
1124249259Sdim      dbgs() << Index;
1125249259Sdim    dbgs() << " => " << getAsString(Index) << " }\n";
1126249259Sdim  }
1127249259Sdim
1128249259Sdim  dbgs() << "]\n";
1129249259Sdim}
1130249259Sdim
1131249259Sdim//===----------------------------------------------------------------------===//
1132249259Sdim// AttrBuilder Method Implementations
1133249259Sdim//===----------------------------------------------------------------------===//
1134249259Sdim
1135251662SdimAttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)
1136288943Sdim    : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
1137288943Sdim      DerefOrNullBytes(0) {
1138249259Sdim  AttributeSetImpl *pImpl = AS.pImpl;
1139249259Sdim  if (!pImpl) return;
1140249259Sdim
1141249259Sdim  for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) {
1142251662Sdim    if (pImpl->getSlotIndex(I) != Index) continue;
1143249259Sdim
1144261991Sdim    for (AttributeSetImpl::iterator II = pImpl->begin(I),
1145249259Sdim           IE = pImpl->end(I); II != IE; ++II)
1146249259Sdim      addAttribute(*II);
1147249259Sdim
1148249259Sdim    break;
1149249259Sdim  }
1150249259Sdim}
1151249259Sdim
1152249259Sdimvoid AttrBuilder::clear() {
1153249259Sdim  Attrs.reset();
1154296417Sdim  TargetDepAttrs.clear();
1155288943Sdim  Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
1156249259Sdim}
1157249259Sdim
1158249259SdimAttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
1159249259Sdim  assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1160249259Sdim  assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment &&
1161276479Sdim         Val != Attribute::Dereferenceable &&
1162276479Sdim         "Adding integer attribute without adding a value!");
1163249259Sdim  Attrs[Val] = true;
1164249259Sdim  return *this;
1165249259Sdim}
1166249259Sdim
1167249259SdimAttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1168249259Sdim  if (Attr.isStringAttribute()) {
1169249259Sdim    addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
1170249259Sdim    return *this;
1171249259Sdim  }
1172249259Sdim
1173249259Sdim  Attribute::AttrKind Kind = Attr.getKindAsEnum();
1174249259Sdim  Attrs[Kind] = true;
1175249259Sdim
1176249259Sdim  if (Kind == Attribute::Alignment)
1177249259Sdim    Alignment = Attr.getAlignment();
1178249259Sdim  else if (Kind == Attribute::StackAlignment)
1179249259Sdim    StackAlignment = Attr.getStackAlignment();
1180276479Sdim  else if (Kind == Attribute::Dereferenceable)
1181276479Sdim    DerefBytes = Attr.getDereferenceableBytes();
1182288943Sdim  else if (Kind == Attribute::DereferenceableOrNull)
1183288943Sdim    DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
1184249259Sdim  return *this;
1185249259Sdim}
1186249259Sdim
1187249259SdimAttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1188249259Sdim  TargetDepAttrs[A] = V;
1189249259Sdim  return *this;
1190249259Sdim}
1191249259Sdim
1192249259SdimAttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1193249259Sdim  assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1194249259Sdim  Attrs[Val] = false;
1195249259Sdim
1196249259Sdim  if (Val == Attribute::Alignment)
1197249259Sdim    Alignment = 0;
1198249259Sdim  else if (Val == Attribute::StackAlignment)
1199249259Sdim    StackAlignment = 0;
1200276479Sdim  else if (Val == Attribute::Dereferenceable)
1201276479Sdim    DerefBytes = 0;
1202288943Sdim  else if (Val == Attribute::DereferenceableOrNull)
1203288943Sdim    DerefOrNullBytes = 0;
1204249259Sdim
1205249259Sdim  return *this;
1206249259Sdim}
1207249259Sdim
1208249259SdimAttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {
1209251662Sdim  unsigned Slot = ~0U;
1210249259Sdim  for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I)
1211249259Sdim    if (A.getSlotIndex(I) == Index) {
1212251662Sdim      Slot = I;
1213249259Sdim      break;
1214249259Sdim    }
1215249259Sdim
1216251662Sdim  assert(Slot != ~0U && "Couldn't find index in AttributeSet!");
1217249259Sdim
1218251662Sdim  for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) {
1219249259Sdim    Attribute Attr = *I;
1220276479Sdim    if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
1221296417Sdim      removeAttribute(Attr.getKindAsEnum());
1222249259Sdim    } else {
1223249259Sdim      assert(Attr.isStringAttribute() && "Invalid attribute type!");
1224296417Sdim      removeAttribute(Attr.getKindAsString());
1225249259Sdim    }
1226249259Sdim  }
1227249259Sdim
1228249259Sdim  return *this;
1229249259Sdim}
1230249259Sdim
1231249259SdimAttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1232249259Sdim  std::map<std::string, std::string>::iterator I = TargetDepAttrs.find(A);
1233249259Sdim  if (I != TargetDepAttrs.end())
1234249259Sdim    TargetDepAttrs.erase(I);
1235249259Sdim  return *this;
1236249259Sdim}
1237249259Sdim
1238249259SdimAttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
1239249259Sdim  if (Align == 0) return *this;
1240249259Sdim
1241249259Sdim  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
1242249259Sdim  assert(Align <= 0x40000000 && "Alignment too large.");
1243249259Sdim
1244249259Sdim  Attrs[Attribute::Alignment] = true;
1245249259Sdim  Alignment = Align;
1246249259Sdim  return *this;
1247249259Sdim}
1248249259Sdim
1249249259SdimAttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) {
1250249259Sdim  // Default alignment, allow the target to define how to align it.
1251249259Sdim  if (Align == 0) return *this;
1252249259Sdim
1253249259Sdim  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
1254249259Sdim  assert(Align <= 0x100 && "Alignment too large.");
1255249259Sdim
1256249259Sdim  Attrs[Attribute::StackAlignment] = true;
1257249259Sdim  StackAlignment = Align;
1258249259Sdim  return *this;
1259249259Sdim}
1260249259Sdim
1261276479SdimAttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1262276479Sdim  if (Bytes == 0) return *this;
1263276479Sdim
1264276479Sdim  Attrs[Attribute::Dereferenceable] = true;
1265276479Sdim  DerefBytes = Bytes;
1266276479Sdim  return *this;
1267276479Sdim}
1268276479Sdim
1269288943SdimAttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1270288943Sdim  if (Bytes == 0)
1271288943Sdim    return *this;
1272288943Sdim
1273288943Sdim  Attrs[Attribute::DereferenceableOrNull] = true;
1274288943Sdim  DerefOrNullBytes = Bytes;
1275288943Sdim  return *this;
1276288943Sdim}
1277288943Sdim
1278249259SdimAttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1279249259Sdim  // FIXME: What if both have alignments, but they don't match?!
1280249259Sdim  if (!Alignment)
1281249259Sdim    Alignment = B.Alignment;
1282249259Sdim
1283249259Sdim  if (!StackAlignment)
1284249259Sdim    StackAlignment = B.StackAlignment;
1285249259Sdim
1286276479Sdim  if (!DerefBytes)
1287276479Sdim    DerefBytes = B.DerefBytes;
1288276479Sdim
1289288943Sdim  if (!DerefOrNullBytes)
1290288943Sdim    DerefOrNullBytes = B.DerefOrNullBytes;
1291288943Sdim
1292249259Sdim  Attrs |= B.Attrs;
1293249259Sdim
1294288943Sdim  for (auto I : B.td_attrs())
1295288943Sdim    TargetDepAttrs[I.first] = I.second;
1296249259Sdim
1297249259Sdim  return *this;
1298249259Sdim}
1299249259Sdim
1300288943SdimAttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
1301288943Sdim  // FIXME: What if both have alignments, but they don't match?!
1302288943Sdim  if (B.Alignment)
1303288943Sdim    Alignment = 0;
1304288943Sdim
1305288943Sdim  if (B.StackAlignment)
1306288943Sdim    StackAlignment = 0;
1307288943Sdim
1308288943Sdim  if (B.DerefBytes)
1309288943Sdim    DerefBytes = 0;
1310288943Sdim
1311288943Sdim  if (B.DerefOrNullBytes)
1312288943Sdim    DerefOrNullBytes = 0;
1313288943Sdim
1314288943Sdim  Attrs &= ~B.Attrs;
1315288943Sdim
1316288943Sdim  for (auto I : B.td_attrs())
1317288943Sdim    TargetDepAttrs.erase(I.first);
1318288943Sdim
1319288943Sdim  return *this;
1320288943Sdim}
1321288943Sdim
1322288943Sdimbool AttrBuilder::overlaps(const AttrBuilder &B) const {
1323288943Sdim  // First check if any of the target independent attributes overlap.
1324288943Sdim  if ((Attrs & B.Attrs).any())
1325288943Sdim    return true;
1326288943Sdim
1327288943Sdim  // Then check if any target dependent ones do.
1328288943Sdim  for (auto I : td_attrs())
1329288943Sdim    if (B.contains(I.first))
1330288943Sdim      return true;
1331288943Sdim
1332288943Sdim  return false;
1333288943Sdim}
1334288943Sdim
1335249259Sdimbool AttrBuilder::contains(StringRef A) const {
1336249259Sdim  return TargetDepAttrs.find(A) != TargetDepAttrs.end();
1337249259Sdim}
1338249259Sdim
1339249259Sdimbool AttrBuilder::hasAttributes() const {
1340249259Sdim  return !Attrs.none() || !TargetDepAttrs.empty();
1341249259Sdim}
1342249259Sdim
1343249259Sdimbool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const {
1344251662Sdim  unsigned Slot = ~0U;
1345249259Sdim  for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I)
1346249259Sdim    if (A.getSlotIndex(I) == Index) {
1347251662Sdim      Slot = I;
1348249259Sdim      break;
1349249259Sdim    }
1350249259Sdim
1351251662Sdim  assert(Slot != ~0U && "Couldn't find the index!");
1352249259Sdim
1353296417Sdim  for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) {
1354249259Sdim    Attribute Attr = *I;
1355276479Sdim    if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
1356249259Sdim      if (Attrs[I->getKindAsEnum()])
1357249259Sdim        return true;
1358249259Sdim    } else {
1359249259Sdim      assert(Attr.isStringAttribute() && "Invalid attribute kind!");
1360249259Sdim      return TargetDepAttrs.find(Attr.getKindAsString())!=TargetDepAttrs.end();
1361249259Sdim    }
1362249259Sdim  }
1363249259Sdim
1364249259Sdim  return false;
1365249259Sdim}
1366249259Sdim
1367249259Sdimbool AttrBuilder::hasAlignmentAttr() const {
1368249259Sdim  return Alignment != 0;
1369249259Sdim}
1370249259Sdim
1371249259Sdimbool AttrBuilder::operator==(const AttrBuilder &B) {
1372249259Sdim  if (Attrs != B.Attrs)
1373249259Sdim    return false;
1374249259Sdim
1375249259Sdim  for (td_const_iterator I = TargetDepAttrs.begin(),
1376249259Sdim         E = TargetDepAttrs.end(); I != E; ++I)
1377249259Sdim    if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())
1378249259Sdim      return false;
1379249259Sdim
1380276479Sdim  return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
1381276479Sdim         DerefBytes == B.DerefBytes;
1382249259Sdim}
1383249259Sdim
1384249259SdimAttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
1385249259Sdim  // FIXME: Remove this in 4.0.
1386249259Sdim  if (!Val) return *this;
1387249259Sdim
1388249259Sdim  for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
1389249259Sdim       I = Attribute::AttrKind(I + 1)) {
1390288943Sdim    if (I == Attribute::Dereferenceable ||
1391288943Sdim        I == Attribute::DereferenceableOrNull ||
1392288943Sdim        I == Attribute::ArgMemOnly)
1393276479Sdim      continue;
1394249259Sdim    if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {
1395249259Sdim      Attrs[I] = true;
1396249259Sdim
1397249259Sdim      if (I == Attribute::Alignment)
1398249259Sdim        Alignment = 1ULL << ((A >> 16) - 1);
1399249259Sdim      else if (I == Attribute::StackAlignment)
1400249259Sdim        StackAlignment = 1ULL << ((A >> 26)-1);
1401249259Sdim    }
1402249259Sdim  }
1403249259Sdim
1404249259Sdim  return *this;
1405249259Sdim}
1406249259Sdim
1407249259Sdim//===----------------------------------------------------------------------===//
1408249259Sdim// AttributeFuncs Function Defintions
1409249259Sdim//===----------------------------------------------------------------------===//
1410249259Sdim
1411249259Sdim/// \brief Which attributes cannot be applied to a type.
1412296417SdimAttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
1413249259Sdim  AttrBuilder Incompatible;
1414249259Sdim
1415249259Sdim  if (!Ty->isIntegerTy())
1416249259Sdim    // Attribute that only apply to integers.
1417249259Sdim    Incompatible.addAttribute(Attribute::SExt)
1418249259Sdim      .addAttribute(Attribute::ZExt);
1419249259Sdim
1420249259Sdim  if (!Ty->isPointerTy())
1421249259Sdim    // Attribute that only apply to pointers.
1422249259Sdim    Incompatible.addAttribute(Attribute::ByVal)
1423249259Sdim      .addAttribute(Attribute::Nest)
1424249259Sdim      .addAttribute(Attribute::NoAlias)
1425249259Sdim      .addAttribute(Attribute::NoCapture)
1426276479Sdim      .addAttribute(Attribute::NonNull)
1427276479Sdim      .addDereferenceableAttr(1) // the int here is ignored
1428288943Sdim      .addDereferenceableOrNullAttr(1) // the int here is ignored
1429261991Sdim      .addAttribute(Attribute::ReadNone)
1430261991Sdim      .addAttribute(Attribute::ReadOnly)
1431276479Sdim      .addAttribute(Attribute::StructRet)
1432276479Sdim      .addAttribute(Attribute::InAlloca);
1433249259Sdim
1434288943Sdim  return Incompatible;
1435249259Sdim}
1436296417Sdim
1437296417Sdimtemplate<typename AttrClass>
1438296417Sdimstatic bool isEqual(const Function &Caller, const Function &Callee) {
1439296417Sdim  return Caller.getFnAttribute(AttrClass::getKind()) ==
1440296417Sdim         Callee.getFnAttribute(AttrClass::getKind());
1441296417Sdim}
1442296417Sdim
1443296417Sdim/// \brief Compute the logical AND of the attributes of the caller and the
1444296417Sdim/// callee.
1445296417Sdim///
1446296417Sdim/// This function sets the caller's attribute to false if the callee's attribute
1447296417Sdim/// is false.
1448296417Sdimtemplate<typename AttrClass>
1449296417Sdimstatic void setAND(Function &Caller, const Function &Callee) {
1450296417Sdim  if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
1451296417Sdim      !AttrClass::isSet(Callee, AttrClass::getKind()))
1452296417Sdim    AttrClass::set(Caller, AttrClass::getKind(), false);
1453296417Sdim}
1454296417Sdim
1455296417Sdim/// \brief Compute the logical OR of the attributes of the caller and the
1456296417Sdim/// callee.
1457296417Sdim///
1458296417Sdim/// This function sets the caller's attribute to true if the callee's attribute
1459296417Sdim/// is true.
1460296417Sdimtemplate<typename AttrClass>
1461296417Sdimstatic void setOR(Function &Caller, const Function &Callee) {
1462296417Sdim  if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
1463296417Sdim      AttrClass::isSet(Callee, AttrClass::getKind()))
1464296417Sdim    AttrClass::set(Caller, AttrClass::getKind(), true);
1465296417Sdim}
1466296417Sdim
1467296417Sdim/// \brief If the inlined function had a higher stack protection level than the
1468296417Sdim/// calling function, then bump up the caller's stack protection level.
1469296417Sdimstatic void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1470296417Sdim  // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1471296417Sdim  // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1472296417Sdim  // clutter to the IR.
1473296417Sdim  AttrBuilder B;
1474296417Sdim  B.addAttribute(Attribute::StackProtect)
1475296417Sdim    .addAttribute(Attribute::StackProtectStrong)
1476296417Sdim    .addAttribute(Attribute::StackProtectReq);
1477296417Sdim  AttributeSet OldSSPAttr = AttributeSet::get(Caller.getContext(),
1478296417Sdim                                              AttributeSet::FunctionIndex,
1479296417Sdim                                              B);
1480296417Sdim
1481296417Sdim  if (Callee.hasFnAttribute(Attribute::SafeStack)) {
1482296417Sdim    Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
1483296417Sdim    Caller.addFnAttr(Attribute::SafeStack);
1484296417Sdim  } else if (Callee.hasFnAttribute(Attribute::StackProtectReq) &&
1485296417Sdim             !Caller.hasFnAttribute(Attribute::SafeStack)) {
1486296417Sdim    Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
1487296417Sdim    Caller.addFnAttr(Attribute::StackProtectReq);
1488296417Sdim  } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
1489296417Sdim             !Caller.hasFnAttribute(Attribute::SafeStack) &&
1490296417Sdim             !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1491296417Sdim    Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
1492296417Sdim    Caller.addFnAttr(Attribute::StackProtectStrong);
1493296417Sdim  } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
1494296417Sdim             !Caller.hasFnAttribute(Attribute::SafeStack) &&
1495296417Sdim             !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
1496296417Sdim             !Caller.hasFnAttribute(Attribute::StackProtectStrong))
1497296417Sdim    Caller.addFnAttr(Attribute::StackProtect);
1498296417Sdim}
1499296417Sdim
1500296417Sdim#define GET_ATTR_COMPAT_FUNC
1501296417Sdim#include "AttributesCompatFunc.inc"
1502296417Sdim
1503296417Sdimbool AttributeFuncs::areInlineCompatible(const Function &Caller,
1504296417Sdim                                         const Function &Callee) {
1505296417Sdim  return hasCompatibleFnAttrs(Caller, Callee);
1506296417Sdim}
1507296417Sdim
1508296417Sdim
1509296417Sdimvoid AttributeFuncs::mergeAttributesForInlining(Function &Caller,
1510296417Sdim                                                const Function &Callee) {
1511296417Sdim  mergeFnAttrs(Caller, Callee);
1512296417Sdim}
1513