xref: /aosp_15_r20/external/llvm/lib/IR/Attributes.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- Attributes.cpp - Implement AttributesList -------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // \file
11*9880d681SAndroid Build Coastguard Worker // \brief This file implements the Attribute, AttributeImpl, AttrBuilder,
12*9880d681SAndroid Build Coastguard Worker // AttributeSetImpl, and AttributeSet classes.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker 
16*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Attributes.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
18*9880d681SAndroid Build Coastguard Worker #include "AttributeImpl.h"
19*9880d681SAndroid Build Coastguard Worker #include "LLVMContextImpl.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Type.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Atomic.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Mutex.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
28*9880d681SAndroid Build Coastguard Worker #include <algorithm>
29*9880d681SAndroid Build Coastguard Worker using namespace llvm;
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
32*9880d681SAndroid Build Coastguard Worker // Attribute Construction Methods
33*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker // allocsize has two integer arguments, but because they're both 32 bits, we can
36*9880d681SAndroid Build Coastguard Worker // pack them into one 64-bit value, at the cost of making said value
37*9880d681SAndroid Build Coastguard Worker // nonsensical.
38*9880d681SAndroid Build Coastguard Worker //
39*9880d681SAndroid Build Coastguard Worker // In order to do this, we need to reserve one value of the second (optional)
40*9880d681SAndroid Build Coastguard Worker // allocsize argument to signify "not present."
41*9880d681SAndroid Build Coastguard Worker LLVM_CONSTEXPR static unsigned AllocSizeNumElemsNotPresent = -1;
42*9880d681SAndroid Build Coastguard Worker 
packAllocSizeArgs(unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)43*9880d681SAndroid Build Coastguard Worker static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
44*9880d681SAndroid Build Coastguard Worker                                   const Optional<unsigned> &NumElemsArg) {
45*9880d681SAndroid Build Coastguard Worker   assert((!NumElemsArg.hasValue() ||
46*9880d681SAndroid Build Coastguard Worker           *NumElemsArg != AllocSizeNumElemsNotPresent) &&
47*9880d681SAndroid Build Coastguard Worker          "Attempting to pack a reserved value");
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker   return uint64_t(ElemSizeArg) << 32 |
50*9880d681SAndroid Build Coastguard Worker          NumElemsArg.getValueOr(AllocSizeNumElemsNotPresent);
51*9880d681SAndroid Build Coastguard Worker }
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker static std::pair<unsigned, Optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)54*9880d681SAndroid Build Coastguard Worker unpackAllocSizeArgs(uint64_t Num) {
55*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
56*9880d681SAndroid Build Coastguard Worker   unsigned ElemSizeArg = Num >> 32;
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker   Optional<unsigned> NumElemsArg;
59*9880d681SAndroid Build Coastguard Worker   if (NumElems != AllocSizeNumElemsNotPresent)
60*9880d681SAndroid Build Coastguard Worker     NumElemsArg = NumElems;
61*9880d681SAndroid Build Coastguard Worker   return std::make_pair(ElemSizeArg, NumElemsArg);
62*9880d681SAndroid Build Coastguard Worker }
63*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)64*9880d681SAndroid Build Coastguard Worker Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
65*9880d681SAndroid Build Coastguard Worker                          uint64_t Val) {
66*9880d681SAndroid Build Coastguard Worker   LLVMContextImpl *pImpl = Context.pImpl;
67*9880d681SAndroid Build Coastguard Worker   FoldingSetNodeID ID;
68*9880d681SAndroid Build Coastguard Worker   ID.AddInteger(Kind);
69*9880d681SAndroid Build Coastguard Worker   if (Val) ID.AddInteger(Val);
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker   void *InsertPoint;
72*9880d681SAndroid Build Coastguard Worker   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker   if (!PA) {
75*9880d681SAndroid Build Coastguard Worker     // If we didn't find any existing attributes of the same shape then create a
76*9880d681SAndroid Build Coastguard Worker     // new one and insert it.
77*9880d681SAndroid Build Coastguard Worker     if (!Val)
78*9880d681SAndroid Build Coastguard Worker       PA = new EnumAttributeImpl(Kind);
79*9880d681SAndroid Build Coastguard Worker     else
80*9880d681SAndroid Build Coastguard Worker       PA = new IntAttributeImpl(Kind, Val);
81*9880d681SAndroid Build Coastguard Worker     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
82*9880d681SAndroid Build Coastguard Worker   }
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker   // Return the Attribute that we found or created.
85*9880d681SAndroid Build Coastguard Worker   return Attribute(PA);
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & Context,StringRef Kind,StringRef Val)88*9880d681SAndroid Build Coastguard Worker Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
89*9880d681SAndroid Build Coastguard Worker   LLVMContextImpl *pImpl = Context.pImpl;
90*9880d681SAndroid Build Coastguard Worker   FoldingSetNodeID ID;
91*9880d681SAndroid Build Coastguard Worker   ID.AddString(Kind);
92*9880d681SAndroid Build Coastguard Worker   if (!Val.empty()) ID.AddString(Val);
93*9880d681SAndroid Build Coastguard Worker 
94*9880d681SAndroid Build Coastguard Worker   void *InsertPoint;
95*9880d681SAndroid Build Coastguard Worker   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker   if (!PA) {
98*9880d681SAndroid Build Coastguard Worker     // If we didn't find any existing attributes of the same shape then create a
99*9880d681SAndroid Build Coastguard Worker     // new one and insert it.
100*9880d681SAndroid Build Coastguard Worker     PA = new StringAttributeImpl(Kind, Val);
101*9880d681SAndroid Build Coastguard Worker     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
102*9880d681SAndroid Build Coastguard Worker   }
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker   // Return the Attribute that we found or created.
105*9880d681SAndroid Build Coastguard Worker   return Attribute(PA);
106*9880d681SAndroid Build Coastguard Worker }
107*9880d681SAndroid Build Coastguard Worker 
getWithAlignment(LLVMContext & Context,uint64_t Align)108*9880d681SAndroid Build Coastguard Worker Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) {
109*9880d681SAndroid Build Coastguard Worker   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
110*9880d681SAndroid Build Coastguard Worker   assert(Align <= 0x40000000 && "Alignment too large.");
111*9880d681SAndroid Build Coastguard Worker   return get(Context, Alignment, Align);
112*9880d681SAndroid Build Coastguard Worker }
113*9880d681SAndroid Build Coastguard Worker 
getWithStackAlignment(LLVMContext & Context,uint64_t Align)114*9880d681SAndroid Build Coastguard Worker Attribute Attribute::getWithStackAlignment(LLVMContext &Context,
115*9880d681SAndroid Build Coastguard Worker                                            uint64_t Align) {
116*9880d681SAndroid Build Coastguard Worker   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
117*9880d681SAndroid Build Coastguard Worker   assert(Align <= 0x100 && "Alignment too large.");
118*9880d681SAndroid Build Coastguard Worker   return get(Context, StackAlignment, Align);
119*9880d681SAndroid Build Coastguard Worker }
120*9880d681SAndroid Build Coastguard Worker 
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)121*9880d681SAndroid Build Coastguard Worker Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
122*9880d681SAndroid Build Coastguard Worker                                                 uint64_t Bytes) {
123*9880d681SAndroid Build Coastguard Worker   assert(Bytes && "Bytes must be non-zero.");
124*9880d681SAndroid Build Coastguard Worker   return get(Context, Dereferenceable, Bytes);
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker 
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)127*9880d681SAndroid Build Coastguard Worker Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
128*9880d681SAndroid Build Coastguard Worker                                                        uint64_t Bytes) {
129*9880d681SAndroid Build Coastguard Worker   assert(Bytes && "Bytes must be non-zero.");
130*9880d681SAndroid Build Coastguard Worker   return get(Context, DereferenceableOrNull, Bytes);
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker 
133*9880d681SAndroid Build Coastguard Worker Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)134*9880d681SAndroid Build Coastguard Worker Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
135*9880d681SAndroid Build Coastguard Worker                                 const Optional<unsigned> &NumElemsArg) {
136*9880d681SAndroid Build Coastguard Worker   assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
137*9880d681SAndroid Build Coastguard Worker          "Invalid allocsize arguments -- given allocsize(0, 0)");
138*9880d681SAndroid Build Coastguard Worker   return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker 
141*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
142*9880d681SAndroid Build Coastguard Worker // Attribute Accessor Methods
143*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
144*9880d681SAndroid Build Coastguard Worker 
isEnumAttribute() const145*9880d681SAndroid Build Coastguard Worker bool Attribute::isEnumAttribute() const {
146*9880d681SAndroid Build Coastguard Worker   return pImpl && pImpl->isEnumAttribute();
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker 
isIntAttribute() const149*9880d681SAndroid Build Coastguard Worker bool Attribute::isIntAttribute() const {
150*9880d681SAndroid Build Coastguard Worker   return pImpl && pImpl->isIntAttribute();
151*9880d681SAndroid Build Coastguard Worker }
152*9880d681SAndroid Build Coastguard Worker 
isStringAttribute() const153*9880d681SAndroid Build Coastguard Worker bool Attribute::isStringAttribute() const {
154*9880d681SAndroid Build Coastguard Worker   return pImpl && pImpl->isStringAttribute();
155*9880d681SAndroid Build Coastguard Worker }
156*9880d681SAndroid Build Coastguard Worker 
getKindAsEnum() const157*9880d681SAndroid Build Coastguard Worker Attribute::AttrKind Attribute::getKindAsEnum() const {
158*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return None;
159*9880d681SAndroid Build Coastguard Worker   assert((isEnumAttribute() || isIntAttribute()) &&
160*9880d681SAndroid Build Coastguard Worker          "Invalid attribute type to get the kind as an enum!");
161*9880d681SAndroid Build Coastguard Worker   return pImpl->getKindAsEnum();
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker 
getValueAsInt() const164*9880d681SAndroid Build Coastguard Worker uint64_t Attribute::getValueAsInt() const {
165*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return 0;
166*9880d681SAndroid Build Coastguard Worker   assert(isIntAttribute() &&
167*9880d681SAndroid Build Coastguard Worker          "Expected the attribute to be an integer attribute!");
168*9880d681SAndroid Build Coastguard Worker   return pImpl->getValueAsInt();
169*9880d681SAndroid Build Coastguard Worker }
170*9880d681SAndroid Build Coastguard Worker 
getKindAsString() const171*9880d681SAndroid Build Coastguard Worker StringRef Attribute::getKindAsString() const {
172*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return StringRef();
173*9880d681SAndroid Build Coastguard Worker   assert(isStringAttribute() &&
174*9880d681SAndroid Build Coastguard Worker          "Invalid attribute type to get the kind as a string!");
175*9880d681SAndroid Build Coastguard Worker   return pImpl->getKindAsString();
176*9880d681SAndroid Build Coastguard Worker }
177*9880d681SAndroid Build Coastguard Worker 
getValueAsString() const178*9880d681SAndroid Build Coastguard Worker StringRef Attribute::getValueAsString() const {
179*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return StringRef();
180*9880d681SAndroid Build Coastguard Worker   assert(isStringAttribute() &&
181*9880d681SAndroid Build Coastguard Worker          "Invalid attribute type to get the value as a string!");
182*9880d681SAndroid Build Coastguard Worker   return pImpl->getValueAsString();
183*9880d681SAndroid Build Coastguard Worker }
184*9880d681SAndroid Build Coastguard Worker 
hasAttribute(AttrKind Kind) const185*9880d681SAndroid Build Coastguard Worker bool Attribute::hasAttribute(AttrKind Kind) const {
186*9880d681SAndroid Build Coastguard Worker   return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
187*9880d681SAndroid Build Coastguard Worker }
188*9880d681SAndroid Build Coastguard Worker 
hasAttribute(StringRef Kind) const189*9880d681SAndroid Build Coastguard Worker bool Attribute::hasAttribute(StringRef Kind) const {
190*9880d681SAndroid Build Coastguard Worker   if (!isStringAttribute()) return false;
191*9880d681SAndroid Build Coastguard Worker   return pImpl && pImpl->hasAttribute(Kind);
192*9880d681SAndroid Build Coastguard Worker }
193*9880d681SAndroid Build Coastguard Worker 
getAlignment() const194*9880d681SAndroid Build Coastguard Worker unsigned Attribute::getAlignment() const {
195*9880d681SAndroid Build Coastguard Worker   assert(hasAttribute(Attribute::Alignment) &&
196*9880d681SAndroid Build Coastguard Worker          "Trying to get alignment from non-alignment attribute!");
197*9880d681SAndroid Build Coastguard Worker   return pImpl->getValueAsInt();
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker 
getStackAlignment() const200*9880d681SAndroid Build Coastguard Worker unsigned Attribute::getStackAlignment() const {
201*9880d681SAndroid Build Coastguard Worker   assert(hasAttribute(Attribute::StackAlignment) &&
202*9880d681SAndroid Build Coastguard Worker          "Trying to get alignment from non-alignment attribute!");
203*9880d681SAndroid Build Coastguard Worker   return pImpl->getValueAsInt();
204*9880d681SAndroid Build Coastguard Worker }
205*9880d681SAndroid Build Coastguard Worker 
getDereferenceableBytes() const206*9880d681SAndroid Build Coastguard Worker uint64_t Attribute::getDereferenceableBytes() const {
207*9880d681SAndroid Build Coastguard Worker   assert(hasAttribute(Attribute::Dereferenceable) &&
208*9880d681SAndroid Build Coastguard Worker          "Trying to get dereferenceable bytes from "
209*9880d681SAndroid Build Coastguard Worker          "non-dereferenceable attribute!");
210*9880d681SAndroid Build Coastguard Worker   return pImpl->getValueAsInt();
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker 
getDereferenceableOrNullBytes() const213*9880d681SAndroid Build Coastguard Worker uint64_t Attribute::getDereferenceableOrNullBytes() const {
214*9880d681SAndroid Build Coastguard Worker   assert(hasAttribute(Attribute::DereferenceableOrNull) &&
215*9880d681SAndroid Build Coastguard Worker          "Trying to get dereferenceable bytes from "
216*9880d681SAndroid Build Coastguard Worker          "non-dereferenceable attribute!");
217*9880d681SAndroid Build Coastguard Worker   return pImpl->getValueAsInt();
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker 
getAllocSizeArgs() const220*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
221*9880d681SAndroid Build Coastguard Worker   assert(hasAttribute(Attribute::AllocSize) &&
222*9880d681SAndroid Build Coastguard Worker          "Trying to get allocsize args from non-allocsize attribute");
223*9880d681SAndroid Build Coastguard Worker   return unpackAllocSizeArgs(pImpl->getValueAsInt());
224*9880d681SAndroid Build Coastguard Worker }
225*9880d681SAndroid Build Coastguard Worker 
getAsString(bool InAttrGrp) const226*9880d681SAndroid Build Coastguard Worker std::string Attribute::getAsString(bool InAttrGrp) const {
227*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return "";
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::SanitizeAddress))
230*9880d681SAndroid Build Coastguard Worker     return "sanitize_address";
231*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::AlwaysInline))
232*9880d681SAndroid Build Coastguard Worker     return "alwaysinline";
233*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::ArgMemOnly))
234*9880d681SAndroid Build Coastguard Worker     return "argmemonly";
235*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::Builtin))
236*9880d681SAndroid Build Coastguard Worker     return "builtin";
237*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::ByVal))
238*9880d681SAndroid Build Coastguard Worker     return "byval";
239*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::Convergent))
240*9880d681SAndroid Build Coastguard Worker     return "convergent";
241*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::SwiftError))
242*9880d681SAndroid Build Coastguard Worker     return "swifterror";
243*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::SwiftSelf))
244*9880d681SAndroid Build Coastguard Worker     return "swiftself";
245*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::InaccessibleMemOnly))
246*9880d681SAndroid Build Coastguard Worker     return "inaccessiblememonly";
247*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
248*9880d681SAndroid Build Coastguard Worker     return "inaccessiblemem_or_argmemonly";
249*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::InAlloca))
250*9880d681SAndroid Build Coastguard Worker     return "inalloca";
251*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::InlineHint))
252*9880d681SAndroid Build Coastguard Worker     return "inlinehint";
253*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::InReg))
254*9880d681SAndroid Build Coastguard Worker     return "inreg";
255*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::JumpTable))
256*9880d681SAndroid Build Coastguard Worker     return "jumptable";
257*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::MinSize))
258*9880d681SAndroid Build Coastguard Worker     return "minsize";
259*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::Naked))
260*9880d681SAndroid Build Coastguard Worker     return "naked";
261*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::Nest))
262*9880d681SAndroid Build Coastguard Worker     return "nest";
263*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoAlias))
264*9880d681SAndroid Build Coastguard Worker     return "noalias";
265*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoBuiltin))
266*9880d681SAndroid Build Coastguard Worker     return "nobuiltin";
267*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoCapture))
268*9880d681SAndroid Build Coastguard Worker     return "nocapture";
269*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoDuplicate))
270*9880d681SAndroid Build Coastguard Worker     return "noduplicate";
271*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoImplicitFloat))
272*9880d681SAndroid Build Coastguard Worker     return "noimplicitfloat";
273*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoInline))
274*9880d681SAndroid Build Coastguard Worker     return "noinline";
275*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NonLazyBind))
276*9880d681SAndroid Build Coastguard Worker     return "nonlazybind";
277*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NonNull))
278*9880d681SAndroid Build Coastguard Worker     return "nonnull";
279*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoRedZone))
280*9880d681SAndroid Build Coastguard Worker     return "noredzone";
281*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoReturn))
282*9880d681SAndroid Build Coastguard Worker     return "noreturn";
283*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoRecurse))
284*9880d681SAndroid Build Coastguard Worker     return "norecurse";
285*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::NoUnwind))
286*9880d681SAndroid Build Coastguard Worker     return "nounwind";
287*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::OptimizeNone))
288*9880d681SAndroid Build Coastguard Worker     return "optnone";
289*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::OptimizeForSize))
290*9880d681SAndroid Build Coastguard Worker     return "optsize";
291*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::ReadNone))
292*9880d681SAndroid Build Coastguard Worker     return "readnone";
293*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::ReadOnly))
294*9880d681SAndroid Build Coastguard Worker     return "readonly";
295*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::WriteOnly))
296*9880d681SAndroid Build Coastguard Worker     return "writeonly";
297*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::Returned))
298*9880d681SAndroid Build Coastguard Worker     return "returned";
299*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::ReturnsTwice))
300*9880d681SAndroid Build Coastguard Worker     return "returns_twice";
301*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::SExt))
302*9880d681SAndroid Build Coastguard Worker     return "signext";
303*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::StackProtect))
304*9880d681SAndroid Build Coastguard Worker     return "ssp";
305*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::StackProtectReq))
306*9880d681SAndroid Build Coastguard Worker     return "sspreq";
307*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::StackProtectStrong))
308*9880d681SAndroid Build Coastguard Worker     return "sspstrong";
309*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::SafeStack))
310*9880d681SAndroid Build Coastguard Worker     return "safestack";
311*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::StructRet))
312*9880d681SAndroid Build Coastguard Worker     return "sret";
313*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::SanitizeThread))
314*9880d681SAndroid Build Coastguard Worker     return "sanitize_thread";
315*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::SanitizeMemory))
316*9880d681SAndroid Build Coastguard Worker     return "sanitize_memory";
317*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::UWTable))
318*9880d681SAndroid Build Coastguard Worker     return "uwtable";
319*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::ZExt))
320*9880d681SAndroid Build Coastguard Worker     return "zeroext";
321*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::Cold))
322*9880d681SAndroid Build Coastguard Worker     return "cold";
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker   // FIXME: These should be output like this:
325*9880d681SAndroid Build Coastguard Worker   //
326*9880d681SAndroid Build Coastguard Worker   //   align=4
327*9880d681SAndroid Build Coastguard Worker   //   alignstack=8
328*9880d681SAndroid Build Coastguard Worker   //
329*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::Alignment)) {
330*9880d681SAndroid Build Coastguard Worker     std::string Result;
331*9880d681SAndroid Build Coastguard Worker     Result += "align";
332*9880d681SAndroid Build Coastguard Worker     Result += (InAttrGrp) ? "=" : " ";
333*9880d681SAndroid Build Coastguard Worker     Result += utostr(getValueAsInt());
334*9880d681SAndroid Build Coastguard Worker     return Result;
335*9880d681SAndroid Build Coastguard Worker   }
336*9880d681SAndroid Build Coastguard Worker 
337*9880d681SAndroid Build Coastguard Worker   auto AttrWithBytesToString = [&](const char *Name) {
338*9880d681SAndroid Build Coastguard Worker     std::string Result;
339*9880d681SAndroid Build Coastguard Worker     Result += Name;
340*9880d681SAndroid Build Coastguard Worker     if (InAttrGrp) {
341*9880d681SAndroid Build Coastguard Worker       Result += "=";
342*9880d681SAndroid Build Coastguard Worker       Result += utostr(getValueAsInt());
343*9880d681SAndroid Build Coastguard Worker     } else {
344*9880d681SAndroid Build Coastguard Worker       Result += "(";
345*9880d681SAndroid Build Coastguard Worker       Result += utostr(getValueAsInt());
346*9880d681SAndroid Build Coastguard Worker       Result += ")";
347*9880d681SAndroid Build Coastguard Worker     }
348*9880d681SAndroid Build Coastguard Worker     return Result;
349*9880d681SAndroid Build Coastguard Worker   };
350*9880d681SAndroid Build Coastguard Worker 
351*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::StackAlignment))
352*9880d681SAndroid Build Coastguard Worker     return AttrWithBytesToString("alignstack");
353*9880d681SAndroid Build Coastguard Worker 
354*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::Dereferenceable))
355*9880d681SAndroid Build Coastguard Worker     return AttrWithBytesToString("dereferenceable");
356*9880d681SAndroid Build Coastguard Worker 
357*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::DereferenceableOrNull))
358*9880d681SAndroid Build Coastguard Worker     return AttrWithBytesToString("dereferenceable_or_null");
359*9880d681SAndroid Build Coastguard Worker 
360*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Attribute::AllocSize)) {
361*9880d681SAndroid Build Coastguard Worker     unsigned ElemSize;
362*9880d681SAndroid Build Coastguard Worker     Optional<unsigned> NumElems;
363*9880d681SAndroid Build Coastguard Worker     std::tie(ElemSize, NumElems) = getAllocSizeArgs();
364*9880d681SAndroid Build Coastguard Worker 
365*9880d681SAndroid Build Coastguard Worker     std::string Result = "allocsize(";
366*9880d681SAndroid Build Coastguard Worker     Result += utostr(ElemSize);
367*9880d681SAndroid Build Coastguard Worker     if (NumElems.hasValue()) {
368*9880d681SAndroid Build Coastguard Worker       Result += ',';
369*9880d681SAndroid Build Coastguard Worker       Result += utostr(*NumElems);
370*9880d681SAndroid Build Coastguard Worker     }
371*9880d681SAndroid Build Coastguard Worker     Result += ')';
372*9880d681SAndroid Build Coastguard Worker     return Result;
373*9880d681SAndroid Build Coastguard Worker   }
374*9880d681SAndroid Build Coastguard Worker 
375*9880d681SAndroid Build Coastguard Worker   // Convert target-dependent attributes to strings of the form:
376*9880d681SAndroid Build Coastguard Worker   //
377*9880d681SAndroid Build Coastguard Worker   //   "kind"
378*9880d681SAndroid Build Coastguard Worker   //   "kind" = "value"
379*9880d681SAndroid Build Coastguard Worker   //
380*9880d681SAndroid Build Coastguard Worker   if (isStringAttribute()) {
381*9880d681SAndroid Build Coastguard Worker     std::string Result;
382*9880d681SAndroid Build Coastguard Worker     Result += (Twine('"') + getKindAsString() + Twine('"')).str();
383*9880d681SAndroid Build Coastguard Worker 
384*9880d681SAndroid Build Coastguard Worker     StringRef Val = pImpl->getValueAsString();
385*9880d681SAndroid Build Coastguard Worker     if (Val.empty()) return Result;
386*9880d681SAndroid Build Coastguard Worker 
387*9880d681SAndroid Build Coastguard Worker     Result += ("=\"" + Val + Twine('"')).str();
388*9880d681SAndroid Build Coastguard Worker     return Result;
389*9880d681SAndroid Build Coastguard Worker   }
390*9880d681SAndroid Build Coastguard Worker 
391*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unknown attribute");
392*9880d681SAndroid Build Coastguard Worker }
393*9880d681SAndroid Build Coastguard Worker 
operator <(Attribute A) const394*9880d681SAndroid Build Coastguard Worker bool Attribute::operator<(Attribute A) const {
395*9880d681SAndroid Build Coastguard Worker   if (!pImpl && !A.pImpl) return false;
396*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return true;
397*9880d681SAndroid Build Coastguard Worker   if (!A.pImpl) return false;
398*9880d681SAndroid Build Coastguard Worker   return *pImpl < *A.pImpl;
399*9880d681SAndroid Build Coastguard Worker }
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
402*9880d681SAndroid Build Coastguard Worker // AttributeImpl Definition
403*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
404*9880d681SAndroid Build Coastguard Worker 
405*9880d681SAndroid Build Coastguard Worker // Pin the vtables to this file.
~AttributeImpl()406*9880d681SAndroid Build Coastguard Worker AttributeImpl::~AttributeImpl() {}
anchor()407*9880d681SAndroid Build Coastguard Worker void EnumAttributeImpl::anchor() {}
anchor()408*9880d681SAndroid Build Coastguard Worker void IntAttributeImpl::anchor() {}
anchor()409*9880d681SAndroid Build Coastguard Worker void StringAttributeImpl::anchor() {}
410*9880d681SAndroid Build Coastguard Worker 
hasAttribute(Attribute::AttrKind A) const411*9880d681SAndroid Build Coastguard Worker bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
412*9880d681SAndroid Build Coastguard Worker   if (isStringAttribute()) return false;
413*9880d681SAndroid Build Coastguard Worker   return getKindAsEnum() == A;
414*9880d681SAndroid Build Coastguard Worker }
415*9880d681SAndroid Build Coastguard Worker 
hasAttribute(StringRef Kind) const416*9880d681SAndroid Build Coastguard Worker bool AttributeImpl::hasAttribute(StringRef Kind) const {
417*9880d681SAndroid Build Coastguard Worker   if (!isStringAttribute()) return false;
418*9880d681SAndroid Build Coastguard Worker   return getKindAsString() == Kind;
419*9880d681SAndroid Build Coastguard Worker }
420*9880d681SAndroid Build Coastguard Worker 
getKindAsEnum() const421*9880d681SAndroid Build Coastguard Worker Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
422*9880d681SAndroid Build Coastguard Worker   assert(isEnumAttribute() || isIntAttribute());
423*9880d681SAndroid Build Coastguard Worker   return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
424*9880d681SAndroid Build Coastguard Worker }
425*9880d681SAndroid Build Coastguard Worker 
getValueAsInt() const426*9880d681SAndroid Build Coastguard Worker uint64_t AttributeImpl::getValueAsInt() const {
427*9880d681SAndroid Build Coastguard Worker   assert(isIntAttribute());
428*9880d681SAndroid Build Coastguard Worker   return static_cast<const IntAttributeImpl *>(this)->getValue();
429*9880d681SAndroid Build Coastguard Worker }
430*9880d681SAndroid Build Coastguard Worker 
getKindAsString() const431*9880d681SAndroid Build Coastguard Worker StringRef AttributeImpl::getKindAsString() const {
432*9880d681SAndroid Build Coastguard Worker   assert(isStringAttribute());
433*9880d681SAndroid Build Coastguard Worker   return static_cast<const StringAttributeImpl *>(this)->getStringKind();
434*9880d681SAndroid Build Coastguard Worker }
435*9880d681SAndroid Build Coastguard Worker 
getValueAsString() const436*9880d681SAndroid Build Coastguard Worker StringRef AttributeImpl::getValueAsString() const {
437*9880d681SAndroid Build Coastguard Worker   assert(isStringAttribute());
438*9880d681SAndroid Build Coastguard Worker   return static_cast<const StringAttributeImpl *>(this)->getStringValue();
439*9880d681SAndroid Build Coastguard Worker }
440*9880d681SAndroid Build Coastguard Worker 
operator <(const AttributeImpl & AI) const441*9880d681SAndroid Build Coastguard Worker bool AttributeImpl::operator<(const AttributeImpl &AI) const {
442*9880d681SAndroid Build Coastguard Worker   // This sorts the attributes with Attribute::AttrKinds coming first (sorted
443*9880d681SAndroid Build Coastguard Worker   // relative to their enum value) and then strings.
444*9880d681SAndroid Build Coastguard Worker   if (isEnumAttribute()) {
445*9880d681SAndroid Build Coastguard Worker     if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();
446*9880d681SAndroid Build Coastguard Worker     if (AI.isIntAttribute()) return true;
447*9880d681SAndroid Build Coastguard Worker     if (AI.isStringAttribute()) return true;
448*9880d681SAndroid Build Coastguard Worker   }
449*9880d681SAndroid Build Coastguard Worker 
450*9880d681SAndroid Build Coastguard Worker   if (isIntAttribute()) {
451*9880d681SAndroid Build Coastguard Worker     if (AI.isEnumAttribute()) return false;
452*9880d681SAndroid Build Coastguard Worker     if (AI.isIntAttribute()) {
453*9880d681SAndroid Build Coastguard Worker       if (getKindAsEnum() == AI.getKindAsEnum())
454*9880d681SAndroid Build Coastguard Worker         return getValueAsInt() < AI.getValueAsInt();
455*9880d681SAndroid Build Coastguard Worker       return getKindAsEnum() < AI.getKindAsEnum();
456*9880d681SAndroid Build Coastguard Worker     }
457*9880d681SAndroid Build Coastguard Worker     if (AI.isStringAttribute()) return true;
458*9880d681SAndroid Build Coastguard Worker   }
459*9880d681SAndroid Build Coastguard Worker 
460*9880d681SAndroid Build Coastguard Worker   if (AI.isEnumAttribute()) return false;
461*9880d681SAndroid Build Coastguard Worker   if (AI.isIntAttribute()) return false;
462*9880d681SAndroid Build Coastguard Worker   if (getKindAsString() == AI.getKindAsString())
463*9880d681SAndroid Build Coastguard Worker     return getValueAsString() < AI.getValueAsString();
464*9880d681SAndroid Build Coastguard Worker   return getKindAsString() < AI.getKindAsString();
465*9880d681SAndroid Build Coastguard Worker }
466*9880d681SAndroid Build Coastguard Worker 
getAttrMask(Attribute::AttrKind Val)467*9880d681SAndroid Build Coastguard Worker uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
468*9880d681SAndroid Build Coastguard Worker   // FIXME: Remove this.
469*9880d681SAndroid Build Coastguard Worker   switch (Val) {
470*9880d681SAndroid Build Coastguard Worker   case Attribute::EndAttrKinds:
471*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Synthetic enumerators which should never get here");
472*9880d681SAndroid Build Coastguard Worker 
473*9880d681SAndroid Build Coastguard Worker   case Attribute::None:            return 0;
474*9880d681SAndroid Build Coastguard Worker   case Attribute::ZExt:            return 1 << 0;
475*9880d681SAndroid Build Coastguard Worker   case Attribute::SExt:            return 1 << 1;
476*9880d681SAndroid Build Coastguard Worker   case Attribute::NoReturn:        return 1 << 2;
477*9880d681SAndroid Build Coastguard Worker   case Attribute::InReg:           return 1 << 3;
478*9880d681SAndroid Build Coastguard Worker   case Attribute::StructRet:       return 1 << 4;
479*9880d681SAndroid Build Coastguard Worker   case Attribute::NoUnwind:        return 1 << 5;
480*9880d681SAndroid Build Coastguard Worker   case Attribute::NoAlias:         return 1 << 6;
481*9880d681SAndroid Build Coastguard Worker   case Attribute::ByVal:           return 1 << 7;
482*9880d681SAndroid Build Coastguard Worker   case Attribute::Nest:            return 1 << 8;
483*9880d681SAndroid Build Coastguard Worker   case Attribute::ReadNone:        return 1 << 9;
484*9880d681SAndroid Build Coastguard Worker   case Attribute::ReadOnly:        return 1 << 10;
485*9880d681SAndroid Build Coastguard Worker   case Attribute::NoInline:        return 1 << 11;
486*9880d681SAndroid Build Coastguard Worker   case Attribute::AlwaysInline:    return 1 << 12;
487*9880d681SAndroid Build Coastguard Worker   case Attribute::OptimizeForSize: return 1 << 13;
488*9880d681SAndroid Build Coastguard Worker   case Attribute::StackProtect:    return 1 << 14;
489*9880d681SAndroid Build Coastguard Worker   case Attribute::StackProtectReq: return 1 << 15;
490*9880d681SAndroid Build Coastguard Worker   case Attribute::Alignment:       return 31 << 16;
491*9880d681SAndroid Build Coastguard Worker   case Attribute::NoCapture:       return 1 << 21;
492*9880d681SAndroid Build Coastguard Worker   case Attribute::NoRedZone:       return 1 << 22;
493*9880d681SAndroid Build Coastguard Worker   case Attribute::NoImplicitFloat: return 1 << 23;
494*9880d681SAndroid Build Coastguard Worker   case Attribute::Naked:           return 1 << 24;
495*9880d681SAndroid Build Coastguard Worker   case Attribute::InlineHint:      return 1 << 25;
496*9880d681SAndroid Build Coastguard Worker   case Attribute::StackAlignment:  return 7 << 26;
497*9880d681SAndroid Build Coastguard Worker   case Attribute::ReturnsTwice:    return 1 << 29;
498*9880d681SAndroid Build Coastguard Worker   case Attribute::UWTable:         return 1 << 30;
499*9880d681SAndroid Build Coastguard Worker   case Attribute::NonLazyBind:     return 1U << 31;
500*9880d681SAndroid Build Coastguard Worker   case Attribute::SanitizeAddress: return 1ULL << 32;
501*9880d681SAndroid Build Coastguard Worker   case Attribute::MinSize:         return 1ULL << 33;
502*9880d681SAndroid Build Coastguard Worker   case Attribute::NoDuplicate:     return 1ULL << 34;
503*9880d681SAndroid Build Coastguard Worker   case Attribute::StackProtectStrong: return 1ULL << 35;
504*9880d681SAndroid Build Coastguard Worker   case Attribute::SanitizeThread:  return 1ULL << 36;
505*9880d681SAndroid Build Coastguard Worker   case Attribute::SanitizeMemory:  return 1ULL << 37;
506*9880d681SAndroid Build Coastguard Worker   case Attribute::NoBuiltin:       return 1ULL << 38;
507*9880d681SAndroid Build Coastguard Worker   case Attribute::Returned:        return 1ULL << 39;
508*9880d681SAndroid Build Coastguard Worker   case Attribute::Cold:            return 1ULL << 40;
509*9880d681SAndroid Build Coastguard Worker   case Attribute::Builtin:         return 1ULL << 41;
510*9880d681SAndroid Build Coastguard Worker   case Attribute::OptimizeNone:    return 1ULL << 42;
511*9880d681SAndroid Build Coastguard Worker   case Attribute::InAlloca:        return 1ULL << 43;
512*9880d681SAndroid Build Coastguard Worker   case Attribute::NonNull:         return 1ULL << 44;
513*9880d681SAndroid Build Coastguard Worker   case Attribute::JumpTable:       return 1ULL << 45;
514*9880d681SAndroid Build Coastguard Worker   case Attribute::Convergent:      return 1ULL << 46;
515*9880d681SAndroid Build Coastguard Worker   case Attribute::SafeStack:       return 1ULL << 47;
516*9880d681SAndroid Build Coastguard Worker   case Attribute::NoRecurse:       return 1ULL << 48;
517*9880d681SAndroid Build Coastguard Worker   case Attribute::InaccessibleMemOnly:         return 1ULL << 49;
518*9880d681SAndroid Build Coastguard Worker   case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50;
519*9880d681SAndroid Build Coastguard Worker   case Attribute::SwiftSelf:       return 1ULL << 51;
520*9880d681SAndroid Build Coastguard Worker   case Attribute::SwiftError:      return 1ULL << 52;
521*9880d681SAndroid Build Coastguard Worker   case Attribute::WriteOnly:       return 1ULL << 53;
522*9880d681SAndroid Build Coastguard Worker   case Attribute::Dereferenceable:
523*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("dereferenceable attribute not supported in raw format");
524*9880d681SAndroid Build Coastguard Worker     break;
525*9880d681SAndroid Build Coastguard Worker   case Attribute::DereferenceableOrNull:
526*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("dereferenceable_or_null attribute not supported in raw "
527*9880d681SAndroid Build Coastguard Worker                      "format");
528*9880d681SAndroid Build Coastguard Worker     break;
529*9880d681SAndroid Build Coastguard Worker   case Attribute::ArgMemOnly:
530*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("argmemonly attribute not supported in raw format");
531*9880d681SAndroid Build Coastguard Worker     break;
532*9880d681SAndroid Build Coastguard Worker   case Attribute::AllocSize:
533*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("allocsize not supported in raw format");
534*9880d681SAndroid Build Coastguard Worker     break;
535*9880d681SAndroid Build Coastguard Worker   }
536*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unsupported attribute type");
537*9880d681SAndroid Build Coastguard Worker }
538*9880d681SAndroid Build Coastguard Worker 
539*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
540*9880d681SAndroid Build Coastguard Worker // AttributeSetNode Definition
541*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
542*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)543*9880d681SAndroid Build Coastguard Worker AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
544*9880d681SAndroid Build Coastguard Worker                                         ArrayRef<Attribute> Attrs) {
545*9880d681SAndroid Build Coastguard Worker   if (Attrs.empty())
546*9880d681SAndroid Build Coastguard Worker     return nullptr;
547*9880d681SAndroid Build Coastguard Worker 
548*9880d681SAndroid Build Coastguard Worker   // Otherwise, build a key to look up the existing attributes.
549*9880d681SAndroid Build Coastguard Worker   LLVMContextImpl *pImpl = C.pImpl;
550*9880d681SAndroid Build Coastguard Worker   FoldingSetNodeID ID;
551*9880d681SAndroid Build Coastguard Worker 
552*9880d681SAndroid Build Coastguard Worker   SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
553*9880d681SAndroid Build Coastguard Worker   std::sort(SortedAttrs.begin(), SortedAttrs.end());
554*9880d681SAndroid Build Coastguard Worker 
555*9880d681SAndroid Build Coastguard Worker   for (Attribute Attr : SortedAttrs)
556*9880d681SAndroid Build Coastguard Worker     Attr.Profile(ID);
557*9880d681SAndroid Build Coastguard Worker 
558*9880d681SAndroid Build Coastguard Worker   void *InsertPoint;
559*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *PA =
560*9880d681SAndroid Build Coastguard Worker     pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
561*9880d681SAndroid Build Coastguard Worker 
562*9880d681SAndroid Build Coastguard Worker   // If we didn't find any existing attributes of the same shape then create a
563*9880d681SAndroid Build Coastguard Worker   // new one and insert it.
564*9880d681SAndroid Build Coastguard Worker   if (!PA) {
565*9880d681SAndroid Build Coastguard Worker     // Coallocate entries after the AttributeSetNode itself.
566*9880d681SAndroid Build Coastguard Worker     void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
567*9880d681SAndroid Build Coastguard Worker     PA = new (Mem) AttributeSetNode(SortedAttrs);
568*9880d681SAndroid Build Coastguard Worker     pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
569*9880d681SAndroid Build Coastguard Worker   }
570*9880d681SAndroid Build Coastguard Worker 
571*9880d681SAndroid Build Coastguard Worker   // Return the AttributesListNode that we found or created.
572*9880d681SAndroid Build Coastguard Worker   return PA;
573*9880d681SAndroid Build Coastguard Worker }
574*9880d681SAndroid Build Coastguard Worker 
hasAttribute(StringRef Kind) const575*9880d681SAndroid Build Coastguard Worker bool AttributeSetNode::hasAttribute(StringRef Kind) const {
576*9880d681SAndroid Build Coastguard Worker   for (Attribute I : *this)
577*9880d681SAndroid Build Coastguard Worker     if (I.hasAttribute(Kind))
578*9880d681SAndroid Build Coastguard Worker       return true;
579*9880d681SAndroid Build Coastguard Worker   return false;
580*9880d681SAndroid Build Coastguard Worker }
581*9880d681SAndroid Build Coastguard Worker 
getAttribute(Attribute::AttrKind Kind) const582*9880d681SAndroid Build Coastguard Worker Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
583*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Kind)) {
584*9880d681SAndroid Build Coastguard Worker     for (Attribute I : *this)
585*9880d681SAndroid Build Coastguard Worker       if (I.hasAttribute(Kind))
586*9880d681SAndroid Build Coastguard Worker         return I;
587*9880d681SAndroid Build Coastguard Worker   }
588*9880d681SAndroid Build Coastguard Worker   return Attribute();
589*9880d681SAndroid Build Coastguard Worker }
590*9880d681SAndroid Build Coastguard Worker 
getAttribute(StringRef Kind) const591*9880d681SAndroid Build Coastguard Worker Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
592*9880d681SAndroid Build Coastguard Worker   for (Attribute I : *this)
593*9880d681SAndroid Build Coastguard Worker     if (I.hasAttribute(Kind))
594*9880d681SAndroid Build Coastguard Worker       return I;
595*9880d681SAndroid Build Coastguard Worker   return Attribute();
596*9880d681SAndroid Build Coastguard Worker }
597*9880d681SAndroid Build Coastguard Worker 
getAlignment() const598*9880d681SAndroid Build Coastguard Worker unsigned AttributeSetNode::getAlignment() const {
599*9880d681SAndroid Build Coastguard Worker   for (Attribute I : *this)
600*9880d681SAndroid Build Coastguard Worker     if (I.hasAttribute(Attribute::Alignment))
601*9880d681SAndroid Build Coastguard Worker       return I.getAlignment();
602*9880d681SAndroid Build Coastguard Worker   return 0;
603*9880d681SAndroid Build Coastguard Worker }
604*9880d681SAndroid Build Coastguard Worker 
getStackAlignment() const605*9880d681SAndroid Build Coastguard Worker unsigned AttributeSetNode::getStackAlignment() const {
606*9880d681SAndroid Build Coastguard Worker   for (Attribute I : *this)
607*9880d681SAndroid Build Coastguard Worker     if (I.hasAttribute(Attribute::StackAlignment))
608*9880d681SAndroid Build Coastguard Worker       return I.getStackAlignment();
609*9880d681SAndroid Build Coastguard Worker   return 0;
610*9880d681SAndroid Build Coastguard Worker }
611*9880d681SAndroid Build Coastguard Worker 
getDereferenceableBytes() const612*9880d681SAndroid Build Coastguard Worker uint64_t AttributeSetNode::getDereferenceableBytes() const {
613*9880d681SAndroid Build Coastguard Worker   for (Attribute I : *this)
614*9880d681SAndroid Build Coastguard Worker     if (I.hasAttribute(Attribute::Dereferenceable))
615*9880d681SAndroid Build Coastguard Worker       return I.getDereferenceableBytes();
616*9880d681SAndroid Build Coastguard Worker   return 0;
617*9880d681SAndroid Build Coastguard Worker }
618*9880d681SAndroid Build Coastguard Worker 
getDereferenceableOrNullBytes() const619*9880d681SAndroid Build Coastguard Worker uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
620*9880d681SAndroid Build Coastguard Worker   for (Attribute I : *this)
621*9880d681SAndroid Build Coastguard Worker     if (I.hasAttribute(Attribute::DereferenceableOrNull))
622*9880d681SAndroid Build Coastguard Worker       return I.getDereferenceableOrNullBytes();
623*9880d681SAndroid Build Coastguard Worker   return 0;
624*9880d681SAndroid Build Coastguard Worker }
625*9880d681SAndroid Build Coastguard Worker 
626*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs() const627*9880d681SAndroid Build Coastguard Worker AttributeSetNode::getAllocSizeArgs() const {
628*9880d681SAndroid Build Coastguard Worker   for (Attribute I : *this)
629*9880d681SAndroid Build Coastguard Worker     if (I.hasAttribute(Attribute::AllocSize))
630*9880d681SAndroid Build Coastguard Worker       return I.getAllocSizeArgs();
631*9880d681SAndroid Build Coastguard Worker   return std::make_pair(0, 0);
632*9880d681SAndroid Build Coastguard Worker }
633*9880d681SAndroid Build Coastguard Worker 
getAsString(bool InAttrGrp) const634*9880d681SAndroid Build Coastguard Worker std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
635*9880d681SAndroid Build Coastguard Worker   std::string Str;
636*9880d681SAndroid Build Coastguard Worker   for (iterator I = begin(), E = end(); I != E; ++I) {
637*9880d681SAndroid Build Coastguard Worker     if (I != begin())
638*9880d681SAndroid Build Coastguard Worker       Str += ' ';
639*9880d681SAndroid Build Coastguard Worker     Str += I->getAsString(InAttrGrp);
640*9880d681SAndroid Build Coastguard Worker   }
641*9880d681SAndroid Build Coastguard Worker   return Str;
642*9880d681SAndroid Build Coastguard Worker }
643*9880d681SAndroid Build Coastguard Worker 
644*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
645*9880d681SAndroid Build Coastguard Worker // AttributeSetImpl Definition
646*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
647*9880d681SAndroid Build Coastguard Worker 
Raw(unsigned Index) const648*9880d681SAndroid Build Coastguard Worker uint64_t AttributeSetImpl::Raw(unsigned Index) const {
649*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = getNumSlots(); I != E; ++I) {
650*9880d681SAndroid Build Coastguard Worker     if (getSlotIndex(I) != Index) continue;
651*9880d681SAndroid Build Coastguard Worker     const AttributeSetNode *ASN = getSlotNode(I);
652*9880d681SAndroid Build Coastguard Worker     uint64_t Mask = 0;
653*9880d681SAndroid Build Coastguard Worker 
654*9880d681SAndroid Build Coastguard Worker     for (AttributeSetNode::iterator II = ASN->begin(),
655*9880d681SAndroid Build Coastguard Worker            IE = ASN->end(); II != IE; ++II) {
656*9880d681SAndroid Build Coastguard Worker       Attribute Attr = *II;
657*9880d681SAndroid Build Coastguard Worker 
658*9880d681SAndroid Build Coastguard Worker       // This cannot handle string attributes.
659*9880d681SAndroid Build Coastguard Worker       if (Attr.isStringAttribute()) continue;
660*9880d681SAndroid Build Coastguard Worker 
661*9880d681SAndroid Build Coastguard Worker       Attribute::AttrKind Kind = Attr.getKindAsEnum();
662*9880d681SAndroid Build Coastguard Worker 
663*9880d681SAndroid Build Coastguard Worker       if (Kind == Attribute::Alignment)
664*9880d681SAndroid Build Coastguard Worker         Mask |= (Log2_32(ASN->getAlignment()) + 1) << 16;
665*9880d681SAndroid Build Coastguard Worker       else if (Kind == Attribute::StackAlignment)
666*9880d681SAndroid Build Coastguard Worker         Mask |= (Log2_32(ASN->getStackAlignment()) + 1) << 26;
667*9880d681SAndroid Build Coastguard Worker       else if (Kind == Attribute::Dereferenceable)
668*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("dereferenceable not supported in bit mask");
669*9880d681SAndroid Build Coastguard Worker       else if (Kind == Attribute::AllocSize)
670*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("allocsize not supported in bit mask");
671*9880d681SAndroid Build Coastguard Worker       else
672*9880d681SAndroid Build Coastguard Worker         Mask |= AttributeImpl::getAttrMask(Kind);
673*9880d681SAndroid Build Coastguard Worker     }
674*9880d681SAndroid Build Coastguard Worker 
675*9880d681SAndroid Build Coastguard Worker     return Mask;
676*9880d681SAndroid Build Coastguard Worker   }
677*9880d681SAndroid Build Coastguard Worker 
678*9880d681SAndroid Build Coastguard Worker   return 0;
679*9880d681SAndroid Build Coastguard Worker }
680*9880d681SAndroid Build Coastguard Worker 
dump() const681*9880d681SAndroid Build Coastguard Worker LLVM_DUMP_METHOD void AttributeSetImpl::dump() const {
682*9880d681SAndroid Build Coastguard Worker   AttributeSet(const_cast<AttributeSetImpl *>(this)).dump();
683*9880d681SAndroid Build Coastguard Worker }
684*9880d681SAndroid Build Coastguard Worker 
685*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
686*9880d681SAndroid Build Coastguard Worker // AttributeSet Construction and Mutation Methods
687*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
688*9880d681SAndroid Build Coastguard Worker 
689*9880d681SAndroid Build Coastguard Worker AttributeSet
getImpl(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSetNode * >> Attrs)690*9880d681SAndroid Build Coastguard Worker AttributeSet::getImpl(LLVMContext &C,
691*9880d681SAndroid Build Coastguard Worker                       ArrayRef<std::pair<unsigned, AttributeSetNode*> > Attrs) {
692*9880d681SAndroid Build Coastguard Worker   LLVMContextImpl *pImpl = C.pImpl;
693*9880d681SAndroid Build Coastguard Worker   FoldingSetNodeID ID;
694*9880d681SAndroid Build Coastguard Worker   AttributeSetImpl::Profile(ID, Attrs);
695*9880d681SAndroid Build Coastguard Worker 
696*9880d681SAndroid Build Coastguard Worker   void *InsertPoint;
697*9880d681SAndroid Build Coastguard Worker   AttributeSetImpl *PA = pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
698*9880d681SAndroid Build Coastguard Worker 
699*9880d681SAndroid Build Coastguard Worker   // If we didn't find any existing attributes of the same shape then
700*9880d681SAndroid Build Coastguard Worker   // create a new one and insert it.
701*9880d681SAndroid Build Coastguard Worker   if (!PA) {
702*9880d681SAndroid Build Coastguard Worker     // Coallocate entries after the AttributeSetImpl itself.
703*9880d681SAndroid Build Coastguard Worker     void *Mem = ::operator new(
704*9880d681SAndroid Build Coastguard Worker         AttributeSetImpl::totalSizeToAlloc<IndexAttrPair>(Attrs.size()));
705*9880d681SAndroid Build Coastguard Worker     PA = new (Mem) AttributeSetImpl(C, Attrs);
706*9880d681SAndroid Build Coastguard Worker     pImpl->AttrsLists.InsertNode(PA, InsertPoint);
707*9880d681SAndroid Build Coastguard Worker   }
708*9880d681SAndroid Build Coastguard Worker 
709*9880d681SAndroid Build Coastguard Worker   // Return the AttributesList that we found or created.
710*9880d681SAndroid Build Coastguard Worker   return AttributeSet(PA);
711*9880d681SAndroid Build Coastguard Worker }
712*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)713*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::get(LLVMContext &C,
714*9880d681SAndroid Build Coastguard Worker                                ArrayRef<std::pair<unsigned, Attribute> > Attrs){
715*9880d681SAndroid Build Coastguard Worker   // If there are no attributes then return a null AttributesList pointer.
716*9880d681SAndroid Build Coastguard Worker   if (Attrs.empty())
717*9880d681SAndroid Build Coastguard Worker     return AttributeSet();
718*9880d681SAndroid Build Coastguard Worker 
719*9880d681SAndroid Build Coastguard Worker   assert(std::is_sorted(Attrs.begin(), Attrs.end(),
720*9880d681SAndroid Build Coastguard Worker                         [](const std::pair<unsigned, Attribute> &LHS,
721*9880d681SAndroid Build Coastguard Worker                            const std::pair<unsigned, Attribute> &RHS) {
722*9880d681SAndroid Build Coastguard Worker                           return LHS.first < RHS.first;
723*9880d681SAndroid Build Coastguard Worker                         }) && "Misordered Attributes list!");
724*9880d681SAndroid Build Coastguard Worker   assert(std::none_of(Attrs.begin(), Attrs.end(),
725*9880d681SAndroid Build Coastguard Worker                       [](const std::pair<unsigned, Attribute> &Pair) {
726*9880d681SAndroid Build Coastguard Worker                         return Pair.second.hasAttribute(Attribute::None);
727*9880d681SAndroid Build Coastguard Worker                       }) && "Pointless attribute!");
728*9880d681SAndroid Build Coastguard Worker 
729*9880d681SAndroid Build Coastguard Worker   // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
730*9880d681SAndroid Build Coastguard Worker   // list.
731*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<unsigned, AttributeSetNode*>, 8> AttrPairVec;
732*9880d681SAndroid Build Coastguard Worker   for (ArrayRef<std::pair<unsigned, Attribute> >::iterator I = Attrs.begin(),
733*9880d681SAndroid Build Coastguard Worker          E = Attrs.end(); I != E; ) {
734*9880d681SAndroid Build Coastguard Worker     unsigned Index = I->first;
735*9880d681SAndroid Build Coastguard Worker     SmallVector<Attribute, 4> AttrVec;
736*9880d681SAndroid Build Coastguard Worker     while (I != E && I->first == Index) {
737*9880d681SAndroid Build Coastguard Worker       AttrVec.push_back(I->second);
738*9880d681SAndroid Build Coastguard Worker       ++I;
739*9880d681SAndroid Build Coastguard Worker     }
740*9880d681SAndroid Build Coastguard Worker 
741*9880d681SAndroid Build Coastguard Worker     AttrPairVec.push_back(std::make_pair(Index,
742*9880d681SAndroid Build Coastguard Worker                                          AttributeSetNode::get(C, AttrVec)));
743*9880d681SAndroid Build Coastguard Worker   }
744*9880d681SAndroid Build Coastguard Worker 
745*9880d681SAndroid Build Coastguard Worker   return getImpl(C, AttrPairVec);
746*9880d681SAndroid Build Coastguard Worker }
747*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSetNode * >> Attrs)748*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::get(LLVMContext &C,
749*9880d681SAndroid Build Coastguard Worker                                ArrayRef<std::pair<unsigned,
750*9880d681SAndroid Build Coastguard Worker                                                   AttributeSetNode*> > Attrs) {
751*9880d681SAndroid Build Coastguard Worker   // If there are no attributes then return a null AttributesList pointer.
752*9880d681SAndroid Build Coastguard Worker   if (Attrs.empty())
753*9880d681SAndroid Build Coastguard Worker     return AttributeSet();
754*9880d681SAndroid Build Coastguard Worker 
755*9880d681SAndroid Build Coastguard Worker   return getImpl(C, Attrs);
756*9880d681SAndroid Build Coastguard Worker }
757*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)758*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
759*9880d681SAndroid Build Coastguard Worker                                const AttrBuilder &B) {
760*9880d681SAndroid Build Coastguard Worker   if (!B.hasAttributes())
761*9880d681SAndroid Build Coastguard Worker     return AttributeSet();
762*9880d681SAndroid Build Coastguard Worker 
763*9880d681SAndroid Build Coastguard Worker   // Add target-independent attributes.
764*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
765*9880d681SAndroid Build Coastguard Worker   for (Attribute::AttrKind Kind = Attribute::None;
766*9880d681SAndroid Build Coastguard Worker        Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
767*9880d681SAndroid Build Coastguard Worker     if (!B.contains(Kind))
768*9880d681SAndroid Build Coastguard Worker       continue;
769*9880d681SAndroid Build Coastguard Worker 
770*9880d681SAndroid Build Coastguard Worker     Attribute Attr;
771*9880d681SAndroid Build Coastguard Worker     switch (Kind) {
772*9880d681SAndroid Build Coastguard Worker     case Attribute::Alignment:
773*9880d681SAndroid Build Coastguard Worker       Attr = Attribute::getWithAlignment(C, B.getAlignment());
774*9880d681SAndroid Build Coastguard Worker       break;
775*9880d681SAndroid Build Coastguard Worker     case Attribute::StackAlignment:
776*9880d681SAndroid Build Coastguard Worker       Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment());
777*9880d681SAndroid Build Coastguard Worker       break;
778*9880d681SAndroid Build Coastguard Worker     case Attribute::Dereferenceable:
779*9880d681SAndroid Build Coastguard Worker       Attr = Attribute::getWithDereferenceableBytes(
780*9880d681SAndroid Build Coastguard Worker           C, B.getDereferenceableBytes());
781*9880d681SAndroid Build Coastguard Worker       break;
782*9880d681SAndroid Build Coastguard Worker     case Attribute::DereferenceableOrNull:
783*9880d681SAndroid Build Coastguard Worker       Attr = Attribute::getWithDereferenceableOrNullBytes(
784*9880d681SAndroid Build Coastguard Worker           C, B.getDereferenceableOrNullBytes());
785*9880d681SAndroid Build Coastguard Worker       break;
786*9880d681SAndroid Build Coastguard Worker     case Attribute::AllocSize: {
787*9880d681SAndroid Build Coastguard Worker       auto A = B.getAllocSizeArgs();
788*9880d681SAndroid Build Coastguard Worker       Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
789*9880d681SAndroid Build Coastguard Worker       break;
790*9880d681SAndroid Build Coastguard Worker     }
791*9880d681SAndroid Build Coastguard Worker     default:
792*9880d681SAndroid Build Coastguard Worker       Attr = Attribute::get(C, Kind);
793*9880d681SAndroid Build Coastguard Worker     }
794*9880d681SAndroid Build Coastguard Worker     Attrs.push_back(std::make_pair(Index, Attr));
795*9880d681SAndroid Build Coastguard Worker   }
796*9880d681SAndroid Build Coastguard Worker 
797*9880d681SAndroid Build Coastguard Worker   // Add target-dependent (string) attributes.
798*9880d681SAndroid Build Coastguard Worker   for (const auto &TDA : B.td_attrs())
799*9880d681SAndroid Build Coastguard Worker     Attrs.push_back(
800*9880d681SAndroid Build Coastguard Worker         std::make_pair(Index, Attribute::get(C, TDA.first, TDA.second)));
801*9880d681SAndroid Build Coastguard Worker 
802*9880d681SAndroid Build Coastguard Worker   return get(C, Attrs);
803*9880d681SAndroid Build Coastguard Worker }
804*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)805*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
806*9880d681SAndroid Build Coastguard Worker                                ArrayRef<Attribute::AttrKind> Kinds) {
807*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
808*9880d681SAndroid Build Coastguard Worker   for (Attribute::AttrKind K : Kinds)
809*9880d681SAndroid Build Coastguard Worker     Attrs.push_back(std::make_pair(Index, Attribute::get(C, K)));
810*9880d681SAndroid Build Coastguard Worker   return get(C, Attrs);
811*9880d681SAndroid Build Coastguard Worker }
812*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)813*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
814*9880d681SAndroid Build Coastguard Worker                                ArrayRef<StringRef> Kinds) {
815*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
816*9880d681SAndroid Build Coastguard Worker   for (StringRef K : Kinds)
817*9880d681SAndroid Build Coastguard Worker     Attrs.push_back(std::make_pair(Index, Attribute::get(C, K)));
818*9880d681SAndroid Build Coastguard Worker   return get(C, Attrs);
819*9880d681SAndroid Build Coastguard Worker }
820*9880d681SAndroid Build Coastguard Worker 
get(LLVMContext & C,ArrayRef<AttributeSet> Attrs)821*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) {
822*9880d681SAndroid Build Coastguard Worker   if (Attrs.empty()) return AttributeSet();
823*9880d681SAndroid Build Coastguard Worker   if (Attrs.size() == 1) return Attrs[0];
824*9880d681SAndroid Build Coastguard Worker 
825*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<unsigned, AttributeSetNode*>, 8> AttrNodeVec;
826*9880d681SAndroid Build Coastguard Worker   AttributeSetImpl *A0 = Attrs[0].pImpl;
827*9880d681SAndroid Build Coastguard Worker   if (A0)
828*9880d681SAndroid Build Coastguard Worker     AttrNodeVec.append(A0->getNode(0), A0->getNode(A0->getNumSlots()));
829*9880d681SAndroid Build Coastguard Worker   // Copy all attributes from Attrs into AttrNodeVec while keeping AttrNodeVec
830*9880d681SAndroid Build Coastguard Worker   // ordered by index.  Because we know that each list in Attrs is ordered by
831*9880d681SAndroid Build Coastguard Worker   // index we only need to merge each successive list in rather than doing a
832*9880d681SAndroid Build Coastguard Worker   // full sort.
833*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 1, E = Attrs.size(); I != E; ++I) {
834*9880d681SAndroid Build Coastguard Worker     AttributeSetImpl *AS = Attrs[I].pImpl;
835*9880d681SAndroid Build Coastguard Worker     if (!AS) continue;
836*9880d681SAndroid Build Coastguard Worker     SmallVector<std::pair<unsigned, AttributeSetNode *>, 8>::iterator
837*9880d681SAndroid Build Coastguard Worker       ANVI = AttrNodeVec.begin(), ANVE;
838*9880d681SAndroid Build Coastguard Worker     for (const IndexAttrPair *AI = AS->getNode(0),
839*9880d681SAndroid Build Coastguard Worker                              *AE = AS->getNode(AS->getNumSlots());
840*9880d681SAndroid Build Coastguard Worker          AI != AE; ++AI) {
841*9880d681SAndroid Build Coastguard Worker       ANVE = AttrNodeVec.end();
842*9880d681SAndroid Build Coastguard Worker       while (ANVI != ANVE && ANVI->first <= AI->first)
843*9880d681SAndroid Build Coastguard Worker         ++ANVI;
844*9880d681SAndroid Build Coastguard Worker       ANVI = AttrNodeVec.insert(ANVI, *AI) + 1;
845*9880d681SAndroid Build Coastguard Worker     }
846*9880d681SAndroid Build Coastguard Worker   }
847*9880d681SAndroid Build Coastguard Worker 
848*9880d681SAndroid Build Coastguard Worker   return getImpl(C, AttrNodeVec);
849*9880d681SAndroid Build Coastguard Worker }
850*9880d681SAndroid Build Coastguard Worker 
addAttribute(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const851*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
852*9880d681SAndroid Build Coastguard Worker                                         Attribute::AttrKind Kind) const {
853*9880d681SAndroid Build Coastguard Worker   if (hasAttribute(Index, Kind)) return *this;
854*9880d681SAndroid Build Coastguard Worker   return addAttributes(C, Index, AttributeSet::get(C, Index, Kind));
855*9880d681SAndroid Build Coastguard Worker }
856*9880d681SAndroid Build Coastguard Worker 
addAttribute(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const857*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
858*9880d681SAndroid Build Coastguard Worker                                         StringRef Kind, StringRef Value) const {
859*9880d681SAndroid Build Coastguard Worker   llvm::AttrBuilder B;
860*9880d681SAndroid Build Coastguard Worker   B.addAttribute(Kind, Value);
861*9880d681SAndroid Build Coastguard Worker   return addAttributes(C, Index, AttributeSet::get(C, Index, B));
862*9880d681SAndroid Build Coastguard Worker }
863*9880d681SAndroid Build Coastguard Worker 
addAttribute(LLVMContext & C,ArrayRef<unsigned> Indices,Attribute A) const864*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::addAttribute(LLVMContext &C,
865*9880d681SAndroid Build Coastguard Worker                                         ArrayRef<unsigned> Indices,
866*9880d681SAndroid Build Coastguard Worker                                         Attribute A) const {
867*9880d681SAndroid Build Coastguard Worker   unsigned I = 0, E = pImpl ? pImpl->getNumSlots() : 0;
868*9880d681SAndroid Build Coastguard Worker   auto IdxI = Indices.begin(), IdxE = Indices.end();
869*9880d681SAndroid Build Coastguard Worker   SmallVector<AttributeSet, 4> AttrSet;
870*9880d681SAndroid Build Coastguard Worker 
871*9880d681SAndroid Build Coastguard Worker   while (I != E && IdxI != IdxE) {
872*9880d681SAndroid Build Coastguard Worker     if (getSlotIndex(I) < *IdxI)
873*9880d681SAndroid Build Coastguard Worker       AttrSet.emplace_back(getSlotAttributes(I++));
874*9880d681SAndroid Build Coastguard Worker     else if (getSlotIndex(I) > *IdxI)
875*9880d681SAndroid Build Coastguard Worker       AttrSet.emplace_back(AttributeSet::get(C, std::make_pair(*IdxI++, A)));
876*9880d681SAndroid Build Coastguard Worker     else {
877*9880d681SAndroid Build Coastguard Worker       AttrBuilder B(getSlotAttributes(I), *IdxI);
878*9880d681SAndroid Build Coastguard Worker       B.addAttribute(A);
879*9880d681SAndroid Build Coastguard Worker       AttrSet.emplace_back(AttributeSet::get(C, *IdxI, B));
880*9880d681SAndroid Build Coastguard Worker       ++I;
881*9880d681SAndroid Build Coastguard Worker       ++IdxI;
882*9880d681SAndroid Build Coastguard Worker     }
883*9880d681SAndroid Build Coastguard Worker   }
884*9880d681SAndroid Build Coastguard Worker 
885*9880d681SAndroid Build Coastguard Worker   while (I != E)
886*9880d681SAndroid Build Coastguard Worker     AttrSet.emplace_back(getSlotAttributes(I++));
887*9880d681SAndroid Build Coastguard Worker 
888*9880d681SAndroid Build Coastguard Worker   while (IdxI != IdxE)
889*9880d681SAndroid Build Coastguard Worker     AttrSet.emplace_back(AttributeSet::get(C, std::make_pair(*IdxI++, A)));
890*9880d681SAndroid Build Coastguard Worker 
891*9880d681SAndroid Build Coastguard Worker   return get(C, AttrSet);
892*9880d681SAndroid Build Coastguard Worker }
893*9880d681SAndroid Build Coastguard Worker 
addAttributes(LLVMContext & C,unsigned Index,AttributeSet Attrs) const894*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index,
895*9880d681SAndroid Build Coastguard Worker                                          AttributeSet Attrs) const {
896*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return Attrs;
897*9880d681SAndroid Build Coastguard Worker   if (!Attrs.pImpl) return *this;
898*9880d681SAndroid Build Coastguard Worker 
899*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
900*9880d681SAndroid Build Coastguard Worker   // FIXME it is not obvious how this should work for alignment. For now, say
901*9880d681SAndroid Build Coastguard Worker   // we can't change a known alignment.
902*9880d681SAndroid Build Coastguard Worker   unsigned OldAlign = getParamAlignment(Index);
903*9880d681SAndroid Build Coastguard Worker   unsigned NewAlign = Attrs.getParamAlignment(Index);
904*9880d681SAndroid Build Coastguard Worker   assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
905*9880d681SAndroid Build Coastguard Worker          "Attempt to change alignment!");
906*9880d681SAndroid Build Coastguard Worker #endif
907*9880d681SAndroid Build Coastguard Worker 
908*9880d681SAndroid Build Coastguard Worker   // Add the attribute slots before the one we're trying to add.
909*9880d681SAndroid Build Coastguard Worker   SmallVector<AttributeSet, 4> AttrSet;
910*9880d681SAndroid Build Coastguard Worker   uint64_t NumAttrs = pImpl->getNumSlots();
911*9880d681SAndroid Build Coastguard Worker   AttributeSet AS;
912*9880d681SAndroid Build Coastguard Worker   uint64_t LastIndex = 0;
913*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
914*9880d681SAndroid Build Coastguard Worker     if (getSlotIndex(I) >= Index) {
915*9880d681SAndroid Build Coastguard Worker       if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++);
916*9880d681SAndroid Build Coastguard Worker       break;
917*9880d681SAndroid Build Coastguard Worker     }
918*9880d681SAndroid Build Coastguard Worker     LastIndex = I + 1;
919*9880d681SAndroid Build Coastguard Worker     AttrSet.push_back(getSlotAttributes(I));
920*9880d681SAndroid Build Coastguard Worker   }
921*9880d681SAndroid Build Coastguard Worker 
922*9880d681SAndroid Build Coastguard Worker   // Now add the attribute into the correct slot. There may already be an
923*9880d681SAndroid Build Coastguard Worker   // AttributeSet there.
924*9880d681SAndroid Build Coastguard Worker   AttrBuilder B(AS, Index);
925*9880d681SAndroid Build Coastguard Worker 
926*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = Attrs.pImpl->getNumSlots(); I != E; ++I)
927*9880d681SAndroid Build Coastguard Worker     if (Attrs.getSlotIndex(I) == Index) {
928*9880d681SAndroid Build Coastguard Worker       for (AttributeSetImpl::iterator II = Attrs.pImpl->begin(I),
929*9880d681SAndroid Build Coastguard Worker              IE = Attrs.pImpl->end(I); II != IE; ++II)
930*9880d681SAndroid Build Coastguard Worker         B.addAttribute(*II);
931*9880d681SAndroid Build Coastguard Worker       break;
932*9880d681SAndroid Build Coastguard Worker     }
933*9880d681SAndroid Build Coastguard Worker 
934*9880d681SAndroid Build Coastguard Worker   AttrSet.push_back(AttributeSet::get(C, Index, B));
935*9880d681SAndroid Build Coastguard Worker 
936*9880d681SAndroid Build Coastguard Worker   // Add the remaining attribute slots.
937*9880d681SAndroid Build Coastguard Worker   for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
938*9880d681SAndroid Build Coastguard Worker     AttrSet.push_back(getSlotAttributes(I));
939*9880d681SAndroid Build Coastguard Worker 
940*9880d681SAndroid Build Coastguard Worker   return get(C, AttrSet);
941*9880d681SAndroid Build Coastguard Worker }
942*9880d681SAndroid Build Coastguard Worker 
removeAttribute(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const943*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Index,
944*9880d681SAndroid Build Coastguard Worker                                            Attribute::AttrKind Kind) const {
945*9880d681SAndroid Build Coastguard Worker   if (!hasAttribute(Index, Kind)) return *this;
946*9880d681SAndroid Build Coastguard Worker   return removeAttributes(C, Index, AttributeSet::get(C, Index, Kind));
947*9880d681SAndroid Build Coastguard Worker }
948*9880d681SAndroid Build Coastguard Worker 
removeAttribute(LLVMContext & C,unsigned Index,StringRef Kind) const949*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Index,
950*9880d681SAndroid Build Coastguard Worker                                            StringRef Kind) const {
951*9880d681SAndroid Build Coastguard Worker   if (!hasAttribute(Index, Kind)) return *this;
952*9880d681SAndroid Build Coastguard Worker   return removeAttributes(C, Index, AttributeSet::get(C, Index, Kind));
953*9880d681SAndroid Build Coastguard Worker }
954*9880d681SAndroid Build Coastguard Worker 
removeAttributes(LLVMContext & C,unsigned Index,AttributeSet Attrs) const955*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
956*9880d681SAndroid Build Coastguard Worker                                             AttributeSet Attrs) const {
957*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return AttributeSet();
958*9880d681SAndroid Build Coastguard Worker   if (!Attrs.pImpl) return *this;
959*9880d681SAndroid Build Coastguard Worker 
960*9880d681SAndroid Build Coastguard Worker   // FIXME it is not obvious how this should work for alignment.
961*9880d681SAndroid Build Coastguard Worker   // For now, say we can't pass in alignment, which no current use does.
962*9880d681SAndroid Build Coastguard Worker   assert(!Attrs.hasAttribute(Index, Attribute::Alignment) &&
963*9880d681SAndroid Build Coastguard Worker          "Attempt to change alignment!");
964*9880d681SAndroid Build Coastguard Worker 
965*9880d681SAndroid Build Coastguard Worker   // Add the attribute slots before the one we're trying to add.
966*9880d681SAndroid Build Coastguard Worker   SmallVector<AttributeSet, 4> AttrSet;
967*9880d681SAndroid Build Coastguard Worker   uint64_t NumAttrs = pImpl->getNumSlots();
968*9880d681SAndroid Build Coastguard Worker   AttributeSet AS;
969*9880d681SAndroid Build Coastguard Worker   uint64_t LastIndex = 0;
970*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
971*9880d681SAndroid Build Coastguard Worker     if (getSlotIndex(I) >= Index) {
972*9880d681SAndroid Build Coastguard Worker       if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++);
973*9880d681SAndroid Build Coastguard Worker       break;
974*9880d681SAndroid Build Coastguard Worker     }
975*9880d681SAndroid Build Coastguard Worker     LastIndex = I + 1;
976*9880d681SAndroid Build Coastguard Worker     AttrSet.push_back(getSlotAttributes(I));
977*9880d681SAndroid Build Coastguard Worker   }
978*9880d681SAndroid Build Coastguard Worker 
979*9880d681SAndroid Build Coastguard Worker   // Now remove the attribute from the correct slot. There may already be an
980*9880d681SAndroid Build Coastguard Worker   // AttributeSet there.
981*9880d681SAndroid Build Coastguard Worker   AttrBuilder B(AS, Index);
982*9880d681SAndroid Build Coastguard Worker 
983*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = Attrs.pImpl->getNumSlots(); I != E; ++I)
984*9880d681SAndroid Build Coastguard Worker     if (Attrs.getSlotIndex(I) == Index) {
985*9880d681SAndroid Build Coastguard Worker       B.removeAttributes(Attrs.pImpl->getSlotAttributes(I), Index);
986*9880d681SAndroid Build Coastguard Worker       break;
987*9880d681SAndroid Build Coastguard Worker     }
988*9880d681SAndroid Build Coastguard Worker 
989*9880d681SAndroid Build Coastguard Worker   AttrSet.push_back(AttributeSet::get(C, Index, B));
990*9880d681SAndroid Build Coastguard Worker 
991*9880d681SAndroid Build Coastguard Worker   // Add the remaining attribute slots.
992*9880d681SAndroid Build Coastguard Worker   for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
993*9880d681SAndroid Build Coastguard Worker     AttrSet.push_back(getSlotAttributes(I));
994*9880d681SAndroid Build Coastguard Worker 
995*9880d681SAndroid Build Coastguard Worker   return get(C, AttrSet);
996*9880d681SAndroid Build Coastguard Worker }
997*9880d681SAndroid Build Coastguard Worker 
removeAttributes(LLVMContext & C,unsigned Index,const AttrBuilder & Attrs) const998*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
999*9880d681SAndroid Build Coastguard Worker                                             const AttrBuilder &Attrs) const {
1000*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return AttributeSet();
1001*9880d681SAndroid Build Coastguard Worker 
1002*9880d681SAndroid Build Coastguard Worker   // FIXME it is not obvious how this should work for alignment.
1003*9880d681SAndroid Build Coastguard Worker   // For now, say we can't pass in alignment, which no current use does.
1004*9880d681SAndroid Build Coastguard Worker   assert(!Attrs.hasAlignmentAttr() && "Attempt to change alignment!");
1005*9880d681SAndroid Build Coastguard Worker 
1006*9880d681SAndroid Build Coastguard Worker   // Add the attribute slots before the one we're trying to add.
1007*9880d681SAndroid Build Coastguard Worker   SmallVector<AttributeSet, 4> AttrSet;
1008*9880d681SAndroid Build Coastguard Worker   uint64_t NumAttrs = pImpl->getNumSlots();
1009*9880d681SAndroid Build Coastguard Worker   AttributeSet AS;
1010*9880d681SAndroid Build Coastguard Worker   uint64_t LastIndex = 0;
1011*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
1012*9880d681SAndroid Build Coastguard Worker     if (getSlotIndex(I) >= Index) {
1013*9880d681SAndroid Build Coastguard Worker       if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++);
1014*9880d681SAndroid Build Coastguard Worker       break;
1015*9880d681SAndroid Build Coastguard Worker     }
1016*9880d681SAndroid Build Coastguard Worker     LastIndex = I + 1;
1017*9880d681SAndroid Build Coastguard Worker     AttrSet.push_back(getSlotAttributes(I));
1018*9880d681SAndroid Build Coastguard Worker   }
1019*9880d681SAndroid Build Coastguard Worker 
1020*9880d681SAndroid Build Coastguard Worker   // Now remove the attribute from the correct slot. There may already be an
1021*9880d681SAndroid Build Coastguard Worker   // AttributeSet there.
1022*9880d681SAndroid Build Coastguard Worker   AttrBuilder B(AS, Index);
1023*9880d681SAndroid Build Coastguard Worker   B.remove(Attrs);
1024*9880d681SAndroid Build Coastguard Worker 
1025*9880d681SAndroid Build Coastguard Worker   AttrSet.push_back(AttributeSet::get(C, Index, B));
1026*9880d681SAndroid Build Coastguard Worker 
1027*9880d681SAndroid Build Coastguard Worker   // Add the remaining attribute slots.
1028*9880d681SAndroid Build Coastguard Worker   for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
1029*9880d681SAndroid Build Coastguard Worker     AttrSet.push_back(getSlotAttributes(I));
1030*9880d681SAndroid Build Coastguard Worker 
1031*9880d681SAndroid Build Coastguard Worker   return get(C, AttrSet);
1032*9880d681SAndroid Build Coastguard Worker }
1033*9880d681SAndroid Build Coastguard Worker 
addDereferenceableAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1034*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::addDereferenceableAttr(LLVMContext &C, unsigned Index,
1035*9880d681SAndroid Build Coastguard Worker                                                   uint64_t Bytes) const {
1036*9880d681SAndroid Build Coastguard Worker   llvm::AttrBuilder B;
1037*9880d681SAndroid Build Coastguard Worker   B.addDereferenceableAttr(Bytes);
1038*9880d681SAndroid Build Coastguard Worker   return addAttributes(C, Index, AttributeSet::get(C, Index, B));
1039*9880d681SAndroid Build Coastguard Worker }
1040*9880d681SAndroid Build Coastguard Worker 
addDereferenceableOrNullAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1041*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::addDereferenceableOrNullAttr(LLVMContext &C,
1042*9880d681SAndroid Build Coastguard Worker                                                         unsigned Index,
1043*9880d681SAndroid Build Coastguard Worker                                                         uint64_t Bytes) const {
1044*9880d681SAndroid Build Coastguard Worker   llvm::AttrBuilder B;
1045*9880d681SAndroid Build Coastguard Worker   B.addDereferenceableOrNullAttr(Bytes);
1046*9880d681SAndroid Build Coastguard Worker   return addAttributes(C, Index, AttributeSet::get(C, Index, B));
1047*9880d681SAndroid Build Coastguard Worker }
1048*9880d681SAndroid Build Coastguard Worker 
1049*9880d681SAndroid Build Coastguard Worker AttributeSet
addAllocSizeAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)1050*9880d681SAndroid Build Coastguard Worker AttributeSet::addAllocSizeAttr(LLVMContext &C, unsigned Index,
1051*9880d681SAndroid Build Coastguard Worker                                unsigned ElemSizeArg,
1052*9880d681SAndroid Build Coastguard Worker                                const Optional<unsigned> &NumElemsArg) {
1053*9880d681SAndroid Build Coastguard Worker   llvm::AttrBuilder B;
1054*9880d681SAndroid Build Coastguard Worker   B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1055*9880d681SAndroid Build Coastguard Worker   return addAttributes(C, Index, AttributeSet::get(C, Index, B));
1056*9880d681SAndroid Build Coastguard Worker }
1057*9880d681SAndroid Build Coastguard Worker 
1058*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1059*9880d681SAndroid Build Coastguard Worker // AttributeSet Accessor Methods
1060*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1061*9880d681SAndroid Build Coastguard Worker 
getContext() const1062*9880d681SAndroid Build Coastguard Worker LLVMContext &AttributeSet::getContext() const {
1063*9880d681SAndroid Build Coastguard Worker   return pImpl->getContext();
1064*9880d681SAndroid Build Coastguard Worker }
1065*9880d681SAndroid Build Coastguard Worker 
getParamAttributes(unsigned Index) const1066*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::getParamAttributes(unsigned Index) const {
1067*9880d681SAndroid Build Coastguard Worker   return pImpl && hasAttributes(Index) ?
1068*9880d681SAndroid Build Coastguard Worker     AttributeSet::get(pImpl->getContext(),
1069*9880d681SAndroid Build Coastguard Worker                       ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
1070*9880d681SAndroid Build Coastguard Worker                         std::make_pair(Index, getAttributes(Index)))) :
1071*9880d681SAndroid Build Coastguard Worker     AttributeSet();
1072*9880d681SAndroid Build Coastguard Worker }
1073*9880d681SAndroid Build Coastguard Worker 
getRetAttributes() const1074*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::getRetAttributes() const {
1075*9880d681SAndroid Build Coastguard Worker   return pImpl && hasAttributes(ReturnIndex) ?
1076*9880d681SAndroid Build Coastguard Worker     AttributeSet::get(pImpl->getContext(),
1077*9880d681SAndroid Build Coastguard Worker                       ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
1078*9880d681SAndroid Build Coastguard Worker                         std::make_pair(ReturnIndex,
1079*9880d681SAndroid Build Coastguard Worker                                        getAttributes(ReturnIndex)))) :
1080*9880d681SAndroid Build Coastguard Worker     AttributeSet();
1081*9880d681SAndroid Build Coastguard Worker }
1082*9880d681SAndroid Build Coastguard Worker 
getFnAttributes() const1083*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::getFnAttributes() const {
1084*9880d681SAndroid Build Coastguard Worker   return pImpl && hasAttributes(FunctionIndex) ?
1085*9880d681SAndroid Build Coastguard Worker     AttributeSet::get(pImpl->getContext(),
1086*9880d681SAndroid Build Coastguard Worker                       ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
1087*9880d681SAndroid Build Coastguard Worker                         std::make_pair(FunctionIndex,
1088*9880d681SAndroid Build Coastguard Worker                                        getAttributes(FunctionIndex)))) :
1089*9880d681SAndroid Build Coastguard Worker     AttributeSet();
1090*9880d681SAndroid Build Coastguard Worker }
1091*9880d681SAndroid Build Coastguard Worker 
hasAttribute(unsigned Index,Attribute::AttrKind Kind) const1092*9880d681SAndroid Build Coastguard Worker bool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{
1093*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1094*9880d681SAndroid Build Coastguard Worker   return ASN && ASN->hasAttribute(Kind);
1095*9880d681SAndroid Build Coastguard Worker }
1096*9880d681SAndroid Build Coastguard Worker 
hasAttribute(unsigned Index,StringRef Kind) const1097*9880d681SAndroid Build Coastguard Worker bool AttributeSet::hasAttribute(unsigned Index, StringRef Kind) const {
1098*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1099*9880d681SAndroid Build Coastguard Worker   return ASN && ASN->hasAttribute(Kind);
1100*9880d681SAndroid Build Coastguard Worker }
1101*9880d681SAndroid Build Coastguard Worker 
hasAttributes(unsigned Index) const1102*9880d681SAndroid Build Coastguard Worker bool AttributeSet::hasAttributes(unsigned Index) const {
1103*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1104*9880d681SAndroid Build Coastguard Worker   return ASN && ASN->hasAttributes();
1105*9880d681SAndroid Build Coastguard Worker }
1106*9880d681SAndroid Build Coastguard Worker 
hasFnAttribute(Attribute::AttrKind Kind) const1107*9880d681SAndroid Build Coastguard Worker bool AttributeSet::hasFnAttribute(Attribute::AttrKind Kind) const {
1108*9880d681SAndroid Build Coastguard Worker   return pImpl && pImpl->hasFnAttribute(Kind);
1109*9880d681SAndroid Build Coastguard Worker }
1110*9880d681SAndroid Build Coastguard Worker 
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1111*9880d681SAndroid Build Coastguard Worker bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr,
1112*9880d681SAndroid Build Coastguard Worker                                     unsigned *Index) const {
1113*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return false;
1114*9880d681SAndroid Build Coastguard Worker 
1115*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I)
1116*9880d681SAndroid Build Coastguard Worker     for (AttributeSetImpl::iterator II = pImpl->begin(I),
1117*9880d681SAndroid Build Coastguard Worker            IE = pImpl->end(I); II != IE; ++II)
1118*9880d681SAndroid Build Coastguard Worker       if (II->hasAttribute(Attr)) {
1119*9880d681SAndroid Build Coastguard Worker         if (Index) *Index = pImpl->getSlotIndex(I);
1120*9880d681SAndroid Build Coastguard Worker         return true;
1121*9880d681SAndroid Build Coastguard Worker       }
1122*9880d681SAndroid Build Coastguard Worker 
1123*9880d681SAndroid Build Coastguard Worker   return false;
1124*9880d681SAndroid Build Coastguard Worker }
1125*9880d681SAndroid Build Coastguard Worker 
getAttribute(unsigned Index,Attribute::AttrKind Kind) const1126*9880d681SAndroid Build Coastguard Worker Attribute AttributeSet::getAttribute(unsigned Index,
1127*9880d681SAndroid Build Coastguard Worker                                      Attribute::AttrKind Kind) const {
1128*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1129*9880d681SAndroid Build Coastguard Worker   return ASN ? ASN->getAttribute(Kind) : Attribute();
1130*9880d681SAndroid Build Coastguard Worker }
1131*9880d681SAndroid Build Coastguard Worker 
getAttribute(unsigned Index,StringRef Kind) const1132*9880d681SAndroid Build Coastguard Worker Attribute AttributeSet::getAttribute(unsigned Index,
1133*9880d681SAndroid Build Coastguard Worker                                      StringRef Kind) const {
1134*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1135*9880d681SAndroid Build Coastguard Worker   return ASN ? ASN->getAttribute(Kind) : Attribute();
1136*9880d681SAndroid Build Coastguard Worker }
1137*9880d681SAndroid Build Coastguard Worker 
getParamAlignment(unsigned Index) const1138*9880d681SAndroid Build Coastguard Worker unsigned AttributeSet::getParamAlignment(unsigned Index) const {
1139*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1140*9880d681SAndroid Build Coastguard Worker   return ASN ? ASN->getAlignment() : 0;
1141*9880d681SAndroid Build Coastguard Worker }
1142*9880d681SAndroid Build Coastguard Worker 
getStackAlignment(unsigned Index) const1143*9880d681SAndroid Build Coastguard Worker unsigned AttributeSet::getStackAlignment(unsigned Index) const {
1144*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1145*9880d681SAndroid Build Coastguard Worker   return ASN ? ASN->getStackAlignment() : 0;
1146*9880d681SAndroid Build Coastguard Worker }
1147*9880d681SAndroid Build Coastguard Worker 
getDereferenceableBytes(unsigned Index) const1148*9880d681SAndroid Build Coastguard Worker uint64_t AttributeSet::getDereferenceableBytes(unsigned Index) const {
1149*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1150*9880d681SAndroid Build Coastguard Worker   return ASN ? ASN->getDereferenceableBytes() : 0;
1151*9880d681SAndroid Build Coastguard Worker }
1152*9880d681SAndroid Build Coastguard Worker 
getDereferenceableOrNullBytes(unsigned Index) const1153*9880d681SAndroid Build Coastguard Worker uint64_t AttributeSet::getDereferenceableOrNullBytes(unsigned Index) const {
1154*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1155*9880d681SAndroid Build Coastguard Worker   return ASN ? ASN->getDereferenceableOrNullBytes() : 0;
1156*9880d681SAndroid Build Coastguard Worker }
1157*9880d681SAndroid Build Coastguard Worker 
1158*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs(unsigned Index) const1159*9880d681SAndroid Build Coastguard Worker AttributeSet::getAllocSizeArgs(unsigned Index) const {
1160*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1161*9880d681SAndroid Build Coastguard Worker   return ASN ? ASN->getAllocSizeArgs() : std::make_pair(0, 0);
1162*9880d681SAndroid Build Coastguard Worker }
1163*9880d681SAndroid Build Coastguard Worker 
getAsString(unsigned Index,bool InAttrGrp) const1164*9880d681SAndroid Build Coastguard Worker std::string AttributeSet::getAsString(unsigned Index, bool InAttrGrp) const {
1165*9880d681SAndroid Build Coastguard Worker   AttributeSetNode *ASN = getAttributes(Index);
1166*9880d681SAndroid Build Coastguard Worker   return ASN ? ASN->getAsString(InAttrGrp) : std::string("");
1167*9880d681SAndroid Build Coastguard Worker }
1168*9880d681SAndroid Build Coastguard Worker 
getAttributes(unsigned Index) const1169*9880d681SAndroid Build Coastguard Worker AttributeSetNode *AttributeSet::getAttributes(unsigned Index) const {
1170*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return nullptr;
1171*9880d681SAndroid Build Coastguard Worker 
1172*9880d681SAndroid Build Coastguard Worker   // Loop through to find the attribute node we want.
1173*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I)
1174*9880d681SAndroid Build Coastguard Worker     if (pImpl->getSlotIndex(I) == Index)
1175*9880d681SAndroid Build Coastguard Worker       return pImpl->getSlotNode(I);
1176*9880d681SAndroid Build Coastguard Worker 
1177*9880d681SAndroid Build Coastguard Worker   return nullptr;
1178*9880d681SAndroid Build Coastguard Worker }
1179*9880d681SAndroid Build Coastguard Worker 
begin(unsigned Slot) const1180*9880d681SAndroid Build Coastguard Worker AttributeSet::iterator AttributeSet::begin(unsigned Slot) const {
1181*9880d681SAndroid Build Coastguard Worker   if (!pImpl)
1182*9880d681SAndroid Build Coastguard Worker     return ArrayRef<Attribute>().begin();
1183*9880d681SAndroid Build Coastguard Worker   return pImpl->begin(Slot);
1184*9880d681SAndroid Build Coastguard Worker }
1185*9880d681SAndroid Build Coastguard Worker 
end(unsigned Slot) const1186*9880d681SAndroid Build Coastguard Worker AttributeSet::iterator AttributeSet::end(unsigned Slot) const {
1187*9880d681SAndroid Build Coastguard Worker   if (!pImpl)
1188*9880d681SAndroid Build Coastguard Worker     return ArrayRef<Attribute>().end();
1189*9880d681SAndroid Build Coastguard Worker   return pImpl->end(Slot);
1190*9880d681SAndroid Build Coastguard Worker }
1191*9880d681SAndroid Build Coastguard Worker 
1192*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1193*9880d681SAndroid Build Coastguard Worker // AttributeSet Introspection Methods
1194*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1195*9880d681SAndroid Build Coastguard Worker 
getNumSlots() const1196*9880d681SAndroid Build Coastguard Worker unsigned AttributeSet::getNumSlots() const {
1197*9880d681SAndroid Build Coastguard Worker   return pImpl ? pImpl->getNumSlots() : 0;
1198*9880d681SAndroid Build Coastguard Worker }
1199*9880d681SAndroid Build Coastguard Worker 
getSlotIndex(unsigned Slot) const1200*9880d681SAndroid Build Coastguard Worker unsigned AttributeSet::getSlotIndex(unsigned Slot) const {
1201*9880d681SAndroid Build Coastguard Worker   assert(pImpl && Slot < pImpl->getNumSlots() &&
1202*9880d681SAndroid Build Coastguard Worker          "Slot # out of range!");
1203*9880d681SAndroid Build Coastguard Worker   return pImpl->getSlotIndex(Slot);
1204*9880d681SAndroid Build Coastguard Worker }
1205*9880d681SAndroid Build Coastguard Worker 
getSlotAttributes(unsigned Slot) const1206*9880d681SAndroid Build Coastguard Worker AttributeSet AttributeSet::getSlotAttributes(unsigned Slot) const {
1207*9880d681SAndroid Build Coastguard Worker   assert(pImpl && Slot < pImpl->getNumSlots() &&
1208*9880d681SAndroid Build Coastguard Worker          "Slot # out of range!");
1209*9880d681SAndroid Build Coastguard Worker   return pImpl->getSlotAttributes(Slot);
1210*9880d681SAndroid Build Coastguard Worker }
1211*9880d681SAndroid Build Coastguard Worker 
Raw(unsigned Index) const1212*9880d681SAndroid Build Coastguard Worker uint64_t AttributeSet::Raw(unsigned Index) const {
1213*9880d681SAndroid Build Coastguard Worker   // FIXME: Remove this.
1214*9880d681SAndroid Build Coastguard Worker   return pImpl ? pImpl->Raw(Index) : 0;
1215*9880d681SAndroid Build Coastguard Worker }
1216*9880d681SAndroid Build Coastguard Worker 
dump() const1217*9880d681SAndroid Build Coastguard Worker LLVM_DUMP_METHOD void AttributeSet::dump() const {
1218*9880d681SAndroid Build Coastguard Worker   dbgs() << "PAL[\n";
1219*9880d681SAndroid Build Coastguard Worker 
1220*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = getNumSlots(); i < e; ++i) {
1221*9880d681SAndroid Build Coastguard Worker     uint64_t Index = getSlotIndex(i);
1222*9880d681SAndroid Build Coastguard Worker     dbgs() << "  { ";
1223*9880d681SAndroid Build Coastguard Worker     if (Index == ~0U)
1224*9880d681SAndroid Build Coastguard Worker       dbgs() << "~0U";
1225*9880d681SAndroid Build Coastguard Worker     else
1226*9880d681SAndroid Build Coastguard Worker       dbgs() << Index;
1227*9880d681SAndroid Build Coastguard Worker     dbgs() << " => " << getAsString(Index) << " }\n";
1228*9880d681SAndroid Build Coastguard Worker   }
1229*9880d681SAndroid Build Coastguard Worker 
1230*9880d681SAndroid Build Coastguard Worker   dbgs() << "]\n";
1231*9880d681SAndroid Build Coastguard Worker }
1232*9880d681SAndroid Build Coastguard Worker 
1233*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1234*9880d681SAndroid Build Coastguard Worker // AttrBuilder Method Implementations
1235*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1236*9880d681SAndroid Build Coastguard Worker 
AttrBuilder(AttributeSet AS,unsigned Index)1237*9880d681SAndroid Build Coastguard Worker AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)
1238*9880d681SAndroid Build Coastguard Worker     : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
1239*9880d681SAndroid Build Coastguard Worker       DerefOrNullBytes(0), AllocSizeArgs(0) {
1240*9880d681SAndroid Build Coastguard Worker   AttributeSetImpl *pImpl = AS.pImpl;
1241*9880d681SAndroid Build Coastguard Worker   if (!pImpl) return;
1242*9880d681SAndroid Build Coastguard Worker 
1243*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I) {
1244*9880d681SAndroid Build Coastguard Worker     if (pImpl->getSlotIndex(I) != Index) continue;
1245*9880d681SAndroid Build Coastguard Worker 
1246*9880d681SAndroid Build Coastguard Worker     for (AttributeSetImpl::iterator II = pImpl->begin(I),
1247*9880d681SAndroid Build Coastguard Worker            IE = pImpl->end(I); II != IE; ++II)
1248*9880d681SAndroid Build Coastguard Worker       addAttribute(*II);
1249*9880d681SAndroid Build Coastguard Worker 
1250*9880d681SAndroid Build Coastguard Worker     break;
1251*9880d681SAndroid Build Coastguard Worker   }
1252*9880d681SAndroid Build Coastguard Worker }
1253*9880d681SAndroid Build Coastguard Worker 
clear()1254*9880d681SAndroid Build Coastguard Worker void AttrBuilder::clear() {
1255*9880d681SAndroid Build Coastguard Worker   Attrs.reset();
1256*9880d681SAndroid Build Coastguard Worker   TargetDepAttrs.clear();
1257*9880d681SAndroid Build Coastguard Worker   Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
1258*9880d681SAndroid Build Coastguard Worker   AllocSizeArgs = 0;
1259*9880d681SAndroid Build Coastguard Worker }
1260*9880d681SAndroid Build Coastguard Worker 
addAttribute(Attribute::AttrKind Val)1261*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
1262*9880d681SAndroid Build Coastguard Worker   assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1263*9880d681SAndroid Build Coastguard Worker   assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment &&
1264*9880d681SAndroid Build Coastguard Worker          Val != Attribute::Dereferenceable && Val != Attribute::AllocSize &&
1265*9880d681SAndroid Build Coastguard Worker          "Adding integer attribute without adding a value!");
1266*9880d681SAndroid Build Coastguard Worker   Attrs[Val] = true;
1267*9880d681SAndroid Build Coastguard Worker   return *this;
1268*9880d681SAndroid Build Coastguard Worker }
1269*9880d681SAndroid Build Coastguard Worker 
addAttribute(Attribute Attr)1270*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1271*9880d681SAndroid Build Coastguard Worker   if (Attr.isStringAttribute()) {
1272*9880d681SAndroid Build Coastguard Worker     addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
1273*9880d681SAndroid Build Coastguard Worker     return *this;
1274*9880d681SAndroid Build Coastguard Worker   }
1275*9880d681SAndroid Build Coastguard Worker 
1276*9880d681SAndroid Build Coastguard Worker   Attribute::AttrKind Kind = Attr.getKindAsEnum();
1277*9880d681SAndroid Build Coastguard Worker   Attrs[Kind] = true;
1278*9880d681SAndroid Build Coastguard Worker 
1279*9880d681SAndroid Build Coastguard Worker   if (Kind == Attribute::Alignment)
1280*9880d681SAndroid Build Coastguard Worker     Alignment = Attr.getAlignment();
1281*9880d681SAndroid Build Coastguard Worker   else if (Kind == Attribute::StackAlignment)
1282*9880d681SAndroid Build Coastguard Worker     StackAlignment = Attr.getStackAlignment();
1283*9880d681SAndroid Build Coastguard Worker   else if (Kind == Attribute::Dereferenceable)
1284*9880d681SAndroid Build Coastguard Worker     DerefBytes = Attr.getDereferenceableBytes();
1285*9880d681SAndroid Build Coastguard Worker   else if (Kind == Attribute::DereferenceableOrNull)
1286*9880d681SAndroid Build Coastguard Worker     DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
1287*9880d681SAndroid Build Coastguard Worker   else if (Kind == Attribute::AllocSize)
1288*9880d681SAndroid Build Coastguard Worker     AllocSizeArgs = Attr.getValueAsInt();
1289*9880d681SAndroid Build Coastguard Worker   return *this;
1290*9880d681SAndroid Build Coastguard Worker }
1291*9880d681SAndroid Build Coastguard Worker 
addAttribute(StringRef A,StringRef V)1292*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1293*9880d681SAndroid Build Coastguard Worker   TargetDepAttrs[A] = V;
1294*9880d681SAndroid Build Coastguard Worker   return *this;
1295*9880d681SAndroid Build Coastguard Worker }
1296*9880d681SAndroid Build Coastguard Worker 
removeAttribute(Attribute::AttrKind Val)1297*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1298*9880d681SAndroid Build Coastguard Worker   assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1299*9880d681SAndroid Build Coastguard Worker   Attrs[Val] = false;
1300*9880d681SAndroid Build Coastguard Worker 
1301*9880d681SAndroid Build Coastguard Worker   if (Val == Attribute::Alignment)
1302*9880d681SAndroid Build Coastguard Worker     Alignment = 0;
1303*9880d681SAndroid Build Coastguard Worker   else if (Val == Attribute::StackAlignment)
1304*9880d681SAndroid Build Coastguard Worker     StackAlignment = 0;
1305*9880d681SAndroid Build Coastguard Worker   else if (Val == Attribute::Dereferenceable)
1306*9880d681SAndroid Build Coastguard Worker     DerefBytes = 0;
1307*9880d681SAndroid Build Coastguard Worker   else if (Val == Attribute::DereferenceableOrNull)
1308*9880d681SAndroid Build Coastguard Worker     DerefOrNullBytes = 0;
1309*9880d681SAndroid Build Coastguard Worker   else if (Val == Attribute::AllocSize)
1310*9880d681SAndroid Build Coastguard Worker     AllocSizeArgs = 0;
1311*9880d681SAndroid Build Coastguard Worker 
1312*9880d681SAndroid Build Coastguard Worker   return *this;
1313*9880d681SAndroid Build Coastguard Worker }
1314*9880d681SAndroid Build Coastguard Worker 
removeAttributes(AttributeSet A,uint64_t Index)1315*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {
1316*9880d681SAndroid Build Coastguard Worker   unsigned Slot = ~0U;
1317*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I)
1318*9880d681SAndroid Build Coastguard Worker     if (A.getSlotIndex(I) == Index) {
1319*9880d681SAndroid Build Coastguard Worker       Slot = I;
1320*9880d681SAndroid Build Coastguard Worker       break;
1321*9880d681SAndroid Build Coastguard Worker     }
1322*9880d681SAndroid Build Coastguard Worker 
1323*9880d681SAndroid Build Coastguard Worker   assert(Slot != ~0U && "Couldn't find index in AttributeSet!");
1324*9880d681SAndroid Build Coastguard Worker 
1325*9880d681SAndroid Build Coastguard Worker   for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) {
1326*9880d681SAndroid Build Coastguard Worker     Attribute Attr = *I;
1327*9880d681SAndroid Build Coastguard Worker     if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
1328*9880d681SAndroid Build Coastguard Worker       removeAttribute(Attr.getKindAsEnum());
1329*9880d681SAndroid Build Coastguard Worker     } else {
1330*9880d681SAndroid Build Coastguard Worker       assert(Attr.isStringAttribute() && "Invalid attribute type!");
1331*9880d681SAndroid Build Coastguard Worker       removeAttribute(Attr.getKindAsString());
1332*9880d681SAndroid Build Coastguard Worker     }
1333*9880d681SAndroid Build Coastguard Worker   }
1334*9880d681SAndroid Build Coastguard Worker 
1335*9880d681SAndroid Build Coastguard Worker   return *this;
1336*9880d681SAndroid Build Coastguard Worker }
1337*9880d681SAndroid Build Coastguard Worker 
removeAttribute(StringRef A)1338*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1339*9880d681SAndroid Build Coastguard Worker   std::map<std::string, std::string>::iterator I = TargetDepAttrs.find(A);
1340*9880d681SAndroid Build Coastguard Worker   if (I != TargetDepAttrs.end())
1341*9880d681SAndroid Build Coastguard Worker     TargetDepAttrs.erase(I);
1342*9880d681SAndroid Build Coastguard Worker   return *this;
1343*9880d681SAndroid Build Coastguard Worker }
1344*9880d681SAndroid Build Coastguard Worker 
getAllocSizeArgs() const1345*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
1346*9880d681SAndroid Build Coastguard Worker   return unpackAllocSizeArgs(AllocSizeArgs);
1347*9880d681SAndroid Build Coastguard Worker }
1348*9880d681SAndroid Build Coastguard Worker 
addAlignmentAttr(unsigned Align)1349*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
1350*9880d681SAndroid Build Coastguard Worker   if (Align == 0) return *this;
1351*9880d681SAndroid Build Coastguard Worker 
1352*9880d681SAndroid Build Coastguard Worker   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
1353*9880d681SAndroid Build Coastguard Worker   assert(Align <= 0x40000000 && "Alignment too large.");
1354*9880d681SAndroid Build Coastguard Worker 
1355*9880d681SAndroid Build Coastguard Worker   Attrs[Attribute::Alignment] = true;
1356*9880d681SAndroid Build Coastguard Worker   Alignment = Align;
1357*9880d681SAndroid Build Coastguard Worker   return *this;
1358*9880d681SAndroid Build Coastguard Worker }
1359*9880d681SAndroid Build Coastguard Worker 
addStackAlignmentAttr(unsigned Align)1360*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) {
1361*9880d681SAndroid Build Coastguard Worker   // Default alignment, allow the target to define how to align it.
1362*9880d681SAndroid Build Coastguard Worker   if (Align == 0) return *this;
1363*9880d681SAndroid Build Coastguard Worker 
1364*9880d681SAndroid Build Coastguard Worker   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
1365*9880d681SAndroid Build Coastguard Worker   assert(Align <= 0x100 && "Alignment too large.");
1366*9880d681SAndroid Build Coastguard Worker 
1367*9880d681SAndroid Build Coastguard Worker   Attrs[Attribute::StackAlignment] = true;
1368*9880d681SAndroid Build Coastguard Worker   StackAlignment = Align;
1369*9880d681SAndroid Build Coastguard Worker   return *this;
1370*9880d681SAndroid Build Coastguard Worker }
1371*9880d681SAndroid Build Coastguard Worker 
addDereferenceableAttr(uint64_t Bytes)1372*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1373*9880d681SAndroid Build Coastguard Worker   if (Bytes == 0) return *this;
1374*9880d681SAndroid Build Coastguard Worker 
1375*9880d681SAndroid Build Coastguard Worker   Attrs[Attribute::Dereferenceable] = true;
1376*9880d681SAndroid Build Coastguard Worker   DerefBytes = Bytes;
1377*9880d681SAndroid Build Coastguard Worker   return *this;
1378*9880d681SAndroid Build Coastguard Worker }
1379*9880d681SAndroid Build Coastguard Worker 
addDereferenceableOrNullAttr(uint64_t Bytes)1380*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1381*9880d681SAndroid Build Coastguard Worker   if (Bytes == 0)
1382*9880d681SAndroid Build Coastguard Worker     return *this;
1383*9880d681SAndroid Build Coastguard Worker 
1384*9880d681SAndroid Build Coastguard Worker   Attrs[Attribute::DereferenceableOrNull] = true;
1385*9880d681SAndroid Build Coastguard Worker   DerefOrNullBytes = Bytes;
1386*9880d681SAndroid Build Coastguard Worker   return *this;
1387*9880d681SAndroid Build Coastguard Worker }
1388*9880d681SAndroid Build Coastguard Worker 
addAllocSizeAttr(unsigned ElemSize,const Optional<unsigned> & NumElems)1389*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1390*9880d681SAndroid Build Coastguard Worker                                            const Optional<unsigned> &NumElems) {
1391*9880d681SAndroid Build Coastguard Worker   return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1392*9880d681SAndroid Build Coastguard Worker }
1393*9880d681SAndroid Build Coastguard Worker 
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1394*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1395*9880d681SAndroid Build Coastguard Worker   // (0, 0) is our "not present" value, so we need to check for it here.
1396*9880d681SAndroid Build Coastguard Worker   assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1397*9880d681SAndroid Build Coastguard Worker 
1398*9880d681SAndroid Build Coastguard Worker   Attrs[Attribute::AllocSize] = true;
1399*9880d681SAndroid Build Coastguard Worker   // Reuse existing machinery to store this as a single 64-bit integer so we can
1400*9880d681SAndroid Build Coastguard Worker   // save a few bytes over using a pair<unsigned, Optional<unsigned>>.
1401*9880d681SAndroid Build Coastguard Worker   AllocSizeArgs = RawArgs;
1402*9880d681SAndroid Build Coastguard Worker   return *this;
1403*9880d681SAndroid Build Coastguard Worker }
1404*9880d681SAndroid Build Coastguard Worker 
merge(const AttrBuilder & B)1405*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1406*9880d681SAndroid Build Coastguard Worker   // FIXME: What if both have alignments, but they don't match?!
1407*9880d681SAndroid Build Coastguard Worker   if (!Alignment)
1408*9880d681SAndroid Build Coastguard Worker     Alignment = B.Alignment;
1409*9880d681SAndroid Build Coastguard Worker 
1410*9880d681SAndroid Build Coastguard Worker   if (!StackAlignment)
1411*9880d681SAndroid Build Coastguard Worker     StackAlignment = B.StackAlignment;
1412*9880d681SAndroid Build Coastguard Worker 
1413*9880d681SAndroid Build Coastguard Worker   if (!DerefBytes)
1414*9880d681SAndroid Build Coastguard Worker     DerefBytes = B.DerefBytes;
1415*9880d681SAndroid Build Coastguard Worker 
1416*9880d681SAndroid Build Coastguard Worker   if (!DerefOrNullBytes)
1417*9880d681SAndroid Build Coastguard Worker     DerefOrNullBytes = B.DerefOrNullBytes;
1418*9880d681SAndroid Build Coastguard Worker 
1419*9880d681SAndroid Build Coastguard Worker   if (!AllocSizeArgs)
1420*9880d681SAndroid Build Coastguard Worker     AllocSizeArgs = B.AllocSizeArgs;
1421*9880d681SAndroid Build Coastguard Worker 
1422*9880d681SAndroid Build Coastguard Worker   Attrs |= B.Attrs;
1423*9880d681SAndroid Build Coastguard Worker 
1424*9880d681SAndroid Build Coastguard Worker   for (auto I : B.td_attrs())
1425*9880d681SAndroid Build Coastguard Worker     TargetDepAttrs[I.first] = I.second;
1426*9880d681SAndroid Build Coastguard Worker 
1427*9880d681SAndroid Build Coastguard Worker   return *this;
1428*9880d681SAndroid Build Coastguard Worker }
1429*9880d681SAndroid Build Coastguard Worker 
remove(const AttrBuilder & B)1430*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
1431*9880d681SAndroid Build Coastguard Worker   // FIXME: What if both have alignments, but they don't match?!
1432*9880d681SAndroid Build Coastguard Worker   if (B.Alignment)
1433*9880d681SAndroid Build Coastguard Worker     Alignment = 0;
1434*9880d681SAndroid Build Coastguard Worker 
1435*9880d681SAndroid Build Coastguard Worker   if (B.StackAlignment)
1436*9880d681SAndroid Build Coastguard Worker     StackAlignment = 0;
1437*9880d681SAndroid Build Coastguard Worker 
1438*9880d681SAndroid Build Coastguard Worker   if (B.DerefBytes)
1439*9880d681SAndroid Build Coastguard Worker     DerefBytes = 0;
1440*9880d681SAndroid Build Coastguard Worker 
1441*9880d681SAndroid Build Coastguard Worker   if (B.DerefOrNullBytes)
1442*9880d681SAndroid Build Coastguard Worker     DerefOrNullBytes = 0;
1443*9880d681SAndroid Build Coastguard Worker 
1444*9880d681SAndroid Build Coastguard Worker   if (B.AllocSizeArgs)
1445*9880d681SAndroid Build Coastguard Worker     AllocSizeArgs = 0;
1446*9880d681SAndroid Build Coastguard Worker 
1447*9880d681SAndroid Build Coastguard Worker   Attrs &= ~B.Attrs;
1448*9880d681SAndroid Build Coastguard Worker 
1449*9880d681SAndroid Build Coastguard Worker   for (auto I : B.td_attrs())
1450*9880d681SAndroid Build Coastguard Worker     TargetDepAttrs.erase(I.first);
1451*9880d681SAndroid Build Coastguard Worker 
1452*9880d681SAndroid Build Coastguard Worker   return *this;
1453*9880d681SAndroid Build Coastguard Worker }
1454*9880d681SAndroid Build Coastguard Worker 
overlaps(const AttrBuilder & B) const1455*9880d681SAndroid Build Coastguard Worker bool AttrBuilder::overlaps(const AttrBuilder &B) const {
1456*9880d681SAndroid Build Coastguard Worker   // First check if any of the target independent attributes overlap.
1457*9880d681SAndroid Build Coastguard Worker   if ((Attrs & B.Attrs).any())
1458*9880d681SAndroid Build Coastguard Worker     return true;
1459*9880d681SAndroid Build Coastguard Worker 
1460*9880d681SAndroid Build Coastguard Worker   // Then check if any target dependent ones do.
1461*9880d681SAndroid Build Coastguard Worker   for (auto I : td_attrs())
1462*9880d681SAndroid Build Coastguard Worker     if (B.contains(I.first))
1463*9880d681SAndroid Build Coastguard Worker       return true;
1464*9880d681SAndroid Build Coastguard Worker 
1465*9880d681SAndroid Build Coastguard Worker   return false;
1466*9880d681SAndroid Build Coastguard Worker }
1467*9880d681SAndroid Build Coastguard Worker 
contains(StringRef A) const1468*9880d681SAndroid Build Coastguard Worker bool AttrBuilder::contains(StringRef A) const {
1469*9880d681SAndroid Build Coastguard Worker   return TargetDepAttrs.find(A) != TargetDepAttrs.end();
1470*9880d681SAndroid Build Coastguard Worker }
1471*9880d681SAndroid Build Coastguard Worker 
hasAttributes() const1472*9880d681SAndroid Build Coastguard Worker bool AttrBuilder::hasAttributes() const {
1473*9880d681SAndroid Build Coastguard Worker   return !Attrs.none() || !TargetDepAttrs.empty();
1474*9880d681SAndroid Build Coastguard Worker }
1475*9880d681SAndroid Build Coastguard Worker 
hasAttributes(AttributeSet A,uint64_t Index) const1476*9880d681SAndroid Build Coastguard Worker bool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const {
1477*9880d681SAndroid Build Coastguard Worker   unsigned Slot = ~0U;
1478*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I)
1479*9880d681SAndroid Build Coastguard Worker     if (A.getSlotIndex(I) == Index) {
1480*9880d681SAndroid Build Coastguard Worker       Slot = I;
1481*9880d681SAndroid Build Coastguard Worker       break;
1482*9880d681SAndroid Build Coastguard Worker     }
1483*9880d681SAndroid Build Coastguard Worker 
1484*9880d681SAndroid Build Coastguard Worker   assert(Slot != ~0U && "Couldn't find the index!");
1485*9880d681SAndroid Build Coastguard Worker 
1486*9880d681SAndroid Build Coastguard Worker   for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) {
1487*9880d681SAndroid Build Coastguard Worker     Attribute Attr = *I;
1488*9880d681SAndroid Build Coastguard Worker     if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
1489*9880d681SAndroid Build Coastguard Worker       if (Attrs[I->getKindAsEnum()])
1490*9880d681SAndroid Build Coastguard Worker         return true;
1491*9880d681SAndroid Build Coastguard Worker     } else {
1492*9880d681SAndroid Build Coastguard Worker       assert(Attr.isStringAttribute() && "Invalid attribute kind!");
1493*9880d681SAndroid Build Coastguard Worker       return TargetDepAttrs.find(Attr.getKindAsString())!=TargetDepAttrs.end();
1494*9880d681SAndroid Build Coastguard Worker     }
1495*9880d681SAndroid Build Coastguard Worker   }
1496*9880d681SAndroid Build Coastguard Worker 
1497*9880d681SAndroid Build Coastguard Worker   return false;
1498*9880d681SAndroid Build Coastguard Worker }
1499*9880d681SAndroid Build Coastguard Worker 
hasAlignmentAttr() const1500*9880d681SAndroid Build Coastguard Worker bool AttrBuilder::hasAlignmentAttr() const {
1501*9880d681SAndroid Build Coastguard Worker   return Alignment != 0;
1502*9880d681SAndroid Build Coastguard Worker }
1503*9880d681SAndroid Build Coastguard Worker 
operator ==(const AttrBuilder & B)1504*9880d681SAndroid Build Coastguard Worker bool AttrBuilder::operator==(const AttrBuilder &B) {
1505*9880d681SAndroid Build Coastguard Worker   if (Attrs != B.Attrs)
1506*9880d681SAndroid Build Coastguard Worker     return false;
1507*9880d681SAndroid Build Coastguard Worker 
1508*9880d681SAndroid Build Coastguard Worker   for (td_const_iterator I = TargetDepAttrs.begin(),
1509*9880d681SAndroid Build Coastguard Worker          E = TargetDepAttrs.end(); I != E; ++I)
1510*9880d681SAndroid Build Coastguard Worker     if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())
1511*9880d681SAndroid Build Coastguard Worker       return false;
1512*9880d681SAndroid Build Coastguard Worker 
1513*9880d681SAndroid Build Coastguard Worker   return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
1514*9880d681SAndroid Build Coastguard Worker          DerefBytes == B.DerefBytes;
1515*9880d681SAndroid Build Coastguard Worker }
1516*9880d681SAndroid Build Coastguard Worker 
addRawValue(uint64_t Val)1517*9880d681SAndroid Build Coastguard Worker AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
1518*9880d681SAndroid Build Coastguard Worker   // FIXME: Remove this in 4.0.
1519*9880d681SAndroid Build Coastguard Worker   if (!Val) return *this;
1520*9880d681SAndroid Build Coastguard Worker 
1521*9880d681SAndroid Build Coastguard Worker   for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
1522*9880d681SAndroid Build Coastguard Worker        I = Attribute::AttrKind(I + 1)) {
1523*9880d681SAndroid Build Coastguard Worker     if (I == Attribute::Dereferenceable ||
1524*9880d681SAndroid Build Coastguard Worker         I == Attribute::DereferenceableOrNull ||
1525*9880d681SAndroid Build Coastguard Worker         I == Attribute::ArgMemOnly ||
1526*9880d681SAndroid Build Coastguard Worker         I == Attribute::AllocSize)
1527*9880d681SAndroid Build Coastguard Worker       continue;
1528*9880d681SAndroid Build Coastguard Worker     if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {
1529*9880d681SAndroid Build Coastguard Worker       Attrs[I] = true;
1530*9880d681SAndroid Build Coastguard Worker 
1531*9880d681SAndroid Build Coastguard Worker       if (I == Attribute::Alignment)
1532*9880d681SAndroid Build Coastguard Worker         Alignment = 1ULL << ((A >> 16) - 1);
1533*9880d681SAndroid Build Coastguard Worker       else if (I == Attribute::StackAlignment)
1534*9880d681SAndroid Build Coastguard Worker         StackAlignment = 1ULL << ((A >> 26)-1);
1535*9880d681SAndroid Build Coastguard Worker     }
1536*9880d681SAndroid Build Coastguard Worker   }
1537*9880d681SAndroid Build Coastguard Worker 
1538*9880d681SAndroid Build Coastguard Worker   return *this;
1539*9880d681SAndroid Build Coastguard Worker }
1540*9880d681SAndroid Build Coastguard Worker 
1541*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1542*9880d681SAndroid Build Coastguard Worker // AttributeFuncs Function Defintions
1543*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1544*9880d681SAndroid Build Coastguard Worker 
1545*9880d681SAndroid Build Coastguard Worker /// \brief Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty)1546*9880d681SAndroid Build Coastguard Worker AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
1547*9880d681SAndroid Build Coastguard Worker   AttrBuilder Incompatible;
1548*9880d681SAndroid Build Coastguard Worker 
1549*9880d681SAndroid Build Coastguard Worker   if (!Ty->isIntegerTy())
1550*9880d681SAndroid Build Coastguard Worker     // Attribute that only apply to integers.
1551*9880d681SAndroid Build Coastguard Worker     Incompatible.addAttribute(Attribute::SExt)
1552*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::ZExt);
1553*9880d681SAndroid Build Coastguard Worker 
1554*9880d681SAndroid Build Coastguard Worker   if (!Ty->isPointerTy())
1555*9880d681SAndroid Build Coastguard Worker     // Attribute that only apply to pointers.
1556*9880d681SAndroid Build Coastguard Worker     Incompatible.addAttribute(Attribute::ByVal)
1557*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::Nest)
1558*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::NoAlias)
1559*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::NoCapture)
1560*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::NonNull)
1561*9880d681SAndroid Build Coastguard Worker       .addDereferenceableAttr(1) // the int here is ignored
1562*9880d681SAndroid Build Coastguard Worker       .addDereferenceableOrNullAttr(1) // the int here is ignored
1563*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::ReadNone)
1564*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::ReadOnly)
1565*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::StructRet)
1566*9880d681SAndroid Build Coastguard Worker       .addAttribute(Attribute::InAlloca);
1567*9880d681SAndroid Build Coastguard Worker 
1568*9880d681SAndroid Build Coastguard Worker   return Incompatible;
1569*9880d681SAndroid Build Coastguard Worker }
1570*9880d681SAndroid Build Coastguard Worker 
1571*9880d681SAndroid Build Coastguard Worker template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)1572*9880d681SAndroid Build Coastguard Worker static bool isEqual(const Function &Caller, const Function &Callee) {
1573*9880d681SAndroid Build Coastguard Worker   return Caller.getFnAttribute(AttrClass::getKind()) ==
1574*9880d681SAndroid Build Coastguard Worker          Callee.getFnAttribute(AttrClass::getKind());
1575*9880d681SAndroid Build Coastguard Worker }
1576*9880d681SAndroid Build Coastguard Worker 
1577*9880d681SAndroid Build Coastguard Worker /// \brief Compute the logical AND of the attributes of the caller and the
1578*9880d681SAndroid Build Coastguard Worker /// callee.
1579*9880d681SAndroid Build Coastguard Worker ///
1580*9880d681SAndroid Build Coastguard Worker /// This function sets the caller's attribute to false if the callee's attribute
1581*9880d681SAndroid Build Coastguard Worker /// is false.
1582*9880d681SAndroid Build Coastguard Worker template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)1583*9880d681SAndroid Build Coastguard Worker static void setAND(Function &Caller, const Function &Callee) {
1584*9880d681SAndroid Build Coastguard Worker   if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
1585*9880d681SAndroid Build Coastguard Worker       !AttrClass::isSet(Callee, AttrClass::getKind()))
1586*9880d681SAndroid Build Coastguard Worker     AttrClass::set(Caller, AttrClass::getKind(), false);
1587*9880d681SAndroid Build Coastguard Worker }
1588*9880d681SAndroid Build Coastguard Worker 
1589*9880d681SAndroid Build Coastguard Worker /// \brief Compute the logical OR of the attributes of the caller and the
1590*9880d681SAndroid Build Coastguard Worker /// callee.
1591*9880d681SAndroid Build Coastguard Worker ///
1592*9880d681SAndroid Build Coastguard Worker /// This function sets the caller's attribute to true if the callee's attribute
1593*9880d681SAndroid Build Coastguard Worker /// is true.
1594*9880d681SAndroid Build Coastguard Worker template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)1595*9880d681SAndroid Build Coastguard Worker static void setOR(Function &Caller, const Function &Callee) {
1596*9880d681SAndroid Build Coastguard Worker   if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
1597*9880d681SAndroid Build Coastguard Worker       AttrClass::isSet(Callee, AttrClass::getKind()))
1598*9880d681SAndroid Build Coastguard Worker     AttrClass::set(Caller, AttrClass::getKind(), true);
1599*9880d681SAndroid Build Coastguard Worker }
1600*9880d681SAndroid Build Coastguard Worker 
1601*9880d681SAndroid Build Coastguard Worker /// \brief If the inlined function had a higher stack protection level than the
1602*9880d681SAndroid Build Coastguard Worker /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)1603*9880d681SAndroid Build Coastguard Worker static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1604*9880d681SAndroid Build Coastguard Worker   // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1605*9880d681SAndroid Build Coastguard Worker   // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1606*9880d681SAndroid Build Coastguard Worker   // clutter to the IR.
1607*9880d681SAndroid Build Coastguard Worker   AttrBuilder B;
1608*9880d681SAndroid Build Coastguard Worker   B.addAttribute(Attribute::StackProtect)
1609*9880d681SAndroid Build Coastguard Worker     .addAttribute(Attribute::StackProtectStrong)
1610*9880d681SAndroid Build Coastguard Worker     .addAttribute(Attribute::StackProtectReq);
1611*9880d681SAndroid Build Coastguard Worker   AttributeSet OldSSPAttr = AttributeSet::get(Caller.getContext(),
1612*9880d681SAndroid Build Coastguard Worker                                               AttributeSet::FunctionIndex,
1613*9880d681SAndroid Build Coastguard Worker                                               B);
1614*9880d681SAndroid Build Coastguard Worker 
1615*9880d681SAndroid Build Coastguard Worker   if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1616*9880d681SAndroid Build Coastguard Worker     Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
1617*9880d681SAndroid Build Coastguard Worker     Caller.addFnAttr(Attribute::StackProtectReq);
1618*9880d681SAndroid Build Coastguard Worker   } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
1619*9880d681SAndroid Build Coastguard Worker              !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1620*9880d681SAndroid Build Coastguard Worker     Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
1621*9880d681SAndroid Build Coastguard Worker     Caller.addFnAttr(Attribute::StackProtectStrong);
1622*9880d681SAndroid Build Coastguard Worker   } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
1623*9880d681SAndroid Build Coastguard Worker              !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
1624*9880d681SAndroid Build Coastguard Worker              !Caller.hasFnAttribute(Attribute::StackProtectStrong))
1625*9880d681SAndroid Build Coastguard Worker     Caller.addFnAttr(Attribute::StackProtect);
1626*9880d681SAndroid Build Coastguard Worker }
1627*9880d681SAndroid Build Coastguard Worker 
1628*9880d681SAndroid Build Coastguard Worker #define GET_ATTR_COMPAT_FUNC
1629*9880d681SAndroid Build Coastguard Worker #include "AttributesCompatFunc.inc"
1630*9880d681SAndroid Build Coastguard Worker 
areInlineCompatible(const Function & Caller,const Function & Callee)1631*9880d681SAndroid Build Coastguard Worker bool AttributeFuncs::areInlineCompatible(const Function &Caller,
1632*9880d681SAndroid Build Coastguard Worker                                          const Function &Callee) {
1633*9880d681SAndroid Build Coastguard Worker   return hasCompatibleFnAttrs(Caller, Callee);
1634*9880d681SAndroid Build Coastguard Worker }
1635*9880d681SAndroid Build Coastguard Worker 
1636*9880d681SAndroid Build Coastguard Worker 
mergeAttributesForInlining(Function & Caller,const Function & Callee)1637*9880d681SAndroid Build Coastguard Worker void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
1638*9880d681SAndroid Build Coastguard Worker                                                 const Function &Callee) {
1639*9880d681SAndroid Build Coastguard Worker   mergeFnAttrs(Caller, Callee);
1640*9880d681SAndroid Build Coastguard Worker }
1641