xref: /openbsd/gnu/llvm/llvm/lib/IR/Attributes.cpp (revision d415bd75)
1 //===- Attributes.cpp - Implement AttributesList --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // \file
10 // This file implements the Attribute, AttributeImpl, AttrBuilder,
11 // AttributeListImpl, and AttributeList classes.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/IR/Attributes.h"
16 #include "AttributeImpl.h"
17 #include "LLVMContextImpl.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/FoldingSet.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/Config/llvm-config.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/LLVMContext.h"
28 #include "llvm/IR/Type.h"
29 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/ModRef.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include <algorithm>
34 #include <cassert>
35 #include <cstddef>
36 #include <cstdint>
37 #include <limits>
38 #include <optional>
39 #include <string>
40 #include <tuple>
41 #include <utility>
42 
43 using namespace llvm;
44 
45 //===----------------------------------------------------------------------===//
46 // Attribute Construction Methods
47 //===----------------------------------------------------------------------===//
48 
49 // allocsize has two integer arguments, but because they're both 32 bits, we can
50 // pack them into one 64-bit value, at the cost of making said value
51 // nonsensical.
52 //
53 // In order to do this, we need to reserve one value of the second (optional)
54 // allocsize argument to signify "not present."
55 static const unsigned AllocSizeNumElemsNotPresent = -1;
56 
packAllocSizeArgs(unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)57 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
58                                   const std::optional<unsigned> &NumElemsArg) {
59   assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
60          "Attempting to pack a reserved value");
61 
62   return uint64_t(ElemSizeArg) << 32 |
63          NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
64 }
65 
66 static std::pair<unsigned, std::optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)67 unpackAllocSizeArgs(uint64_t Num) {
68   unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
69   unsigned ElemSizeArg = Num >> 32;
70 
71   std::optional<unsigned> NumElemsArg;
72   if (NumElems != AllocSizeNumElemsNotPresent)
73     NumElemsArg = NumElems;
74   return std::make_pair(ElemSizeArg, NumElemsArg);
75 }
76 
packVScaleRangeArgs(unsigned MinValue,std::optional<unsigned> MaxValue)77 static uint64_t packVScaleRangeArgs(unsigned MinValue,
78                                     std::optional<unsigned> MaxValue) {
79   return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
80 }
81 
82 static std::pair<unsigned, std::optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value)83 unpackVScaleRangeArgs(uint64_t Value) {
84   unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
85   unsigned MinValue = Value >> 32;
86 
87   return std::make_pair(MinValue,
88                         MaxValue > 0 ? MaxValue : std::optional<unsigned>());
89 }
90 
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)91 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
92                          uint64_t Val) {
93   bool IsIntAttr = Attribute::isIntAttrKind(Kind);
94   assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
95          "Not an enum or int attribute");
96 
97   LLVMContextImpl *pImpl = Context.pImpl;
98   FoldingSetNodeID ID;
99   ID.AddInteger(Kind);
100   if (IsIntAttr)
101     ID.AddInteger(Val);
102   else
103     assert(Val == 0 && "Value must be zero for enum attributes");
104 
105   void *InsertPoint;
106   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
107 
108   if (!PA) {
109     // If we didn't find any existing attributes of the same shape then create a
110     // new one and insert it.
111     if (!IsIntAttr)
112       PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
113     else
114       PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
115     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
116   }
117 
118   // Return the Attribute that we found or created.
119   return Attribute(PA);
120 }
121 
get(LLVMContext & Context,StringRef Kind,StringRef Val)122 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
123   LLVMContextImpl *pImpl = Context.pImpl;
124   FoldingSetNodeID ID;
125   ID.AddString(Kind);
126   if (!Val.empty()) ID.AddString(Val);
127 
128   void *InsertPoint;
129   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
130 
131   if (!PA) {
132     // If we didn't find any existing attributes of the same shape then create a
133     // new one and insert it.
134     void *Mem =
135         pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
136                               alignof(StringAttributeImpl));
137     PA = new (Mem) StringAttributeImpl(Kind, Val);
138     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
139   }
140 
141   // Return the Attribute that we found or created.
142   return Attribute(PA);
143 }
144 
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)145 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
146                          Type *Ty) {
147   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
148   LLVMContextImpl *pImpl = Context.pImpl;
149   FoldingSetNodeID ID;
150   ID.AddInteger(Kind);
151   ID.AddPointer(Ty);
152 
153   void *InsertPoint;
154   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
155 
156   if (!PA) {
157     // If we didn't find any existing attributes of the same shape then create a
158     // new one and insert it.
159     PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
160     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
161   }
162 
163   // Return the Attribute that we found or created.
164   return Attribute(PA);
165 }
166 
getWithAlignment(LLVMContext & Context,Align A)167 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
168   assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
169   return get(Context, Alignment, A.value());
170 }
171 
getWithStackAlignment(LLVMContext & Context,Align A)172 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
173   assert(A <= 0x100 && "Alignment too large.");
174   return get(Context, StackAlignment, A.value());
175 }
176 
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)177 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
178                                                 uint64_t Bytes) {
179   assert(Bytes && "Bytes must be non-zero.");
180   return get(Context, Dereferenceable, Bytes);
181 }
182 
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)183 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
184                                                        uint64_t Bytes) {
185   assert(Bytes && "Bytes must be non-zero.");
186   return get(Context, DereferenceableOrNull, Bytes);
187 }
188 
getWithByValType(LLVMContext & Context,Type * Ty)189 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
190   return get(Context, ByVal, Ty);
191 }
192 
getWithStructRetType(LLVMContext & Context,Type * Ty)193 Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
194   return get(Context, StructRet, Ty);
195 }
196 
getWithByRefType(LLVMContext & Context,Type * Ty)197 Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
198   return get(Context, ByRef, Ty);
199 }
200 
getWithPreallocatedType(LLVMContext & Context,Type * Ty)201 Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
202   return get(Context, Preallocated, Ty);
203 }
204 
getWithInAllocaType(LLVMContext & Context,Type * Ty)205 Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
206   return get(Context, InAlloca, Ty);
207 }
208 
getWithUWTableKind(LLVMContext & Context,UWTableKind Kind)209 Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
210                                         UWTableKind Kind) {
211   return get(Context, UWTable, uint64_t(Kind));
212 }
213 
getWithMemoryEffects(LLVMContext & Context,MemoryEffects ME)214 Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
215                                           MemoryEffects ME) {
216   return get(Context, Memory, ME.toIntValue());
217 }
218 
219 Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)220 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
221                                 const std::optional<unsigned> &NumElemsArg) {
222   assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
223          "Invalid allocsize arguments -- given allocsize(0, 0)");
224   return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
225 }
226 
getWithVScaleRangeArgs(LLVMContext & Context,unsigned MinValue,unsigned MaxValue)227 Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
228                                             unsigned MinValue,
229                                             unsigned MaxValue) {
230   return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
231 }
232 
getAttrKindFromName(StringRef AttrName)233 Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
234   return StringSwitch<Attribute::AttrKind>(AttrName)
235 #define GET_ATTR_NAMES
236 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
237   .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
238 #include "llvm/IR/Attributes.inc"
239       .Default(Attribute::None);
240 }
241 
getNameFromAttrKind(Attribute::AttrKind AttrKind)242 StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
243   switch (AttrKind) {
244 #define GET_ATTR_NAMES
245 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
246   case Attribute::ENUM_NAME:                                                   \
247     return #DISPLAY_NAME;
248 #include "llvm/IR/Attributes.inc"
249   case Attribute::None:
250     return "none";
251   default:
252     llvm_unreachable("invalid Kind");
253   }
254 }
255 
isExistingAttribute(StringRef Name)256 bool Attribute::isExistingAttribute(StringRef Name) {
257   return StringSwitch<bool>(Name)
258 #define GET_ATTR_NAMES
259 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
260 #include "llvm/IR/Attributes.inc"
261       .Default(false);
262 }
263 
264 //===----------------------------------------------------------------------===//
265 // Attribute Accessor Methods
266 //===----------------------------------------------------------------------===//
267 
isEnumAttribute() const268 bool Attribute::isEnumAttribute() const {
269   return pImpl && pImpl->isEnumAttribute();
270 }
271 
isIntAttribute() const272 bool Attribute::isIntAttribute() const {
273   return pImpl && pImpl->isIntAttribute();
274 }
275 
isStringAttribute() const276 bool Attribute::isStringAttribute() const {
277   return pImpl && pImpl->isStringAttribute();
278 }
279 
isTypeAttribute() const280 bool Attribute::isTypeAttribute() const {
281   return pImpl && pImpl->isTypeAttribute();
282 }
283 
getKindAsEnum() const284 Attribute::AttrKind Attribute::getKindAsEnum() const {
285   if (!pImpl) return None;
286   assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
287          "Invalid attribute type to get the kind as an enum!");
288   return pImpl->getKindAsEnum();
289 }
290 
getValueAsInt() const291 uint64_t Attribute::getValueAsInt() const {
292   if (!pImpl) return 0;
293   assert(isIntAttribute() &&
294          "Expected the attribute to be an integer attribute!");
295   return pImpl->getValueAsInt();
296 }
297 
getValueAsBool() const298 bool Attribute::getValueAsBool() const {
299   if (!pImpl) return false;
300   assert(isStringAttribute() &&
301          "Expected the attribute to be a string attribute!");
302   return pImpl->getValueAsBool();
303 }
304 
getKindAsString() const305 StringRef Attribute::getKindAsString() const {
306   if (!pImpl) return {};
307   assert(isStringAttribute() &&
308          "Invalid attribute type to get the kind as a string!");
309   return pImpl->getKindAsString();
310 }
311 
getValueAsString() const312 StringRef Attribute::getValueAsString() const {
313   if (!pImpl) return {};
314   assert(isStringAttribute() &&
315          "Invalid attribute type to get the value as a string!");
316   return pImpl->getValueAsString();
317 }
318 
getValueAsType() const319 Type *Attribute::getValueAsType() const {
320   if (!pImpl) return {};
321   assert(isTypeAttribute() &&
322          "Invalid attribute type to get the value as a type!");
323   return pImpl->getValueAsType();
324 }
325 
326 
hasAttribute(AttrKind Kind) const327 bool Attribute::hasAttribute(AttrKind Kind) const {
328   return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
329 }
330 
hasAttribute(StringRef Kind) const331 bool Attribute::hasAttribute(StringRef Kind) const {
332   if (!isStringAttribute()) return false;
333   return pImpl && pImpl->hasAttribute(Kind);
334 }
335 
getAlignment() const336 MaybeAlign Attribute::getAlignment() const {
337   assert(hasAttribute(Attribute::Alignment) &&
338          "Trying to get alignment from non-alignment attribute!");
339   return MaybeAlign(pImpl->getValueAsInt());
340 }
341 
getStackAlignment() const342 MaybeAlign Attribute::getStackAlignment() const {
343   assert(hasAttribute(Attribute::StackAlignment) &&
344          "Trying to get alignment from non-alignment attribute!");
345   return MaybeAlign(pImpl->getValueAsInt());
346 }
347 
getDereferenceableBytes() const348 uint64_t Attribute::getDereferenceableBytes() const {
349   assert(hasAttribute(Attribute::Dereferenceable) &&
350          "Trying to get dereferenceable bytes from "
351          "non-dereferenceable attribute!");
352   return pImpl->getValueAsInt();
353 }
354 
getDereferenceableOrNullBytes() const355 uint64_t Attribute::getDereferenceableOrNullBytes() const {
356   assert(hasAttribute(Attribute::DereferenceableOrNull) &&
357          "Trying to get dereferenceable bytes from "
358          "non-dereferenceable attribute!");
359   return pImpl->getValueAsInt();
360 }
361 
362 std::pair<unsigned, std::optional<unsigned>>
getAllocSizeArgs() const363 Attribute::getAllocSizeArgs() const {
364   assert(hasAttribute(Attribute::AllocSize) &&
365          "Trying to get allocsize args from non-allocsize attribute");
366   return unpackAllocSizeArgs(pImpl->getValueAsInt());
367 }
368 
getVScaleRangeMin() const369 unsigned Attribute::getVScaleRangeMin() const {
370   assert(hasAttribute(Attribute::VScaleRange) &&
371          "Trying to get vscale args from non-vscale attribute");
372   return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
373 }
374 
getVScaleRangeMax() const375 std::optional<unsigned> Attribute::getVScaleRangeMax() const {
376   assert(hasAttribute(Attribute::VScaleRange) &&
377          "Trying to get vscale args from non-vscale attribute");
378   return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
379 }
380 
getUWTableKind() const381 UWTableKind Attribute::getUWTableKind() const {
382   assert(hasAttribute(Attribute::UWTable) &&
383          "Trying to get unwind table kind from non-uwtable attribute");
384   return UWTableKind(pImpl->getValueAsInt());
385 }
386 
getAllocKind() const387 AllocFnKind Attribute::getAllocKind() const {
388   assert(hasAttribute(Attribute::AllocKind) &&
389          "Trying to get allockind value from non-allockind attribute");
390   return AllocFnKind(pImpl->getValueAsInt());
391 }
392 
getMemoryEffects() const393 MemoryEffects Attribute::getMemoryEffects() const {
394   assert(hasAttribute(Attribute::Memory) &&
395          "Can only call getMemoryEffects() on memory attribute");
396   return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
397 }
398 
getModRefStr(ModRefInfo MR)399 static const char *getModRefStr(ModRefInfo MR) {
400   switch (MR) {
401   case ModRefInfo::NoModRef:
402     return "none";
403   case ModRefInfo::Ref:
404     return "read";
405   case ModRefInfo::Mod:
406     return "write";
407   case ModRefInfo::ModRef:
408     return "readwrite";
409   }
410   llvm_unreachable("Invalid ModRefInfo");
411 }
412 
getAsString(bool InAttrGrp) const413 std::string Attribute::getAsString(bool InAttrGrp) const {
414   if (!pImpl) return {};
415 
416   if (isEnumAttribute())
417     return getNameFromAttrKind(getKindAsEnum()).str();
418 
419   if (isTypeAttribute()) {
420     std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
421     Result += '(';
422     raw_string_ostream OS(Result);
423     getValueAsType()->print(OS, false, true);
424     OS.flush();
425     Result += ')';
426     return Result;
427   }
428 
429   // FIXME: These should be output like this:
430   //
431   //   align=4
432   //   alignstack=8
433   //
434   if (hasAttribute(Attribute::Alignment))
435     return (InAttrGrp ? "align=" + Twine(getValueAsInt())
436                       : "align " + Twine(getValueAsInt()))
437         .str();
438 
439   auto AttrWithBytesToString = [&](const char *Name) {
440     return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
441                       : Name + ("(" + Twine(getValueAsInt())) + ")")
442         .str();
443   };
444 
445   if (hasAttribute(Attribute::StackAlignment))
446     return AttrWithBytesToString("alignstack");
447 
448   if (hasAttribute(Attribute::Dereferenceable))
449     return AttrWithBytesToString("dereferenceable");
450 
451   if (hasAttribute(Attribute::DereferenceableOrNull))
452     return AttrWithBytesToString("dereferenceable_or_null");
453 
454   if (hasAttribute(Attribute::AllocSize)) {
455     unsigned ElemSize;
456     std::optional<unsigned> NumElems;
457     std::tie(ElemSize, NumElems) = getAllocSizeArgs();
458 
459     return (NumElems
460                 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
461                 : "allocsize(" + Twine(ElemSize) + ")")
462         .str();
463   }
464 
465   if (hasAttribute(Attribute::VScaleRange)) {
466     unsigned MinValue = getVScaleRangeMin();
467     std::optional<unsigned> MaxValue = getVScaleRangeMax();
468     return ("vscale_range(" + Twine(MinValue) + "," +
469             Twine(MaxValue.value_or(0)) + ")")
470         .str();
471   }
472 
473   if (hasAttribute(Attribute::UWTable)) {
474     UWTableKind Kind = getUWTableKind();
475     if (Kind != UWTableKind::None) {
476       return Kind == UWTableKind::Default
477                  ? "uwtable"
478                  : ("uwtable(" +
479                     Twine(Kind == UWTableKind::Sync ? "sync" : "async") + ")")
480                        .str();
481     }
482   }
483 
484   if (hasAttribute(Attribute::AllocKind)) {
485     AllocFnKind Kind = getAllocKind();
486     SmallVector<StringRef> parts;
487     if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
488       parts.push_back("alloc");
489     if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
490       parts.push_back("realloc");
491     if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
492       parts.push_back("free");
493     if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
494       parts.push_back("uninitialized");
495     if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
496       parts.push_back("zeroed");
497     if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
498       parts.push_back("aligned");
499     return ("allockind(\"" +
500             Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
501         .str();
502   }
503 
504   if (hasAttribute(Attribute::Memory)) {
505     std::string Result;
506     raw_string_ostream OS(Result);
507     bool First = true;
508     OS << "memory(";
509 
510     MemoryEffects ME = getMemoryEffects();
511 
512     // Print access kind for "other" as the default access kind. This way it
513     // will apply to any new location kinds that get split out of "other".
514     ModRefInfo OtherMR = ME.getModRef(MemoryEffects::Other);
515     if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
516       First = false;
517       OS << getModRefStr(OtherMR);
518     }
519 
520     for (auto Loc : MemoryEffects::locations()) {
521       ModRefInfo MR = ME.getModRef(Loc);
522       if (MR == OtherMR)
523         continue;
524 
525       if (!First)
526         OS << ", ";
527       First = false;
528 
529       switch (Loc) {
530       case MemoryEffects::ArgMem:
531         OS << "argmem: ";
532         break;
533       case MemoryEffects::InaccessibleMem:
534         OS << "inaccessiblemem: ";
535         break;
536       case MemoryEffects::Other:
537         llvm_unreachable("This is represented as the default access kind");
538       }
539       OS << getModRefStr(MR);
540     }
541     OS << ")";
542     OS.flush();
543     return Result;
544   }
545 
546   // Convert target-dependent attributes to strings of the form:
547   //
548   //   "kind"
549   //   "kind" = "value"
550   //
551   if (isStringAttribute()) {
552     std::string Result;
553     {
554       raw_string_ostream OS(Result);
555       OS << '"' << getKindAsString() << '"';
556 
557       // Since some attribute strings contain special characters that cannot be
558       // printable, those have to be escaped to make the attribute value
559       // printable as is.  e.g. "\01__gnu_mcount_nc"
560       const auto &AttrVal = pImpl->getValueAsString();
561       if (!AttrVal.empty()) {
562         OS << "=\"";
563         printEscapedString(AttrVal, OS);
564         OS << "\"";
565       }
566     }
567     return Result;
568   }
569 
570   llvm_unreachable("Unknown attribute");
571 }
572 
hasParentContext(LLVMContext & C) const573 bool Attribute::hasParentContext(LLVMContext &C) const {
574   assert(isValid() && "invalid Attribute doesn't refer to any context");
575   FoldingSetNodeID ID;
576   pImpl->Profile(ID);
577   void *Unused;
578   return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
579 }
580 
operator <(Attribute A) const581 bool Attribute::operator<(Attribute A) const {
582   if (!pImpl && !A.pImpl) return false;
583   if (!pImpl) return true;
584   if (!A.pImpl) return false;
585   return *pImpl < *A.pImpl;
586 }
587 
Profile(FoldingSetNodeID & ID) const588 void Attribute::Profile(FoldingSetNodeID &ID) const {
589   ID.AddPointer(pImpl);
590 }
591 
592 enum AttributeProperty {
593   FnAttr = (1 << 0),
594   ParamAttr = (1 << 1),
595   RetAttr = (1 << 2),
596 };
597 
598 #define GET_ATTR_PROP_TABLE
599 #include "llvm/IR/Attributes.inc"
600 
hasAttributeProperty(Attribute::AttrKind Kind,AttributeProperty Prop)601 static bool hasAttributeProperty(Attribute::AttrKind Kind,
602                                  AttributeProperty Prop) {
603   unsigned Index = Kind - 1;
604   assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
605   return AttrPropTable[Index] & Prop;
606 }
607 
canUseAsFnAttr(AttrKind Kind)608 bool Attribute::canUseAsFnAttr(AttrKind Kind) {
609   return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
610 }
611 
canUseAsParamAttr(AttrKind Kind)612 bool Attribute::canUseAsParamAttr(AttrKind Kind) {
613   return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
614 }
615 
canUseAsRetAttr(AttrKind Kind)616 bool Attribute::canUseAsRetAttr(AttrKind Kind) {
617   return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
618 }
619 
620 //===----------------------------------------------------------------------===//
621 // AttributeImpl Definition
622 //===----------------------------------------------------------------------===//
623 
hasAttribute(Attribute::AttrKind A) const624 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
625   if (isStringAttribute()) return false;
626   return getKindAsEnum() == A;
627 }
628 
hasAttribute(StringRef Kind) const629 bool AttributeImpl::hasAttribute(StringRef Kind) const {
630   if (!isStringAttribute()) return false;
631   return getKindAsString() == Kind;
632 }
633 
getKindAsEnum() const634 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
635   assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
636   return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
637 }
638 
getValueAsInt() const639 uint64_t AttributeImpl::getValueAsInt() const {
640   assert(isIntAttribute());
641   return static_cast<const IntAttributeImpl *>(this)->getValue();
642 }
643 
getValueAsBool() const644 bool AttributeImpl::getValueAsBool() const {
645   assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
646   return getValueAsString() == "true";
647 }
648 
getKindAsString() const649 StringRef AttributeImpl::getKindAsString() const {
650   assert(isStringAttribute());
651   return static_cast<const StringAttributeImpl *>(this)->getStringKind();
652 }
653 
getValueAsString() const654 StringRef AttributeImpl::getValueAsString() const {
655   assert(isStringAttribute());
656   return static_cast<const StringAttributeImpl *>(this)->getStringValue();
657 }
658 
getValueAsType() const659 Type *AttributeImpl::getValueAsType() const {
660   assert(isTypeAttribute());
661   return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
662 }
663 
operator <(const AttributeImpl & AI) const664 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
665   if (this == &AI)
666     return false;
667 
668   // This sorts the attributes with Attribute::AttrKinds coming first (sorted
669   // relative to their enum value) and then strings.
670   if (!isStringAttribute()) {
671     if (AI.isStringAttribute())
672       return true;
673     if (getKindAsEnum() != AI.getKindAsEnum())
674       return getKindAsEnum() < AI.getKindAsEnum();
675     assert(!AI.isEnumAttribute() && "Non-unique attribute");
676     assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
677     // TODO: Is this actually needed?
678     assert(AI.isIntAttribute() && "Only possibility left");
679     return getValueAsInt() < AI.getValueAsInt();
680   }
681 
682   if (!AI.isStringAttribute())
683     return false;
684   if (getKindAsString() == AI.getKindAsString())
685     return getValueAsString() < AI.getValueAsString();
686   return getKindAsString() < AI.getKindAsString();
687 }
688 
689 //===----------------------------------------------------------------------===//
690 // AttributeSet Definition
691 //===----------------------------------------------------------------------===//
692 
get(LLVMContext & C,const AttrBuilder & B)693 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
694   return AttributeSet(AttributeSetNode::get(C, B));
695 }
696 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)697 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
698   return AttributeSet(AttributeSetNode::get(C, Attrs));
699 }
700 
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const701 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
702                                         Attribute::AttrKind Kind) const {
703   if (hasAttribute(Kind)) return *this;
704   AttrBuilder B(C);
705   B.addAttribute(Kind);
706   return addAttributes(C, AttributeSet::get(C, B));
707 }
708 
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const709 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
710                                         StringRef Value) const {
711   AttrBuilder B(C);
712   B.addAttribute(Kind, Value);
713   return addAttributes(C, AttributeSet::get(C, B));
714 }
715 
addAttributes(LLVMContext & C,const AttributeSet AS) const716 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
717                                          const AttributeSet AS) const {
718   if (!hasAttributes())
719     return AS;
720 
721   if (!AS.hasAttributes())
722     return *this;
723 
724   AttrBuilder B(C, *this);
725   B.merge(AttrBuilder(C, AS));
726   return get(C, B);
727 }
728 
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const729 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
730                                              Attribute::AttrKind Kind) const {
731   if (!hasAttribute(Kind)) return *this;
732   AttrBuilder B(C, *this);
733   B.removeAttribute(Kind);
734   return get(C, B);
735 }
736 
removeAttribute(LLVMContext & C,StringRef Kind) const737 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
738                                              StringRef Kind) const {
739   if (!hasAttribute(Kind)) return *this;
740   AttrBuilder B(C, *this);
741   B.removeAttribute(Kind);
742   return get(C, B);
743 }
744 
removeAttributes(LLVMContext & C,const AttributeMask & Attrs) const745 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
746                                             const AttributeMask &Attrs) const {
747   AttrBuilder B(C, *this);
748   // If there is nothing to remove, directly return the original set.
749   if (!B.overlaps(Attrs))
750     return *this;
751 
752   B.remove(Attrs);
753   return get(C, B);
754 }
755 
getNumAttributes() const756 unsigned AttributeSet::getNumAttributes() const {
757   return SetNode ? SetNode->getNumAttributes() : 0;
758 }
759 
hasAttribute(Attribute::AttrKind Kind) const760 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
761   return SetNode ? SetNode->hasAttribute(Kind) : false;
762 }
763 
hasAttribute(StringRef Kind) const764 bool AttributeSet::hasAttribute(StringRef Kind) const {
765   return SetNode ? SetNode->hasAttribute(Kind) : false;
766 }
767 
getAttribute(Attribute::AttrKind Kind) const768 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
769   return SetNode ? SetNode->getAttribute(Kind) : Attribute();
770 }
771 
getAttribute(StringRef Kind) const772 Attribute AttributeSet::getAttribute(StringRef Kind) const {
773   return SetNode ? SetNode->getAttribute(Kind) : Attribute();
774 }
775 
getAlignment() const776 MaybeAlign AttributeSet::getAlignment() const {
777   return SetNode ? SetNode->getAlignment() : std::nullopt;
778 }
779 
getStackAlignment() const780 MaybeAlign AttributeSet::getStackAlignment() const {
781   return SetNode ? SetNode->getStackAlignment() : std::nullopt;
782 }
783 
getDereferenceableBytes() const784 uint64_t AttributeSet::getDereferenceableBytes() const {
785   return SetNode ? SetNode->getDereferenceableBytes() : 0;
786 }
787 
getDereferenceableOrNullBytes() const788 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
789   return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
790 }
791 
getByRefType() const792 Type *AttributeSet::getByRefType() const {
793   return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
794 }
795 
getByValType() const796 Type *AttributeSet::getByValType() const {
797   return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
798 }
799 
getStructRetType() const800 Type *AttributeSet::getStructRetType() const {
801   return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
802 }
803 
getPreallocatedType() const804 Type *AttributeSet::getPreallocatedType() const {
805   return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
806 }
807 
getInAllocaType() const808 Type *AttributeSet::getInAllocaType() const {
809   return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
810 }
811 
getElementType() const812 Type *AttributeSet::getElementType() const {
813   return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
814 }
815 
816 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const817 AttributeSet::getAllocSizeArgs() const {
818   if (SetNode)
819     return SetNode->getAllocSizeArgs();
820   return std::nullopt;
821 }
822 
getVScaleRangeMin() const823 unsigned AttributeSet::getVScaleRangeMin() const {
824   return SetNode ? SetNode->getVScaleRangeMin() : 1;
825 }
826 
getVScaleRangeMax() const827 std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
828   return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
829 }
830 
getUWTableKind() const831 UWTableKind AttributeSet::getUWTableKind() const {
832   return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
833 }
834 
getAllocKind() const835 AllocFnKind AttributeSet::getAllocKind() const {
836   return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
837 }
838 
getMemoryEffects() const839 MemoryEffects AttributeSet::getMemoryEffects() const {
840   return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
841 }
842 
getAsString(bool InAttrGrp) const843 std::string AttributeSet::getAsString(bool InAttrGrp) const {
844   return SetNode ? SetNode->getAsString(InAttrGrp) : "";
845 }
846 
hasParentContext(LLVMContext & C) const847 bool AttributeSet::hasParentContext(LLVMContext &C) const {
848   assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
849   FoldingSetNodeID ID;
850   SetNode->Profile(ID);
851   void *Unused;
852   return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
853 }
854 
begin() const855 AttributeSet::iterator AttributeSet::begin() const {
856   return SetNode ? SetNode->begin() : nullptr;
857 }
858 
end() const859 AttributeSet::iterator AttributeSet::end() const {
860   return SetNode ? SetNode->end() : nullptr;
861 }
862 
863 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const864 LLVM_DUMP_METHOD void AttributeSet::dump() const {
865   dbgs() << "AS =\n";
866     dbgs() << "  { ";
867     dbgs() << getAsString(true) << " }\n";
868 }
869 #endif
870 
871 //===----------------------------------------------------------------------===//
872 // AttributeSetNode Definition
873 //===----------------------------------------------------------------------===//
874 
AttributeSetNode(ArrayRef<Attribute> Attrs)875 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
876     : NumAttrs(Attrs.size()) {
877   // There's memory after the node where we can store the entries in.
878   llvm::copy(Attrs, getTrailingObjects<Attribute>());
879 
880   for (const auto &I : *this) {
881     if (I.isStringAttribute())
882       StringAttrs.insert({ I.getKindAsString(), I });
883     else
884       AvailableAttrs.addAttribute(I.getKindAsEnum());
885   }
886 }
887 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)888 AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
889                                         ArrayRef<Attribute> Attrs) {
890   SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
891   llvm::sort(SortedAttrs);
892   return getSorted(C, SortedAttrs);
893 }
894 
getSorted(LLVMContext & C,ArrayRef<Attribute> SortedAttrs)895 AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
896                                               ArrayRef<Attribute> SortedAttrs) {
897   if (SortedAttrs.empty())
898     return nullptr;
899 
900   // Build a key to look up the existing attributes.
901   LLVMContextImpl *pImpl = C.pImpl;
902   FoldingSetNodeID ID;
903 
904   assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
905   for (const auto &Attr : SortedAttrs)
906     Attr.Profile(ID);
907 
908   void *InsertPoint;
909   AttributeSetNode *PA =
910     pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
911 
912   // If we didn't find any existing attributes of the same shape then create a
913   // new one and insert it.
914   if (!PA) {
915     // Coallocate entries after the AttributeSetNode itself.
916     void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
917     PA = new (Mem) AttributeSetNode(SortedAttrs);
918     pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
919   }
920 
921   // Return the AttributeSetNode that we found or created.
922   return PA;
923 }
924 
get(LLVMContext & C,const AttrBuilder & B)925 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
926   return getSorted(C, B.attrs());
927 }
928 
hasAttribute(StringRef Kind) const929 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
930   return StringAttrs.count(Kind);
931 }
932 
933 std::optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const934 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
935   // Do a quick presence check.
936   if (!hasAttribute(Kind))
937     return std::nullopt;
938 
939   // Attributes in a set are sorted by enum value, followed by string
940   // attributes. Binary search the one we want.
941   const Attribute *I =
942       std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
943                        [](Attribute A, Attribute::AttrKind Kind) {
944                          return A.getKindAsEnum() < Kind;
945                        });
946   assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
947   return *I;
948 }
949 
getAttribute(Attribute::AttrKind Kind) const950 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
951   if (auto A = findEnumAttribute(Kind))
952     return *A;
953   return {};
954 }
955 
getAttribute(StringRef Kind) const956 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
957   return StringAttrs.lookup(Kind);
958 }
959 
getAlignment() const960 MaybeAlign AttributeSetNode::getAlignment() const {
961   if (auto A = findEnumAttribute(Attribute::Alignment))
962     return A->getAlignment();
963   return std::nullopt;
964 }
965 
getStackAlignment() const966 MaybeAlign AttributeSetNode::getStackAlignment() const {
967   if (auto A = findEnumAttribute(Attribute::StackAlignment))
968     return A->getStackAlignment();
969   return std::nullopt;
970 }
971 
getAttributeType(Attribute::AttrKind Kind) const972 Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
973   if (auto A = findEnumAttribute(Kind))
974     return A->getValueAsType();
975   return nullptr;
976 }
977 
getDereferenceableBytes() const978 uint64_t AttributeSetNode::getDereferenceableBytes() const {
979   if (auto A = findEnumAttribute(Attribute::Dereferenceable))
980     return A->getDereferenceableBytes();
981   return 0;
982 }
983 
getDereferenceableOrNullBytes() const984 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
985   if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
986     return A->getDereferenceableOrNullBytes();
987   return 0;
988 }
989 
990 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const991 AttributeSetNode::getAllocSizeArgs() const {
992   if (auto A = findEnumAttribute(Attribute::AllocSize))
993     return A->getAllocSizeArgs();
994   return std::nullopt;
995 }
996 
getVScaleRangeMin() const997 unsigned AttributeSetNode::getVScaleRangeMin() const {
998   if (auto A = findEnumAttribute(Attribute::VScaleRange))
999     return A->getVScaleRangeMin();
1000   return 1;
1001 }
1002 
getVScaleRangeMax() const1003 std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1004   if (auto A = findEnumAttribute(Attribute::VScaleRange))
1005     return A->getVScaleRangeMax();
1006   return std::nullopt;
1007 }
1008 
getUWTableKind() const1009 UWTableKind AttributeSetNode::getUWTableKind() const {
1010   if (auto A = findEnumAttribute(Attribute::UWTable))
1011     return A->getUWTableKind();
1012   return UWTableKind::None;
1013 }
1014 
getAllocKind() const1015 AllocFnKind AttributeSetNode::getAllocKind() const {
1016   if (auto A = findEnumAttribute(Attribute::AllocKind))
1017     return A->getAllocKind();
1018   return AllocFnKind::Unknown;
1019 }
1020 
getMemoryEffects() const1021 MemoryEffects AttributeSetNode::getMemoryEffects() const {
1022   if (auto A = findEnumAttribute(Attribute::Memory))
1023     return A->getMemoryEffects();
1024   return MemoryEffects::unknown();
1025 }
1026 
getAsString(bool InAttrGrp) const1027 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1028   std::string Str;
1029   for (iterator I = begin(), E = end(); I != E; ++I) {
1030     if (I != begin())
1031       Str += ' ';
1032     Str += I->getAsString(InAttrGrp);
1033   }
1034   return Str;
1035 }
1036 
1037 //===----------------------------------------------------------------------===//
1038 // AttributeListImpl Definition
1039 //===----------------------------------------------------------------------===//
1040 
1041 /// Map from AttributeList index to the internal array index. Adding one happens
1042 /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)1043 static unsigned attrIdxToArrayIdx(unsigned Index) {
1044   return Index + 1;
1045 }
1046 
AttributeListImpl(ArrayRef<AttributeSet> Sets)1047 AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
1048     : NumAttrSets(Sets.size()) {
1049   assert(!Sets.empty() && "pointless AttributeListImpl");
1050 
1051   // There's memory after the node where we can store the entries in.
1052   llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1053 
1054   // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1055   // summary bitsets.
1056   for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1057     if (!I.isStringAttribute())
1058       AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1059 
1060   for (const auto &Set : Sets)
1061     for (const auto &I : Set)
1062       if (!I.isStringAttribute())
1063         AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1064 }
1065 
Profile(FoldingSetNodeID & ID) const1066 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
1067   Profile(ID, ArrayRef(begin(), end()));
1068 }
1069 
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)1070 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
1071                                 ArrayRef<AttributeSet> Sets) {
1072   for (const auto &Set : Sets)
1073     ID.AddPointer(Set.SetNode);
1074 }
1075 
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const1076 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
1077                                         unsigned *Index) const {
1078   if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1079     return false;
1080 
1081   if (Index) {
1082     for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1083       if (begin()[I].hasAttribute(Kind)) {
1084         *Index = I - 1;
1085         break;
1086       }
1087     }
1088   }
1089 
1090   return true;
1091 }
1092 
1093 
1094 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1095 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1096   AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1097 }
1098 #endif
1099 
1100 //===----------------------------------------------------------------------===//
1101 // AttributeList Construction and Mutation Methods
1102 //===----------------------------------------------------------------------===//
1103 
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)1104 AttributeList AttributeList::getImpl(LLVMContext &C,
1105                                      ArrayRef<AttributeSet> AttrSets) {
1106   assert(!AttrSets.empty() && "pointless AttributeListImpl");
1107 
1108   LLVMContextImpl *pImpl = C.pImpl;
1109   FoldingSetNodeID ID;
1110   AttributeListImpl::Profile(ID, AttrSets);
1111 
1112   void *InsertPoint;
1113   AttributeListImpl *PA =
1114       pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1115 
1116   // If we didn't find any existing attributes of the same shape then
1117   // create a new one and insert it.
1118   if (!PA) {
1119     // Coallocate entries after the AttributeListImpl itself.
1120     void *Mem = pImpl->Alloc.Allocate(
1121         AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1122         alignof(AttributeListImpl));
1123     PA = new (Mem) AttributeListImpl(AttrSets);
1124     pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1125   }
1126 
1127   // Return the AttributesList that we found or created.
1128   return AttributeList(PA);
1129 }
1130 
1131 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)1132 AttributeList::get(LLVMContext &C,
1133                    ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1134   // If there are no attributes then return a null AttributesList pointer.
1135   if (Attrs.empty())
1136     return {};
1137 
1138   assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1139          "Misordered Attributes list!");
1140   assert(llvm::all_of(Attrs,
1141                       [](const std::pair<unsigned, Attribute> &Pair) {
1142                         return Pair.second.isValid();
1143                       }) &&
1144          "Pointless attribute!");
1145 
1146   // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1147   // list.
1148   SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1149   for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1150          E = Attrs.end(); I != E; ) {
1151     unsigned Index = I->first;
1152     SmallVector<Attribute, 4> AttrVec;
1153     while (I != E && I->first == Index) {
1154       AttrVec.push_back(I->second);
1155       ++I;
1156     }
1157 
1158     AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1159   }
1160 
1161   return get(C, AttrPairVec);
1162 }
1163 
1164 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1165 AttributeList::get(LLVMContext &C,
1166                    ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1167   // If there are no attributes then return a null AttributesList pointer.
1168   if (Attrs.empty())
1169     return {};
1170 
1171   assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1172          "Misordered Attributes list!");
1173   assert(llvm::none_of(Attrs,
1174                        [](const std::pair<unsigned, AttributeSet> &Pair) {
1175                          return !Pair.second.hasAttributes();
1176                        }) &&
1177          "Pointless attribute!");
1178 
1179   unsigned MaxIndex = Attrs.back().first;
1180   // If the MaxIndex is FunctionIndex and there are other indices in front
1181   // of it, we need to use the largest of those to get the right size.
1182   if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1183     MaxIndex = Attrs[Attrs.size() - 2].first;
1184 
1185   SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1186   for (const auto &Pair : Attrs)
1187     AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1188 
1189   return getImpl(C, AttrVec);
1190 }
1191 
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)1192 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1193                                  AttributeSet RetAttrs,
1194                                  ArrayRef<AttributeSet> ArgAttrs) {
1195   // Scan from the end to find the last argument with attributes.  Most
1196   // arguments don't have attributes, so it's nice if we can have fewer unique
1197   // AttributeListImpls by dropping empty attribute sets at the end of the list.
1198   unsigned NumSets = 0;
1199   for (size_t I = ArgAttrs.size(); I != 0; --I) {
1200     if (ArgAttrs[I - 1].hasAttributes()) {
1201       NumSets = I + 2;
1202       break;
1203     }
1204   }
1205   if (NumSets == 0) {
1206     // Check function and return attributes if we didn't have argument
1207     // attributes.
1208     if (RetAttrs.hasAttributes())
1209       NumSets = 2;
1210     else if (FnAttrs.hasAttributes())
1211       NumSets = 1;
1212   }
1213 
1214   // If all attribute sets were empty, we can use the empty attribute list.
1215   if (NumSets == 0)
1216     return {};
1217 
1218   SmallVector<AttributeSet, 8> AttrSets;
1219   AttrSets.reserve(NumSets);
1220   // If we have any attributes, we always have function attributes.
1221   AttrSets.push_back(FnAttrs);
1222   if (NumSets > 1)
1223     AttrSets.push_back(RetAttrs);
1224   if (NumSets > 2) {
1225     // Drop the empty argument attribute sets at the end.
1226     ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1227     llvm::append_range(AttrSets, ArgAttrs);
1228   }
1229 
1230   return getImpl(C, AttrSets);
1231 }
1232 
get(LLVMContext & C,unsigned Index,AttributeSet Attrs)1233 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1234                                  AttributeSet Attrs) {
1235   if (!Attrs.hasAttributes())
1236     return {};
1237   Index = attrIdxToArrayIdx(Index);
1238   SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1239   AttrSets[Index] = Attrs;
1240   return getImpl(C, AttrSets);
1241 }
1242 
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1243 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1244                                  const AttrBuilder &B) {
1245   return get(C, Index, AttributeSet::get(C, B));
1246 }
1247 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1248 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1249                                  ArrayRef<Attribute::AttrKind> Kinds) {
1250   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1251   for (const auto K : Kinds)
1252     Attrs.emplace_back(Index, Attribute::get(C, K));
1253   return get(C, Attrs);
1254 }
1255 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)1256 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1257                                  ArrayRef<Attribute::AttrKind> Kinds,
1258                                  ArrayRef<uint64_t> Values) {
1259   assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1260   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1261   auto VI = Values.begin();
1262   for (const auto K : Kinds)
1263     Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1264   return get(C, Attrs);
1265 }
1266 
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1267 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1268                                  ArrayRef<StringRef> Kinds) {
1269   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1270   for (const auto &K : Kinds)
1271     Attrs.emplace_back(Index, Attribute::get(C, K));
1272   return get(C, Attrs);
1273 }
1274 
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1275 AttributeList AttributeList::get(LLVMContext &C,
1276                                  ArrayRef<AttributeList> Attrs) {
1277   if (Attrs.empty())
1278     return {};
1279   if (Attrs.size() == 1)
1280     return Attrs[0];
1281 
1282   unsigned MaxSize = 0;
1283   for (const auto &List : Attrs)
1284     MaxSize = std::max(MaxSize, List.getNumAttrSets());
1285 
1286   // If every list was empty, there is no point in merging the lists.
1287   if (MaxSize == 0)
1288     return {};
1289 
1290   SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1291   for (unsigned I = 0; I < MaxSize; ++I) {
1292     AttrBuilder CurBuilder(C);
1293     for (const auto &List : Attrs)
1294       CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1295     NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1296   }
1297 
1298   return getImpl(C, NewAttrSets);
1299 }
1300 
1301 AttributeList
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1302 AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1303                                    Attribute::AttrKind Kind) const {
1304   AttributeSet Attrs = getAttributes(Index);
1305   if (Attrs.hasAttribute(Kind))
1306     return *this;
1307   // TODO: Insert at correct position and avoid sort.
1308   SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1309   NewAttrs.push_back(Attribute::get(C, Kind));
1310   return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1311 }
1312 
addAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1313 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1314                                                  StringRef Kind,
1315                                                  StringRef Value) const {
1316   AttrBuilder B(C);
1317   B.addAttribute(Kind, Value);
1318   return addAttributesAtIndex(C, Index, B);
1319 }
1320 
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute A) const1321 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1322                                                  Attribute A) const {
1323   AttrBuilder B(C);
1324   B.addAttribute(A);
1325   return addAttributesAtIndex(C, Index, B);
1326 }
1327 
setAttributesAtIndex(LLVMContext & C,unsigned Index,AttributeSet Attrs) const1328 AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1329                                                   unsigned Index,
1330                                                   AttributeSet Attrs) const {
1331   Index = attrIdxToArrayIdx(Index);
1332   SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1333   if (Index >= AttrSets.size())
1334     AttrSets.resize(Index + 1);
1335   AttrSets[Index] = Attrs;
1336 
1337   // Remove trailing empty attribute sets.
1338   while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1339     AttrSets.pop_back();
1340   if (AttrSets.empty())
1341     return {};
1342   return AttributeList::getImpl(C, AttrSets);
1343 }
1344 
addAttributesAtIndex(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1345 AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1346                                                   unsigned Index,
1347                                                   const AttrBuilder &B) const {
1348   if (!B.hasAttributes())
1349     return *this;
1350 
1351   if (!pImpl)
1352     return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1353 
1354   AttrBuilder Merged(C, getAttributes(Index));
1355   Merged.merge(B);
1356   return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1357 }
1358 
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const1359 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1360                                                ArrayRef<unsigned> ArgNos,
1361                                                Attribute A) const {
1362   assert(llvm::is_sorted(ArgNos));
1363 
1364   SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1365   unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1366   if (MaxIndex >= AttrSets.size())
1367     AttrSets.resize(MaxIndex + 1);
1368 
1369   for (unsigned ArgNo : ArgNos) {
1370     unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1371     AttrBuilder B(C, AttrSets[Index]);
1372     B.addAttribute(A);
1373     AttrSets[Index] = AttributeSet::get(C, B);
1374   }
1375 
1376   return getImpl(C, AttrSets);
1377 }
1378 
1379 AttributeList
removeAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1380 AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1381                                       Attribute::AttrKind Kind) const {
1382   AttributeSet Attrs = getAttributes(Index);
1383   AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1384   if (Attrs == NewAttrs)
1385     return *this;
1386   return setAttributesAtIndex(C, Index, NewAttrs);
1387 }
1388 
removeAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind) const1389 AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1390                                                     unsigned Index,
1391                                                     StringRef Kind) const {
1392   AttributeSet Attrs = getAttributes(Index);
1393   AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1394   if (Attrs == NewAttrs)
1395     return *this;
1396   return setAttributesAtIndex(C, Index, NewAttrs);
1397 }
1398 
removeAttributesAtIndex(LLVMContext & C,unsigned Index,const AttributeMask & AttrsToRemove) const1399 AttributeList AttributeList::removeAttributesAtIndex(
1400     LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1401   AttributeSet Attrs = getAttributes(Index);
1402   AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1403   // If nothing was removed, return the original list.
1404   if (Attrs == NewAttrs)
1405     return *this;
1406   return setAttributesAtIndex(C, Index, NewAttrs);
1407 }
1408 
1409 AttributeList
removeAttributesAtIndex(LLVMContext & C,unsigned WithoutIndex) const1410 AttributeList::removeAttributesAtIndex(LLVMContext &C,
1411                                        unsigned WithoutIndex) const {
1412   if (!pImpl)
1413     return {};
1414   if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1415     return *this;
1416   return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1417 }
1418 
addDereferenceableRetAttr(LLVMContext & C,uint64_t Bytes) const1419 AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1420                                                        uint64_t Bytes) const {
1421   AttrBuilder B(C);
1422   B.addDereferenceableAttr(Bytes);
1423   return addRetAttributes(C, B);
1424 }
1425 
addDereferenceableParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1426 AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1427                                                          unsigned Index,
1428                                                          uint64_t Bytes) const {
1429   AttrBuilder B(C);
1430   B.addDereferenceableAttr(Bytes);
1431   return addParamAttributes(C, Index, B);
1432 }
1433 
1434 AttributeList
addDereferenceableOrNullParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1435 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1436                                                  uint64_t Bytes) const {
1437   AttrBuilder B(C);
1438   B.addDereferenceableOrNullAttr(Bytes);
1439   return addParamAttributes(C, Index, B);
1440 }
1441 
addAllocSizeParamAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)1442 AttributeList AttributeList::addAllocSizeParamAttr(
1443     LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1444     const std::optional<unsigned> &NumElemsArg) {
1445   AttrBuilder B(C);
1446   B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1447   return addParamAttributes(C, Index, B);
1448 }
1449 
1450 //===----------------------------------------------------------------------===//
1451 // AttributeList Accessor Methods
1452 //===----------------------------------------------------------------------===//
1453 
getParamAttrs(unsigned ArgNo) const1454 AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1455   return getAttributes(ArgNo + FirstArgIndex);
1456 }
1457 
getRetAttrs() const1458 AttributeSet AttributeList::getRetAttrs() const {
1459   return getAttributes(ReturnIndex);
1460 }
1461 
getFnAttrs() const1462 AttributeSet AttributeList::getFnAttrs() const {
1463   return getAttributes(FunctionIndex);
1464 }
1465 
hasAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1466 bool AttributeList::hasAttributeAtIndex(unsigned Index,
1467                                         Attribute::AttrKind Kind) const {
1468   return getAttributes(Index).hasAttribute(Kind);
1469 }
1470 
hasAttributeAtIndex(unsigned Index,StringRef Kind) const1471 bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1472   return getAttributes(Index).hasAttribute(Kind);
1473 }
1474 
hasAttributesAtIndex(unsigned Index) const1475 bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1476   return getAttributes(Index).hasAttributes();
1477 }
1478 
hasFnAttr(Attribute::AttrKind Kind) const1479 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1480   return pImpl && pImpl->hasFnAttribute(Kind);
1481 }
1482 
hasFnAttr(StringRef Kind) const1483 bool AttributeList::hasFnAttr(StringRef Kind) const {
1484   return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1485 }
1486 
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1487 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1488                                      unsigned *Index) const {
1489   return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1490 }
1491 
getAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1492 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1493                                              Attribute::AttrKind Kind) const {
1494   return getAttributes(Index).getAttribute(Kind);
1495 }
1496 
getAttributeAtIndex(unsigned Index,StringRef Kind) const1497 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1498                                              StringRef Kind) const {
1499   return getAttributes(Index).getAttribute(Kind);
1500 }
1501 
getRetAlignment() const1502 MaybeAlign AttributeList::getRetAlignment() const {
1503   return getAttributes(ReturnIndex).getAlignment();
1504 }
1505 
getParamAlignment(unsigned ArgNo) const1506 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1507   return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1508 }
1509 
getParamStackAlignment(unsigned ArgNo) const1510 MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1511   return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1512 }
1513 
getParamByValType(unsigned Index) const1514 Type *AttributeList::getParamByValType(unsigned Index) const {
1515   return getAttributes(Index+FirstArgIndex).getByValType();
1516 }
1517 
getParamStructRetType(unsigned Index) const1518 Type *AttributeList::getParamStructRetType(unsigned Index) const {
1519   return getAttributes(Index + FirstArgIndex).getStructRetType();
1520 }
1521 
getParamByRefType(unsigned Index) const1522 Type *AttributeList::getParamByRefType(unsigned Index) const {
1523   return getAttributes(Index + FirstArgIndex).getByRefType();
1524 }
1525 
getParamPreallocatedType(unsigned Index) const1526 Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1527   return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1528 }
1529 
getParamInAllocaType(unsigned Index) const1530 Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1531   return getAttributes(Index + FirstArgIndex).getInAllocaType();
1532 }
1533 
getParamElementType(unsigned Index) const1534 Type *AttributeList::getParamElementType(unsigned Index) const {
1535   return getAttributes(Index + FirstArgIndex).getElementType();
1536 }
1537 
getFnStackAlignment() const1538 MaybeAlign AttributeList::getFnStackAlignment() const {
1539   return getFnAttrs().getStackAlignment();
1540 }
1541 
getRetStackAlignment() const1542 MaybeAlign AttributeList::getRetStackAlignment() const {
1543   return getRetAttrs().getStackAlignment();
1544 }
1545 
getRetDereferenceableBytes() const1546 uint64_t AttributeList::getRetDereferenceableBytes() const {
1547   return getRetAttrs().getDereferenceableBytes();
1548 }
1549 
getParamDereferenceableBytes(unsigned Index) const1550 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1551   return getParamAttrs(Index).getDereferenceableBytes();
1552 }
1553 
getRetDereferenceableOrNullBytes() const1554 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1555   return getRetAttrs().getDereferenceableOrNullBytes();
1556 }
1557 
1558 uint64_t
getParamDereferenceableOrNullBytes(unsigned Index) const1559 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1560   return getParamAttrs(Index).getDereferenceableOrNullBytes();
1561 }
1562 
getUWTableKind() const1563 UWTableKind AttributeList::getUWTableKind() const {
1564   return getFnAttrs().getUWTableKind();
1565 }
1566 
getAllocKind() const1567 AllocFnKind AttributeList::getAllocKind() const {
1568   return getFnAttrs().getAllocKind();
1569 }
1570 
getMemoryEffects() const1571 MemoryEffects AttributeList::getMemoryEffects() const {
1572   return getFnAttrs().getMemoryEffects();
1573 }
1574 
getAsString(unsigned Index,bool InAttrGrp) const1575 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1576   return getAttributes(Index).getAsString(InAttrGrp);
1577 }
1578 
getAttributes(unsigned Index) const1579 AttributeSet AttributeList::getAttributes(unsigned Index) const {
1580   Index = attrIdxToArrayIdx(Index);
1581   if (!pImpl || Index >= getNumAttrSets())
1582     return {};
1583   return pImpl->begin()[Index];
1584 }
1585 
hasParentContext(LLVMContext & C) const1586 bool AttributeList::hasParentContext(LLVMContext &C) const {
1587   assert(!isEmpty() && "an empty attribute list has no parent context");
1588   FoldingSetNodeID ID;
1589   pImpl->Profile(ID);
1590   void *Unused;
1591   return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1592 }
1593 
begin() const1594 AttributeList::iterator AttributeList::begin() const {
1595   return pImpl ? pImpl->begin() : nullptr;
1596 }
1597 
end() const1598 AttributeList::iterator AttributeList::end() const {
1599   return pImpl ? pImpl->end() : nullptr;
1600 }
1601 
1602 //===----------------------------------------------------------------------===//
1603 // AttributeList Introspection Methods
1604 //===----------------------------------------------------------------------===//
1605 
getNumAttrSets() const1606 unsigned AttributeList::getNumAttrSets() const {
1607   return pImpl ? pImpl->NumAttrSets : 0;
1608 }
1609 
print(raw_ostream & O) const1610 void AttributeList::print(raw_ostream &O) const {
1611   O << "AttributeList[\n";
1612 
1613   for (unsigned i : indexes()) {
1614     if (!getAttributes(i).hasAttributes())
1615       continue;
1616     O << "  { ";
1617     switch (i) {
1618     case AttrIndex::ReturnIndex:
1619       O << "return";
1620       break;
1621     case AttrIndex::FunctionIndex:
1622       O << "function";
1623       break;
1624     default:
1625       O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1626     }
1627     O << " => " << getAsString(i) << " }\n";
1628   }
1629 
1630   O << "]\n";
1631 }
1632 
1633 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1634 LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
1635 #endif
1636 
1637 //===----------------------------------------------------------------------===//
1638 // AttrBuilder Method Implementations
1639 //===----------------------------------------------------------------------===//
1640 
AttrBuilder(LLVMContext & Ctx,AttributeSet AS)1641 AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
1642   append_range(Attrs, AS);
1643   assert(is_sorted(Attrs) && "AttributeSet should be sorted");
1644 }
1645 
clear()1646 void AttrBuilder::clear() { Attrs.clear(); }
1647 
1648 /// Attribute comparator that only compares attribute keys. Enum attributes are
1649 /// sorted before string attributes.
1650 struct AttributeComparator {
operator ()AttributeComparator1651   bool operator()(Attribute A0, Attribute A1) const {
1652     bool A0IsString = A0.isStringAttribute();
1653     bool A1IsString = A1.isStringAttribute();
1654     if (A0IsString) {
1655       if (A1IsString)
1656         return A0.getKindAsString() < A1.getKindAsString();
1657       else
1658         return false;
1659     }
1660     if (A1IsString)
1661       return true;
1662     return A0.getKindAsEnum() < A1.getKindAsEnum();
1663   }
operator ()AttributeComparator1664   bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
1665     if (A0.isStringAttribute())
1666       return false;
1667     return A0.getKindAsEnum() < Kind;
1668   }
operator ()AttributeComparator1669   bool operator()(Attribute A0, StringRef Kind) const {
1670     if (A0.isStringAttribute())
1671       return A0.getKindAsString() < Kind;
1672     return true;
1673   }
1674 };
1675 
1676 template <typename K>
addAttributeImpl(SmallVectorImpl<Attribute> & Attrs,K Kind,Attribute Attr)1677 static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
1678                              Attribute Attr) {
1679   auto It = lower_bound(Attrs, Kind, AttributeComparator());
1680   if (It != Attrs.end() && It->hasAttribute(Kind))
1681     std::swap(*It, Attr);
1682   else
1683     Attrs.insert(It, Attr);
1684 }
1685 
addAttribute(Attribute Attr)1686 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1687   if (Attr.isStringAttribute())
1688     addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1689   else
1690     addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
1691   return *this;
1692 }
1693 
addAttribute(Attribute::AttrKind Kind)1694 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
1695   addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
1696   return *this;
1697 }
1698 
addAttribute(StringRef A,StringRef V)1699 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1700   addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
1701   return *this;
1702 }
1703 
removeAttribute(Attribute::AttrKind Val)1704 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1705   assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1706   auto It = lower_bound(Attrs, Val, AttributeComparator());
1707   if (It != Attrs.end() && It->hasAttribute(Val))
1708     Attrs.erase(It);
1709   return *this;
1710 }
1711 
removeAttribute(StringRef A)1712 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1713   auto It = lower_bound(Attrs, A, AttributeComparator());
1714   if (It != Attrs.end() && It->hasAttribute(A))
1715     Attrs.erase(It);
1716   return *this;
1717 }
1718 
1719 std::optional<uint64_t>
getRawIntAttr(Attribute::AttrKind Kind) const1720 AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
1721   assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
1722   Attribute A = getAttribute(Kind);
1723   if (A.isValid())
1724     return A.getValueAsInt();
1725   return std::nullopt;
1726 }
1727 
addRawIntAttr(Attribute::AttrKind Kind,uint64_t Value)1728 AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
1729                                         uint64_t Value) {
1730   return addAttribute(Attribute::get(Ctx, Kind, Value));
1731 }
1732 
1733 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1734 AttrBuilder::getAllocSizeArgs() const {
1735   Attribute A = getAttribute(Attribute::AllocSize);
1736   if (A.isValid())
1737     return A.getAllocSizeArgs();
1738   return std::nullopt;
1739 }
1740 
addAlignmentAttr(MaybeAlign Align)1741 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1742   if (!Align)
1743     return *this;
1744 
1745   assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1746   return addRawIntAttr(Attribute::Alignment, Align->value());
1747 }
1748 
addStackAlignmentAttr(MaybeAlign Align)1749 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1750   // Default alignment, allow the target to define how to align it.
1751   if (!Align)
1752     return *this;
1753 
1754   assert(*Align <= 0x100 && "Alignment too large.");
1755   return addRawIntAttr(Attribute::StackAlignment, Align->value());
1756 }
1757 
addDereferenceableAttr(uint64_t Bytes)1758 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1759   if (Bytes == 0) return *this;
1760 
1761   return addRawIntAttr(Attribute::Dereferenceable, Bytes);
1762 }
1763 
addDereferenceableOrNullAttr(uint64_t Bytes)1764 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1765   if (Bytes == 0)
1766     return *this;
1767 
1768   return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
1769 }
1770 
1771 AttrBuilder &
addAllocSizeAttr(unsigned ElemSize,const std::optional<unsigned> & NumElems)1772 AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1773                               const std::optional<unsigned> &NumElems) {
1774   return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1775 }
1776 
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1777 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1778   // (0, 0) is our "not present" value, so we need to check for it here.
1779   assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1780   return addRawIntAttr(Attribute::AllocSize, RawArgs);
1781 }
1782 
addVScaleRangeAttr(unsigned MinValue,std::optional<unsigned> MaxValue)1783 AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
1784                                              std::optional<unsigned> MaxValue) {
1785   return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
1786 }
1787 
addVScaleRangeAttrFromRawRepr(uint64_t RawArgs)1788 AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
1789   // (0, 0) is not present hence ignore this case
1790   if (RawArgs == 0)
1791     return *this;
1792 
1793   return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1794 }
1795 
addUWTableAttr(UWTableKind Kind)1796 AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
1797   if (Kind == UWTableKind::None)
1798     return *this;
1799   return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
1800 }
1801 
addMemoryAttr(MemoryEffects ME)1802 AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
1803   return addRawIntAttr(Attribute::Memory, ME.toIntValue());
1804 }
1805 
addAllocKindAttr(AllocFnKind Kind)1806 AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
1807   return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
1808 }
1809 
getTypeAttr(Attribute::AttrKind Kind) const1810 Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
1811   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
1812   Attribute A = getAttribute(Kind);
1813   return A.isValid() ? A.getValueAsType() : nullptr;
1814 }
1815 
addTypeAttr(Attribute::AttrKind Kind,Type * Ty)1816 AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
1817   return addAttribute(Attribute::get(Ctx, Kind, Ty));
1818 }
1819 
addByValAttr(Type * Ty)1820 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
1821   return addTypeAttr(Attribute::ByVal, Ty);
1822 }
1823 
addStructRetAttr(Type * Ty)1824 AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
1825   return addTypeAttr(Attribute::StructRet, Ty);
1826 }
1827 
addByRefAttr(Type * Ty)1828 AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
1829   return addTypeAttr(Attribute::ByRef, Ty);
1830 }
1831 
addPreallocatedAttr(Type * Ty)1832 AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
1833   return addTypeAttr(Attribute::Preallocated, Ty);
1834 }
1835 
addInAllocaAttr(Type * Ty)1836 AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
1837   return addTypeAttr(Attribute::InAlloca, Ty);
1838 }
1839 
merge(const AttrBuilder & B)1840 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1841   // TODO: Could make this O(n) as we're merging two sorted lists.
1842   for (const auto &I : B.attrs())
1843     addAttribute(I);
1844 
1845   return *this;
1846 }
1847 
remove(const AttributeMask & AM)1848 AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
1849   erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
1850   return *this;
1851 }
1852 
overlaps(const AttributeMask & AM) const1853 bool AttrBuilder::overlaps(const AttributeMask &AM) const {
1854   return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
1855 }
1856 
getAttribute(Attribute::AttrKind A) const1857 Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
1858   assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
1859   auto It = lower_bound(Attrs, A, AttributeComparator());
1860   if (It != Attrs.end() && It->hasAttribute(A))
1861     return *It;
1862   return {};
1863 }
1864 
getAttribute(StringRef A) const1865 Attribute AttrBuilder::getAttribute(StringRef A) const {
1866   auto It = lower_bound(Attrs, A, AttributeComparator());
1867   if (It != Attrs.end() && It->hasAttribute(A))
1868     return *It;
1869   return {};
1870 }
1871 
contains(Attribute::AttrKind A) const1872 bool AttrBuilder::contains(Attribute::AttrKind A) const {
1873   return getAttribute(A).isValid();
1874 }
1875 
contains(StringRef A) const1876 bool AttrBuilder::contains(StringRef A) const {
1877   return getAttribute(A).isValid();
1878 }
1879 
operator ==(const AttrBuilder & B) const1880 bool AttrBuilder::operator==(const AttrBuilder &B) const {
1881   return Attrs == B.Attrs;
1882 }
1883 
1884 //===----------------------------------------------------------------------===//
1885 // AttributeFuncs Function Defintions
1886 //===----------------------------------------------------------------------===//
1887 
1888 /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty,AttributeSafetyKind ASK)1889 AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
1890                                                AttributeSafetyKind ASK) {
1891   AttributeMask Incompatible;
1892 
1893   if (!Ty->isIntegerTy()) {
1894     // Attributes that only apply to integers.
1895     if (ASK & ASK_SAFE_TO_DROP)
1896       Incompatible.addAttribute(Attribute::AllocAlign);
1897     if (ASK & ASK_UNSAFE_TO_DROP)
1898       Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
1899   }
1900 
1901   if (!Ty->isPointerTy()) {
1902     // Attributes that only apply to pointers.
1903     if (ASK & ASK_SAFE_TO_DROP)
1904       Incompatible.addAttribute(Attribute::NoAlias)
1905           .addAttribute(Attribute::NoCapture)
1906           .addAttribute(Attribute::NonNull)
1907           .addAttribute(Attribute::ReadNone)
1908           .addAttribute(Attribute::ReadOnly)
1909           .addAttribute(Attribute::Dereferenceable)
1910           .addAttribute(Attribute::DereferenceableOrNull);
1911     if (ASK & ASK_UNSAFE_TO_DROP)
1912       Incompatible.addAttribute(Attribute::Nest)
1913           .addAttribute(Attribute::SwiftError)
1914           .addAttribute(Attribute::Preallocated)
1915           .addAttribute(Attribute::InAlloca)
1916           .addAttribute(Attribute::ByVal)
1917           .addAttribute(Attribute::StructRet)
1918           .addAttribute(Attribute::ByRef)
1919           .addAttribute(Attribute::ElementType)
1920           .addAttribute(Attribute::AllocatedPointer);
1921   }
1922 
1923     // Attributes that only apply to pointers or vectors of pointers.
1924   if (!Ty->isPtrOrPtrVectorTy()) {
1925     if (ASK & ASK_SAFE_TO_DROP)
1926       Incompatible.addAttribute(Attribute::Alignment);
1927   }
1928 
1929   // Some attributes can apply to all "values" but there are no `void` values.
1930   if (Ty->isVoidTy()) {
1931     if (ASK & ASK_SAFE_TO_DROP)
1932       Incompatible.addAttribute(Attribute::NoUndef);
1933   }
1934 
1935   return Incompatible;
1936 }
1937 
getUBImplyingAttributes()1938 AttributeMask AttributeFuncs::getUBImplyingAttributes() {
1939   AttributeMask AM;
1940   AM.addAttribute(Attribute::NoUndef);
1941   AM.addAttribute(Attribute::Dereferenceable);
1942   AM.addAttribute(Attribute::DereferenceableOrNull);
1943   return AM;
1944 }
1945 
1946 template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)1947 static bool isEqual(const Function &Caller, const Function &Callee) {
1948   return Caller.getFnAttribute(AttrClass::getKind()) ==
1949          Callee.getFnAttribute(AttrClass::getKind());
1950 }
1951 
1952 /// Compute the logical AND of the attributes of the caller and the
1953 /// callee.
1954 ///
1955 /// This function sets the caller's attribute to false if the callee's attribute
1956 /// is false.
1957 template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)1958 static void setAND(Function &Caller, const Function &Callee) {
1959   if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
1960       !AttrClass::isSet(Callee, AttrClass::getKind()))
1961     AttrClass::set(Caller, AttrClass::getKind(), false);
1962 }
1963 
1964 /// Compute the logical OR of the attributes of the caller and the
1965 /// callee.
1966 ///
1967 /// This function sets the caller's attribute to true if the callee's attribute
1968 /// is true.
1969 template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)1970 static void setOR(Function &Caller, const Function &Callee) {
1971   if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
1972       AttrClass::isSet(Callee, AttrClass::getKind()))
1973     AttrClass::set(Caller, AttrClass::getKind(), true);
1974 }
1975 
1976 /// If the inlined function had a higher stack protection level than the
1977 /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)1978 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1979   // If the calling function has *no* stack protection level (e.g. it was built
1980   // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
1981   // change it as that could change the program's semantics.
1982   if (!Caller.hasStackProtectorFnAttr())
1983     return;
1984 
1985   // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1986   // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1987   // clutter to the IR.
1988   AttributeMask OldSSPAttr;
1989   OldSSPAttr.addAttribute(Attribute::StackProtect)
1990       .addAttribute(Attribute::StackProtectStrong)
1991       .addAttribute(Attribute::StackProtectReq);
1992 
1993   if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1994     Caller.removeFnAttrs(OldSSPAttr);
1995     Caller.addFnAttr(Attribute::StackProtectReq);
1996   } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
1997              !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1998     Caller.removeFnAttrs(OldSSPAttr);
1999     Caller.addFnAttr(Attribute::StackProtectStrong);
2000   } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2001              !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2002              !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2003     Caller.addFnAttr(Attribute::StackProtect);
2004 }
2005 
2006 /// If the inlined function required stack probes, then ensure that
2007 /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)2008 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2009   if (!Caller.hasFnAttribute("probe-stack") &&
2010       Callee.hasFnAttribute("probe-stack")) {
2011     Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2012   }
2013 }
2014 
2015 /// If the inlined function defines the size of guard region
2016 /// on the stack, then ensure that the calling function defines a guard region
2017 /// that is no larger.
2018 static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)2019 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
2020   Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2021   if (CalleeAttr.isValid()) {
2022     Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2023     if (CallerAttr.isValid()) {
2024       uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2025       CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2026       CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2027 
2028       if (CallerStackProbeSize > CalleeStackProbeSize) {
2029         Caller.addFnAttr(CalleeAttr);
2030       }
2031     } else {
2032       Caller.addFnAttr(CalleeAttr);
2033     }
2034   }
2035 }
2036 
2037 /// If the inlined function defines a min legal vector width, then ensure
2038 /// the calling function has the same or larger min legal vector width. If the
2039 /// caller has the attribute, but the callee doesn't, we need to remove the
2040 /// attribute from the caller since we can't make any guarantees about the
2041 /// caller's requirements.
2042 /// This function is called after the inlining decision has been made so we have
2043 /// to merge the attribute this way. Heuristics that would use
2044 /// min-legal-vector-width to determine inline compatibility would need to be
2045 /// handled as part of inline cost analysis.
2046 static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)2047 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
2048   Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2049   if (CallerAttr.isValid()) {
2050     Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2051     if (CalleeAttr.isValid()) {
2052       uint64_t CallerVectorWidth, CalleeVectorWidth;
2053       CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2054       CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2055       if (CallerVectorWidth < CalleeVectorWidth)
2056         Caller.addFnAttr(CalleeAttr);
2057     } else {
2058       // If the callee doesn't have the attribute then we don't know anything
2059       // and must drop the attribute from the caller.
2060       Caller.removeFnAttr("min-legal-vector-width");
2061     }
2062   }
2063 }
2064 
2065 /// If the inlined function has null_pointer_is_valid attribute,
2066 /// set this attribute in the caller post inlining.
2067 static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)2068 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2069   if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2070     Caller.addFnAttr(Attribute::NullPointerIsValid);
2071   }
2072 }
2073 
2074 struct EnumAttr {
isSetEnumAttr2075   static bool isSet(const Function &Fn,
2076                     Attribute::AttrKind Kind) {
2077     return Fn.hasFnAttribute(Kind);
2078   }
2079 
setEnumAttr2080   static void set(Function &Fn,
2081                   Attribute::AttrKind Kind, bool Val) {
2082     if (Val)
2083       Fn.addFnAttr(Kind);
2084     else
2085       Fn.removeFnAttr(Kind);
2086   }
2087 };
2088 
2089 struct StrBoolAttr {
isSetStrBoolAttr2090   static bool isSet(const Function &Fn,
2091                     StringRef Kind) {
2092     auto A = Fn.getFnAttribute(Kind);
2093     return A.getValueAsString().equals("true");
2094   }
2095 
setStrBoolAttr2096   static void set(Function &Fn,
2097                   StringRef Kind, bool Val) {
2098     Fn.addFnAttr(Kind, Val ? "true" : "false");
2099   }
2100 };
2101 
2102 #define GET_ATTR_NAMES
2103 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
2104   struct ENUM_NAME##Attr : EnumAttr {                                          \
2105     static enum Attribute::AttrKind getKind() {                                \
2106       return llvm::Attribute::ENUM_NAME;                                       \
2107     }                                                                          \
2108   };
2109 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME)                             \
2110   struct ENUM_NAME##Attr : StrBoolAttr {                                       \
2111     static StringRef getKind() { return #DISPLAY_NAME; }                       \
2112   };
2113 #include "llvm/IR/Attributes.inc"
2114 
2115 #define GET_ATTR_COMPAT_FUNC
2116 #include "llvm/IR/Attributes.inc"
2117 
areInlineCompatible(const Function & Caller,const Function & Callee)2118 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2119                                          const Function &Callee) {
2120   return hasCompatibleFnAttrs(Caller, Callee);
2121 }
2122 
areOutlineCompatible(const Function & A,const Function & B)2123 bool AttributeFuncs::areOutlineCompatible(const Function &A,
2124                                           const Function &B) {
2125   return hasCompatibleFnAttrs(A, B);
2126 }
2127 
mergeAttributesForInlining(Function & Caller,const Function & Callee)2128 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2129                                                 const Function &Callee) {
2130   mergeFnAttrs(Caller, Callee);
2131 }
2132 
mergeAttributesForOutlining(Function & Base,const Function & ToMerge)2133 void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2134                                                 const Function &ToMerge) {
2135 
2136   // We merge functions so that they meet the most general case.
2137   // For example, if the NoNansFPMathAttr is set in one function, but not in
2138   // the other, in the merged function we can say that the NoNansFPMathAttr
2139   // is not set.
2140   // However if we have the SpeculativeLoadHardeningAttr set true in one
2141   // function, but not the other, we make sure that the function retains
2142   // that aspect in the merged function.
2143   mergeFnAttrs(Base, ToMerge);
2144 }
2145 
updateMinLegalVectorWidthAttr(Function & Fn,uint64_t Width)2146 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2147                                                    uint64_t Width) {
2148   Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2149   if (Attr.isValid()) {
2150     uint64_t OldWidth;
2151     Attr.getValueAsString().getAsInteger(0, OldWidth);
2152     if (Width > OldWidth)
2153       Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2154   }
2155 }
2156