xref: /freebsd/contrib/llvm-project/llvm/lib/IR/Attributes.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/AttributeMask.h"
27 #include "llvm/IR/ConstantRange.h"
28 #include "llvm/IR/ConstantRangeList.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/LLVMContext.h"
31 #include "llvm/IR/Operator.h"
32 #include "llvm/IR/Type.h"
33 #include "llvm/Support/Compiler.h"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Support/ModRef.h"
36 #include "llvm/Support/raw_ostream.h"
37 #include <algorithm>
38 #include <cassert>
39 #include <cstddef>
40 #include <cstdint>
41 #include <limits>
42 #include <optional>
43 #include <string>
44 #include <tuple>
45 #include <utility>
46 
47 using namespace llvm;
48 
49 //===----------------------------------------------------------------------===//
50 // Attribute Construction Methods
51 //===----------------------------------------------------------------------===//
52 
53 // allocsize has two integer arguments, but because they're both 32 bits, we can
54 // pack them into one 64-bit value, at the cost of making said value
55 // nonsensical.
56 //
57 // In order to do this, we need to reserve one value of the second (optional)
58 // allocsize argument to signify "not present."
59 static const unsigned AllocSizeNumElemsNotPresent = -1;
60 
packAllocSizeArgs(unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)61 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
62                                   const std::optional<unsigned> &NumElemsArg) {
63   assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
64          "Attempting to pack a reserved value");
65 
66   return uint64_t(ElemSizeArg) << 32 |
67          NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
68 }
69 
70 static std::pair<unsigned, std::optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)71 unpackAllocSizeArgs(uint64_t Num) {
72   unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
73   unsigned ElemSizeArg = Num >> 32;
74 
75   std::optional<unsigned> NumElemsArg;
76   if (NumElems != AllocSizeNumElemsNotPresent)
77     NumElemsArg = NumElems;
78   return std::make_pair(ElemSizeArg, NumElemsArg);
79 }
80 
packVScaleRangeArgs(unsigned MinValue,std::optional<unsigned> MaxValue)81 static uint64_t packVScaleRangeArgs(unsigned MinValue,
82                                     std::optional<unsigned> MaxValue) {
83   return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
84 }
85 
86 static std::pair<unsigned, std::optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value)87 unpackVScaleRangeArgs(uint64_t Value) {
88   unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
89   unsigned MinValue = Value >> 32;
90 
91   return std::make_pair(MinValue,
92                         MaxValue > 0 ? MaxValue : std::optional<unsigned>());
93 }
94 
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)95 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
96                          uint64_t Val) {
97   bool IsIntAttr = Attribute::isIntAttrKind(Kind);
98   assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
99          "Not an enum or int attribute");
100 
101   LLVMContextImpl *pImpl = Context.pImpl;
102   FoldingSetNodeID ID;
103   ID.AddInteger(Kind);
104   if (IsIntAttr)
105     ID.AddInteger(Val);
106   else
107     assert(Val == 0 && "Value must be zero for enum attributes");
108 
109   void *InsertPoint;
110   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
111 
112   if (!PA) {
113     // If we didn't find any existing attributes of the same shape then create a
114     // new one and insert it.
115     if (!IsIntAttr)
116       PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
117     else
118       PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
119     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
120   }
121 
122   // Return the Attribute that we found or created.
123   return Attribute(PA);
124 }
125 
get(LLVMContext & Context,StringRef Kind,StringRef Val)126 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
127   LLVMContextImpl *pImpl = Context.pImpl;
128   FoldingSetNodeID ID;
129   ID.AddString(Kind);
130   if (!Val.empty()) ID.AddString(Val);
131 
132   void *InsertPoint;
133   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
134 
135   if (!PA) {
136     // If we didn't find any existing attributes of the same shape then create a
137     // new one and insert it.
138     void *Mem =
139         pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
140                               alignof(StringAttributeImpl));
141     PA = new (Mem) StringAttributeImpl(Kind, Val);
142     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
143   }
144 
145   // Return the Attribute that we found or created.
146   return Attribute(PA);
147 }
148 
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)149 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
150                          Type *Ty) {
151   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
152   LLVMContextImpl *pImpl = Context.pImpl;
153   FoldingSetNodeID ID;
154   ID.AddInteger(Kind);
155   ID.AddPointer(Ty);
156 
157   void *InsertPoint;
158   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
159 
160   if (!PA) {
161     // If we didn't find any existing attributes of the same shape then create a
162     // new one and insert it.
163     PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
164     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
165   }
166 
167   // Return the Attribute that we found or created.
168   return Attribute(PA);
169 }
170 
get(LLVMContext & Context,Attribute::AttrKind Kind,const ConstantRange & CR)171 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
172                          const ConstantRange &CR) {
173   assert(Attribute::isConstantRangeAttrKind(Kind) &&
174          "Not a ConstantRange attribute");
175   assert(!CR.isFullSet() && "ConstantRange attribute must not be full");
176   LLVMContextImpl *pImpl = Context.pImpl;
177   FoldingSetNodeID ID;
178   ID.AddInteger(Kind);
179   CR.getLower().Profile(ID);
180   CR.getUpper().Profile(ID);
181 
182   void *InsertPoint;
183   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
184 
185   if (!PA) {
186     // If we didn't find any existing attributes of the same shape then create a
187     // new one and insert it.
188     PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
189         ConstantRangeAttributeImpl(Kind, CR);
190     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
191   }
192 
193   // Return the Attribute that we found or created.
194   return Attribute(PA);
195 }
196 
get(LLVMContext & Context,Attribute::AttrKind Kind,ArrayRef<ConstantRange> Val)197 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
198                          ArrayRef<ConstantRange> Val) {
199   assert(Attribute::isConstantRangeListAttrKind(Kind) &&
200          "Not a ConstantRangeList attribute");
201   LLVMContextImpl *pImpl = Context.pImpl;
202   FoldingSetNodeID ID;
203   ID.AddInteger(Kind);
204   ID.AddInteger(Val.size());
205   for (auto &CR : Val) {
206     CR.getLower().Profile(ID);
207     CR.getUpper().Profile(ID);
208   }
209 
210   void *InsertPoint;
211   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
212 
213   if (!PA) {
214     // If we didn't find any existing attributes of the same shape then create a
215     // new one and insert it.
216     // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
217     // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
218     // allocation and record the allocated pointer in
219     // `ConstantRangeListAttributes`. LLVMContext destructor will call the
220     // destructor of the allocated pointer explicitly.
221     void *Mem = pImpl->Alloc.Allocate(
222         ConstantRangeListAttributeImpl::totalSizeToAlloc(Val),
223         alignof(ConstantRangeListAttributeImpl));
224     PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
225     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
226     pImpl->ConstantRangeListAttributes.push_back(
227         reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
228   }
229 
230   // Return the Attribute that we found or created.
231   return Attribute(PA);
232 }
233 
getWithAlignment(LLVMContext & Context,Align A)234 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
235   assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
236   return get(Context, Alignment, A.value());
237 }
238 
getWithStackAlignment(LLVMContext & Context,Align A)239 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
240   assert(A <= 0x100 && "Alignment too large.");
241   return get(Context, StackAlignment, A.value());
242 }
243 
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)244 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
245                                                 uint64_t Bytes) {
246   assert(Bytes && "Bytes must be non-zero.");
247   return get(Context, Dereferenceable, Bytes);
248 }
249 
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)250 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
251                                                        uint64_t Bytes) {
252   assert(Bytes && "Bytes must be non-zero.");
253   return get(Context, DereferenceableOrNull, Bytes);
254 }
255 
getWithByValType(LLVMContext & Context,Type * Ty)256 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
257   return get(Context, ByVal, Ty);
258 }
259 
getWithStructRetType(LLVMContext & Context,Type * Ty)260 Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
261   return get(Context, StructRet, Ty);
262 }
263 
getWithByRefType(LLVMContext & Context,Type * Ty)264 Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
265   return get(Context, ByRef, Ty);
266 }
267 
getWithPreallocatedType(LLVMContext & Context,Type * Ty)268 Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
269   return get(Context, Preallocated, Ty);
270 }
271 
getWithInAllocaType(LLVMContext & Context,Type * Ty)272 Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
273   return get(Context, InAlloca, Ty);
274 }
275 
getWithUWTableKind(LLVMContext & Context,UWTableKind Kind)276 Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
277                                         UWTableKind Kind) {
278   return get(Context, UWTable, uint64_t(Kind));
279 }
280 
getWithMemoryEffects(LLVMContext & Context,MemoryEffects ME)281 Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
282                                           MemoryEffects ME) {
283   return get(Context, Memory, ME.toIntValue());
284 }
285 
getWithNoFPClass(LLVMContext & Context,FPClassTest ClassMask)286 Attribute Attribute::getWithNoFPClass(LLVMContext &Context,
287                                       FPClassTest ClassMask) {
288   return get(Context, NoFPClass, ClassMask);
289 }
290 
getWithCaptureInfo(LLVMContext & Context,CaptureInfo CI)291 Attribute Attribute::getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI) {
292   return get(Context, Captures, CI.toIntValue());
293 }
294 
295 Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)296 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
297                                 const std::optional<unsigned> &NumElemsArg) {
298   assert(!(ElemSizeArg == 0 && NumElemsArg == 0) &&
299          "Invalid allocsize arguments -- given allocsize(0, 0)");
300   return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
301 }
302 
getWithAllocKind(LLVMContext & Context,AllocFnKind Kind)303 Attribute Attribute::getWithAllocKind(LLVMContext &Context, AllocFnKind Kind) {
304   return get(Context, AllocKind, static_cast<uint64_t>(Kind));
305 }
306 
getWithVScaleRangeArgs(LLVMContext & Context,unsigned MinValue,unsigned MaxValue)307 Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
308                                             unsigned MinValue,
309                                             unsigned MaxValue) {
310   return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
311 }
312 
getAttrKindFromName(StringRef AttrName)313 Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
314   return StringSwitch<Attribute::AttrKind>(AttrName)
315 #define GET_ATTR_NAMES
316 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
317   .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
318 #include "llvm/IR/Attributes.inc"
319       .Default(Attribute::None);
320 }
321 
getNameFromAttrKind(Attribute::AttrKind AttrKind)322 StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
323   switch (AttrKind) {
324 #define GET_ATTR_NAMES
325 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
326   case Attribute::ENUM_NAME:                                                   \
327     return #DISPLAY_NAME;
328 #include "llvm/IR/Attributes.inc"
329   case Attribute::None:
330     return "none";
331   default:
332     llvm_unreachable("invalid Kind");
333   }
334 }
335 
isExistingAttribute(StringRef Name)336 bool Attribute::isExistingAttribute(StringRef Name) {
337   return StringSwitch<bool>(Name)
338 #define GET_ATTR_NAMES
339 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
340 #include "llvm/IR/Attributes.inc"
341       .Default(false);
342 }
343 
344 //===----------------------------------------------------------------------===//
345 // Attribute Accessor Methods
346 //===----------------------------------------------------------------------===//
347 
isEnumAttribute() const348 bool Attribute::isEnumAttribute() const {
349   return pImpl && pImpl->isEnumAttribute();
350 }
351 
isIntAttribute() const352 bool Attribute::isIntAttribute() const {
353   return pImpl && pImpl->isIntAttribute();
354 }
355 
isStringAttribute() const356 bool Attribute::isStringAttribute() const {
357   return pImpl && pImpl->isStringAttribute();
358 }
359 
isTypeAttribute() const360 bool Attribute::isTypeAttribute() const {
361   return pImpl && pImpl->isTypeAttribute();
362 }
363 
isConstantRangeAttribute() const364 bool Attribute::isConstantRangeAttribute() const {
365   return pImpl && pImpl->isConstantRangeAttribute();
366 }
367 
isConstantRangeListAttribute() const368 bool Attribute::isConstantRangeListAttribute() const {
369   return pImpl && pImpl->isConstantRangeListAttribute();
370 }
371 
getKindAsEnum() const372 Attribute::AttrKind Attribute::getKindAsEnum() const {
373   if (!pImpl) return None;
374   assert(hasKindAsEnum() &&
375          "Invalid attribute type to get the kind as an enum!");
376   return pImpl->getKindAsEnum();
377 }
378 
getValueAsInt() const379 uint64_t Attribute::getValueAsInt() const {
380   if (!pImpl) return 0;
381   assert(isIntAttribute() &&
382          "Expected the attribute to be an integer attribute!");
383   return pImpl->getValueAsInt();
384 }
385 
getValueAsBool() const386 bool Attribute::getValueAsBool() const {
387   if (!pImpl) return false;
388   assert(isStringAttribute() &&
389          "Expected the attribute to be a string attribute!");
390   return pImpl->getValueAsBool();
391 }
392 
getKindAsString() const393 StringRef Attribute::getKindAsString() const {
394   if (!pImpl) return {};
395   assert(isStringAttribute() &&
396          "Invalid attribute type to get the kind as a string!");
397   return pImpl->getKindAsString();
398 }
399 
getValueAsString() const400 StringRef Attribute::getValueAsString() const {
401   if (!pImpl) return {};
402   assert(isStringAttribute() &&
403          "Invalid attribute type to get the value as a string!");
404   return pImpl->getValueAsString();
405 }
406 
getValueAsType() const407 Type *Attribute::getValueAsType() const {
408   if (!pImpl) return {};
409   assert(isTypeAttribute() &&
410          "Invalid attribute type to get the value as a type!");
411   return pImpl->getValueAsType();
412 }
413 
getValueAsConstantRange() const414 const ConstantRange &Attribute::getValueAsConstantRange() const {
415   assert(isConstantRangeAttribute() &&
416          "Invalid attribute type to get the value as a ConstantRange!");
417   return pImpl->getValueAsConstantRange();
418 }
419 
getValueAsConstantRangeList() const420 ArrayRef<ConstantRange> Attribute::getValueAsConstantRangeList() const {
421   assert(isConstantRangeListAttribute() &&
422          "Invalid attribute type to get the value as a ConstantRangeList!");
423   return pImpl->getValueAsConstantRangeList();
424 }
425 
hasAttribute(AttrKind Kind) const426 bool Attribute::hasAttribute(AttrKind Kind) const {
427   return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
428 }
429 
hasAttribute(StringRef Kind) const430 bool Attribute::hasAttribute(StringRef Kind) const {
431   if (!isStringAttribute()) return false;
432   return pImpl && pImpl->hasAttribute(Kind);
433 }
434 
getAlignment() const435 MaybeAlign Attribute::getAlignment() const {
436   assert(hasAttribute(Attribute::Alignment) &&
437          "Trying to get alignment from non-alignment attribute!");
438   return MaybeAlign(pImpl->getValueAsInt());
439 }
440 
getStackAlignment() const441 MaybeAlign Attribute::getStackAlignment() const {
442   assert(hasAttribute(Attribute::StackAlignment) &&
443          "Trying to get alignment from non-alignment attribute!");
444   return MaybeAlign(pImpl->getValueAsInt());
445 }
446 
getDereferenceableBytes() const447 uint64_t Attribute::getDereferenceableBytes() const {
448   assert(hasAttribute(Attribute::Dereferenceable) &&
449          "Trying to get dereferenceable bytes from "
450          "non-dereferenceable attribute!");
451   return pImpl->getValueAsInt();
452 }
453 
getDereferenceableOrNullBytes() const454 uint64_t Attribute::getDereferenceableOrNullBytes() const {
455   assert(hasAttribute(Attribute::DereferenceableOrNull) &&
456          "Trying to get dereferenceable bytes from "
457          "non-dereferenceable attribute!");
458   return pImpl->getValueAsInt();
459 }
460 
461 std::pair<unsigned, std::optional<unsigned>>
getAllocSizeArgs() const462 Attribute::getAllocSizeArgs() const {
463   assert(hasAttribute(Attribute::AllocSize) &&
464          "Trying to get allocsize args from non-allocsize attribute");
465   return unpackAllocSizeArgs(pImpl->getValueAsInt());
466 }
467 
getVScaleRangeMin() const468 unsigned Attribute::getVScaleRangeMin() const {
469   assert(hasAttribute(Attribute::VScaleRange) &&
470          "Trying to get vscale args from non-vscale attribute");
471   return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
472 }
473 
getVScaleRangeMax() const474 std::optional<unsigned> Attribute::getVScaleRangeMax() const {
475   assert(hasAttribute(Attribute::VScaleRange) &&
476          "Trying to get vscale args from non-vscale attribute");
477   return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
478 }
479 
getUWTableKind() const480 UWTableKind Attribute::getUWTableKind() const {
481   assert(hasAttribute(Attribute::UWTable) &&
482          "Trying to get unwind table kind from non-uwtable attribute");
483   return UWTableKind(pImpl->getValueAsInt());
484 }
485 
getAllocKind() const486 AllocFnKind Attribute::getAllocKind() const {
487   assert(hasAttribute(Attribute::AllocKind) &&
488          "Trying to get allockind value from non-allockind attribute");
489   return AllocFnKind(pImpl->getValueAsInt());
490 }
491 
getMemoryEffects() const492 MemoryEffects Attribute::getMemoryEffects() const {
493   assert(hasAttribute(Attribute::Memory) &&
494          "Can only call getMemoryEffects() on memory attribute");
495   return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
496 }
497 
getCaptureInfo() const498 CaptureInfo Attribute::getCaptureInfo() const {
499   assert(hasAttribute(Attribute::Captures) &&
500          "Can only call getCaptureInfo() on captures attribute");
501   return CaptureInfo::createFromIntValue(pImpl->getValueAsInt());
502 }
503 
getNoFPClass() const504 FPClassTest Attribute::getNoFPClass() const {
505   assert(hasAttribute(Attribute::NoFPClass) &&
506          "Can only call getNoFPClass() on nofpclass attribute");
507   return static_cast<FPClassTest>(pImpl->getValueAsInt());
508 }
509 
getRange() const510 const ConstantRange &Attribute::getRange() const {
511   assert(hasAttribute(Attribute::Range) &&
512          "Trying to get range args from non-range attribute");
513   return pImpl->getValueAsConstantRange();
514 }
515 
getInitializes() const516 ArrayRef<ConstantRange> Attribute::getInitializes() const {
517   assert(hasAttribute(Attribute::Initializes) &&
518          "Trying to get initializes attr from non-ConstantRangeList attribute");
519   return pImpl->getValueAsConstantRangeList();
520 }
521 
getModRefStr(ModRefInfo MR)522 static const char *getModRefStr(ModRefInfo MR) {
523   switch (MR) {
524   case ModRefInfo::NoModRef:
525     return "none";
526   case ModRefInfo::Ref:
527     return "read";
528   case ModRefInfo::Mod:
529     return "write";
530   case ModRefInfo::ModRef:
531     return "readwrite";
532   }
533   llvm_unreachable("Invalid ModRefInfo");
534 }
535 
getAsString(bool InAttrGrp) const536 std::string Attribute::getAsString(bool InAttrGrp) const {
537   if (!pImpl) return {};
538 
539   if (isEnumAttribute())
540     return getNameFromAttrKind(getKindAsEnum()).str();
541 
542   if (isTypeAttribute()) {
543     std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
544     Result += '(';
545     raw_string_ostream OS(Result);
546     getValueAsType()->print(OS, false, true);
547     OS.flush();
548     Result += ')';
549     return Result;
550   }
551 
552   // FIXME: These should be output like this:
553   //
554   //   align=4
555   //   alignstack=8
556   //
557   if (hasAttribute(Attribute::Alignment))
558     return (InAttrGrp ? "align=" + Twine(getValueAsInt())
559                       : "align " + Twine(getValueAsInt()))
560         .str();
561 
562   auto AttrWithBytesToString = [&](const char *Name) {
563     return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
564                       : Name + ("(" + Twine(getValueAsInt())) + ")")
565         .str();
566   };
567 
568   if (hasAttribute(Attribute::StackAlignment))
569     return AttrWithBytesToString("alignstack");
570 
571   if (hasAttribute(Attribute::Dereferenceable))
572     return AttrWithBytesToString("dereferenceable");
573 
574   if (hasAttribute(Attribute::DereferenceableOrNull))
575     return AttrWithBytesToString("dereferenceable_or_null");
576 
577   if (hasAttribute(Attribute::AllocSize)) {
578     unsigned ElemSize;
579     std::optional<unsigned> NumElems;
580     std::tie(ElemSize, NumElems) = getAllocSizeArgs();
581 
582     return (NumElems
583                 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
584                 : "allocsize(" + Twine(ElemSize) + ")")
585         .str();
586   }
587 
588   if (hasAttribute(Attribute::VScaleRange)) {
589     unsigned MinValue = getVScaleRangeMin();
590     std::optional<unsigned> MaxValue = getVScaleRangeMax();
591     return ("vscale_range(" + Twine(MinValue) + "," +
592             Twine(MaxValue.value_or(0)) + ")")
593         .str();
594   }
595 
596   if (hasAttribute(Attribute::UWTable)) {
597     UWTableKind Kind = getUWTableKind();
598     assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
599     return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
600   }
601 
602   if (hasAttribute(Attribute::AllocKind)) {
603     AllocFnKind Kind = getAllocKind();
604     SmallVector<StringRef> parts;
605     if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
606       parts.push_back("alloc");
607     if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
608       parts.push_back("realloc");
609     if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
610       parts.push_back("free");
611     if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
612       parts.push_back("uninitialized");
613     if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
614       parts.push_back("zeroed");
615     if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
616       parts.push_back("aligned");
617     return ("allockind(\"" +
618             Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
619         .str();
620   }
621 
622   if (hasAttribute(Attribute::Memory)) {
623     std::string Result;
624     raw_string_ostream OS(Result);
625     bool First = true;
626     OS << "memory(";
627 
628     MemoryEffects ME = getMemoryEffects();
629 
630     // Print access kind for "other" as the default access kind. This way it
631     // will apply to any new location kinds that get split out of "other".
632     ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other);
633     if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
634       First = false;
635       OS << getModRefStr(OtherMR);
636     }
637 
638     for (auto Loc : MemoryEffects::locations()) {
639       ModRefInfo MR = ME.getModRef(Loc);
640       if (MR == OtherMR)
641         continue;
642 
643       if (!First)
644         OS << ", ";
645       First = false;
646 
647       switch (Loc) {
648       case IRMemLocation::ArgMem:
649         OS << "argmem: ";
650         break;
651       case IRMemLocation::InaccessibleMem:
652         OS << "inaccessiblemem: ";
653         break;
654       case IRMemLocation::ErrnoMem:
655         OS << "errnomem: ";
656         break;
657       case IRMemLocation::Other:
658         llvm_unreachable("This is represented as the default access kind");
659       }
660       OS << getModRefStr(MR);
661     }
662     OS << ")";
663     OS.flush();
664     return Result;
665   }
666 
667   if (hasAttribute(Attribute::Captures)) {
668     std::string Result;
669     raw_string_ostream OS(Result);
670     OS << getCaptureInfo();
671     return Result;
672   }
673 
674   if (hasAttribute(Attribute::NoFPClass)) {
675     std::string Result = "nofpclass";
676     raw_string_ostream OS(Result);
677     OS << getNoFPClass();
678     return Result;
679   }
680 
681   if (hasAttribute(Attribute::Range)) {
682     std::string Result;
683     raw_string_ostream OS(Result);
684     const ConstantRange &CR = getValueAsConstantRange();
685     OS << "range(";
686     OS << "i" << CR.getBitWidth() << " ";
687     OS << CR.getLower() << ", " << CR.getUpper();
688     OS << ")";
689     OS.flush();
690     return Result;
691   }
692 
693   if (hasAttribute(Attribute::Initializes)) {
694     std::string Result;
695     raw_string_ostream OS(Result);
696     ConstantRangeList CRL = getInitializes();
697     OS << "initializes(";
698     CRL.print(OS);
699     OS << ")";
700     OS.flush();
701     return Result;
702   }
703 
704   // Convert target-dependent attributes to strings of the form:
705   //
706   //   "kind"
707   //   "kind" = "value"
708   //
709   if (isStringAttribute()) {
710     std::string Result;
711     {
712       raw_string_ostream OS(Result);
713       OS << '"' << getKindAsString() << '"';
714 
715       // Since some attribute strings contain special characters that cannot be
716       // printable, those have to be escaped to make the attribute value
717       // printable as is.  e.g. "\01__gnu_mcount_nc"
718       const auto &AttrVal = pImpl->getValueAsString();
719       if (!AttrVal.empty()) {
720         OS << "=\"";
721         printEscapedString(AttrVal, OS);
722         OS << "\"";
723       }
724     }
725     return Result;
726   }
727 
728   llvm_unreachable("Unknown attribute");
729 }
730 
hasParentContext(LLVMContext & C) const731 bool Attribute::hasParentContext(LLVMContext &C) const {
732   assert(isValid() && "invalid Attribute doesn't refer to any context");
733   FoldingSetNodeID ID;
734   pImpl->Profile(ID);
735   void *Unused;
736   return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
737 }
738 
cmpKind(Attribute A) const739 int Attribute::cmpKind(Attribute A) const {
740   if (!pImpl && !A.pImpl)
741     return 0;
742   if (!pImpl)
743     return 1;
744   if (!A.pImpl)
745     return -1;
746   return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
747 }
748 
operator <(Attribute A) const749 bool Attribute::operator<(Attribute A) const {
750   if (!pImpl && !A.pImpl) return false;
751   if (!pImpl) return true;
752   if (!A.pImpl) return false;
753   return *pImpl < *A.pImpl;
754 }
755 
Profile(FoldingSetNodeID & ID) const756 void Attribute::Profile(FoldingSetNodeID &ID) const {
757   ID.AddPointer(pImpl);
758 }
759 
760 enum AttributeProperty {
761   FnAttr = (1 << 0),
762   ParamAttr = (1 << 1),
763   RetAttr = (1 << 2),
764   IntersectPreserve = (0 << 3),
765   IntersectAnd = (1 << 3),
766   IntersectMin = (2 << 3),
767   IntersectCustom = (3 << 3),
768   IntersectPropertyMask = (3 << 3),
769 };
770 
771 #define GET_ATTR_PROP_TABLE
772 #include "llvm/IR/Attributes.inc"
773 
getAttributeProperties(Attribute::AttrKind Kind)774 static unsigned getAttributeProperties(Attribute::AttrKind Kind) {
775   unsigned Index = Kind - 1;
776   assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
777   return AttrPropTable[Index];
778 }
779 
hasAttributeProperty(Attribute::AttrKind Kind,AttributeProperty Prop)780 static bool hasAttributeProperty(Attribute::AttrKind Kind,
781                                  AttributeProperty Prop) {
782   return getAttributeProperties(Kind) & Prop;
783 }
784 
canUseAsFnAttr(AttrKind Kind)785 bool Attribute::canUseAsFnAttr(AttrKind Kind) {
786   return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
787 }
788 
canUseAsParamAttr(AttrKind Kind)789 bool Attribute::canUseAsParamAttr(AttrKind Kind) {
790   return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
791 }
792 
canUseAsRetAttr(AttrKind Kind)793 bool Attribute::canUseAsRetAttr(AttrKind Kind) {
794   return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
795 }
796 
hasIntersectProperty(Attribute::AttrKind Kind,AttributeProperty Prop)797 static bool hasIntersectProperty(Attribute::AttrKind Kind,
798                                  AttributeProperty Prop) {
799   assert((Prop == AttributeProperty::IntersectPreserve ||
800           Prop == AttributeProperty::IntersectAnd ||
801           Prop == AttributeProperty::IntersectMin ||
802           Prop == AttributeProperty::IntersectCustom) &&
803          "Unknown intersect property");
804   return (getAttributeProperties(Kind) &
805           AttributeProperty::IntersectPropertyMask) == Prop;
806 }
807 
intersectMustPreserve(AttrKind Kind)808 bool Attribute::intersectMustPreserve(AttrKind Kind) {
809   return hasIntersectProperty(Kind, AttributeProperty::IntersectPreserve);
810 }
intersectWithAnd(AttrKind Kind)811 bool Attribute::intersectWithAnd(AttrKind Kind) {
812   return hasIntersectProperty(Kind, AttributeProperty::IntersectAnd);
813 }
intersectWithMin(AttrKind Kind)814 bool Attribute::intersectWithMin(AttrKind Kind) {
815   return hasIntersectProperty(Kind, AttributeProperty::IntersectMin);
816 }
intersectWithCustom(AttrKind Kind)817 bool Attribute::intersectWithCustom(AttrKind Kind) {
818   return hasIntersectProperty(Kind, AttributeProperty::IntersectCustom);
819 }
820 
821 //===----------------------------------------------------------------------===//
822 // AttributeImpl Definition
823 //===----------------------------------------------------------------------===//
824 
hasAttribute(Attribute::AttrKind A) const825 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
826   if (isStringAttribute()) return false;
827   return getKindAsEnum() == A;
828 }
829 
hasAttribute(StringRef Kind) const830 bool AttributeImpl::hasAttribute(StringRef Kind) const {
831   if (!isStringAttribute()) return false;
832   return getKindAsString() == Kind;
833 }
834 
getKindAsEnum() const835 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
836   assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
837          isConstantRangeAttribute() || isConstantRangeListAttribute());
838   return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
839 }
840 
getValueAsInt() const841 uint64_t AttributeImpl::getValueAsInt() const {
842   assert(isIntAttribute());
843   return static_cast<const IntAttributeImpl *>(this)->getValue();
844 }
845 
getValueAsBool() const846 bool AttributeImpl::getValueAsBool() const {
847   assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
848   return getValueAsString() == "true";
849 }
850 
getKindAsString() const851 StringRef AttributeImpl::getKindAsString() const {
852   assert(isStringAttribute());
853   return static_cast<const StringAttributeImpl *>(this)->getStringKind();
854 }
855 
getValueAsString() const856 StringRef AttributeImpl::getValueAsString() const {
857   assert(isStringAttribute());
858   return static_cast<const StringAttributeImpl *>(this)->getStringValue();
859 }
860 
getValueAsType() const861 Type *AttributeImpl::getValueAsType() const {
862   assert(isTypeAttribute());
863   return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
864 }
865 
getValueAsConstantRange() const866 const ConstantRange &AttributeImpl::getValueAsConstantRange() const {
867   assert(isConstantRangeAttribute());
868   return static_cast<const ConstantRangeAttributeImpl *>(this)
869       ->getConstantRangeValue();
870 }
871 
getValueAsConstantRangeList() const872 ArrayRef<ConstantRange> AttributeImpl::getValueAsConstantRangeList() const {
873   assert(isConstantRangeListAttribute());
874   return static_cast<const ConstantRangeListAttributeImpl *>(this)
875       ->getConstantRangeListValue();
876 }
877 
cmp(const AttributeImpl & AI,bool KindOnly) const878 int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
879   if (this == &AI)
880     return 0;
881 
882   // This sorts the attributes with Attribute::AttrKinds coming first (sorted
883   // relative to their enum value) and then strings.
884   if (!isStringAttribute()) {
885     if (AI.isStringAttribute())
886       return -1;
887 
888     if (getKindAsEnum() != AI.getKindAsEnum())
889       return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
890     else if (KindOnly)
891       return 0;
892 
893     assert(!AI.isEnumAttribute() && "Non-unique attribute");
894     assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
895     assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
896     assert(!AI.isConstantRangeListAttribute() &&
897            "Unclear how to compare range list");
898     // TODO: Is this actually needed?
899     assert(AI.isIntAttribute() && "Only possibility left");
900     if (getValueAsInt() < AI.getValueAsInt())
901       return -1;
902     return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
903   }
904   if (!AI.isStringAttribute())
905     return 1;
906   if (KindOnly)
907     return getKindAsString().compare(AI.getKindAsString());
908   if (getKindAsString() == AI.getKindAsString())
909     return getValueAsString().compare(AI.getValueAsString());
910   return getKindAsString().compare(AI.getKindAsString());
911 }
912 
operator <(const AttributeImpl & AI) const913 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
914   return cmp(AI, /*KindOnly=*/false) < 0;
915 }
916 
917 //===----------------------------------------------------------------------===//
918 // AttributeSet Definition
919 //===----------------------------------------------------------------------===//
920 
get(LLVMContext & C,const AttrBuilder & B)921 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
922   return AttributeSet(AttributeSetNode::get(C, B));
923 }
924 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)925 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
926   return AttributeSet(AttributeSetNode::get(C, Attrs));
927 }
928 
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const929 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
930                                         Attribute::AttrKind Kind) const {
931   if (hasAttribute(Kind)) return *this;
932   AttrBuilder B(C);
933   B.addAttribute(Kind);
934   return addAttributes(C, AttributeSet::get(C, B));
935 }
936 
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const937 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
938                                         StringRef Value) const {
939   AttrBuilder B(C);
940   B.addAttribute(Kind, Value);
941   return addAttributes(C, AttributeSet::get(C, B));
942 }
943 
addAttributes(LLVMContext & C,const AttributeSet AS) const944 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
945                                          const AttributeSet AS) const {
946   if (!hasAttributes())
947     return AS;
948 
949   if (!AS.hasAttributes())
950     return *this;
951 
952   AttrBuilder B(C, *this);
953   B.merge(AttrBuilder(C, AS));
954   return get(C, B);
955 }
956 
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const957 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
958                                              Attribute::AttrKind Kind) const {
959   if (!hasAttribute(Kind)) return *this;
960   AttrBuilder B(C, *this);
961   B.removeAttribute(Kind);
962   return get(C, B);
963 }
964 
removeAttribute(LLVMContext & C,StringRef Kind) const965 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
966                                              StringRef Kind) const {
967   if (!hasAttribute(Kind)) return *this;
968   AttrBuilder B(C, *this);
969   B.removeAttribute(Kind);
970   return get(C, B);
971 }
972 
removeAttributes(LLVMContext & C,const AttributeMask & Attrs) const973 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
974                                             const AttributeMask &Attrs) const {
975   AttrBuilder B(C, *this);
976   // If there is nothing to remove, directly return the original set.
977   if (!B.overlaps(Attrs))
978     return *this;
979 
980   B.remove(Attrs);
981   return get(C, B);
982 }
983 
984 std::optional<AttributeSet>
intersectWith(LLVMContext & C,AttributeSet Other) const985 AttributeSet::intersectWith(LLVMContext &C, AttributeSet Other) const {
986   if (*this == Other)
987     return *this;
988 
989   AttrBuilder Intersected(C);
990   // Iterate over both attr sets at once.
991   auto ItBegin0 = begin();
992   auto ItEnd0 = end();
993   auto ItBegin1 = Other.begin();
994   auto ItEnd1 = Other.end();
995 
996   while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
997     // Loop through all attributes in both this and Other in sorted order. If
998     // the attribute is only present in one of the sets, it will be set in
999     // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
1000     Attribute Attr0, Attr1;
1001     if (ItBegin1 == ItEnd1)
1002       Attr0 = *ItBegin0++;
1003     else if (ItBegin0 == ItEnd0)
1004       Attr0 = *ItBegin1++;
1005     else {
1006       int Cmp = ItBegin0->cmpKind(*ItBegin1);
1007       if (Cmp == 0) {
1008         Attr0 = *ItBegin0++;
1009         Attr1 = *ItBegin1++;
1010       } else if (Cmp < 0)
1011         Attr0 = *ItBegin0++;
1012       else
1013         Attr0 = *ItBegin1++;
1014     }
1015     assert(Attr0.isValid() && "Iteration should always yield a valid attr");
1016 
1017     auto IntersectEq = [&]() {
1018       if (!Attr1.isValid())
1019         return false;
1020       if (Attr0 != Attr1)
1021         return false;
1022       Intersected.addAttribute(Attr0);
1023       return true;
1024     };
1025 
1026     // Non-enum assume we must preserve. Handle early so we can unconditionally
1027     // use Kind below.
1028     if (!Attr0.hasKindAsEnum()) {
1029       if (!IntersectEq())
1030         return std::nullopt;
1031       continue;
1032     }
1033 
1034     Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1035     // If we don't have both attributes, then fail if the attribute is
1036     // must-preserve or drop it otherwise.
1037     if (!Attr1.isValid()) {
1038       if (Attribute::intersectMustPreserve(Kind))
1039         return std::nullopt;
1040       continue;
1041     }
1042 
1043     // We have both attributes so apply the intersection rule.
1044     assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1045            "Iterator picked up two different attributes in the same iteration");
1046 
1047     // Attribute we can intersect with "and"
1048     if (Attribute::intersectWithAnd(Kind)) {
1049       assert(Attribute::isEnumAttrKind(Kind) &&
1050              "Invalid attr type of intersectAnd");
1051       Intersected.addAttribute(Kind);
1052       continue;
1053     }
1054 
1055     // Attribute we can intersect with "min"
1056     if (Attribute::intersectWithMin(Kind)) {
1057       assert(Attribute::isIntAttrKind(Kind) &&
1058              "Invalid attr type of intersectMin");
1059       uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1060       Intersected.addRawIntAttr(Kind, NewVal);
1061       continue;
1062     }
1063     // Attribute we can intersect but need a custom rule for.
1064     if (Attribute::intersectWithCustom(Kind)) {
1065       switch (Kind) {
1066       case Attribute::Alignment:
1067         // If `byval` is present, alignment become must-preserve. This is
1068         // handled below if we have `byval`.
1069         Intersected.addAlignmentAttr(
1070             std::min(Attr0.getAlignment().valueOrOne(),
1071                      Attr1.getAlignment().valueOrOne()));
1072         break;
1073       case Attribute::Memory:
1074         Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1075                                   Attr1.getMemoryEffects());
1076         break;
1077       case Attribute::Captures:
1078         Intersected.addCapturesAttr(Attr0.getCaptureInfo() |
1079                                     Attr1.getCaptureInfo());
1080         break;
1081       case Attribute::NoFPClass:
1082         Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1083                                      Attr1.getNoFPClass());
1084         break;
1085       case Attribute::Range: {
1086         ConstantRange Range0 = Attr0.getRange();
1087         ConstantRange Range1 = Attr1.getRange();
1088         ConstantRange NewRange = Range0.unionWith(Range1);
1089         if (!NewRange.isFullSet())
1090           Intersected.addRangeAttr(NewRange);
1091       } break;
1092       default:
1093         llvm_unreachable("Unknown attribute with custom intersection rule");
1094       }
1095       continue;
1096     }
1097 
1098     // Attributes with no intersection rule. Only intersect if they are equal.
1099     // Otherwise fail.
1100     if (!IntersectEq())
1101       return std::nullopt;
1102 
1103     // Special handling of `byval`. `byval` essentially turns align attr into
1104     // must-preserve
1105     if (Kind == Attribute::ByVal &&
1106         getAttribute(Attribute::Alignment) !=
1107             Other.getAttribute(Attribute::Alignment))
1108       return std::nullopt;
1109   }
1110 
1111   return get(C, Intersected);
1112 }
1113 
getNumAttributes() const1114 unsigned AttributeSet::getNumAttributes() const {
1115   return SetNode ? SetNode->getNumAttributes() : 0;
1116 }
1117 
hasAttribute(Attribute::AttrKind Kind) const1118 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
1119   return SetNode ? SetNode->hasAttribute(Kind) : false;
1120 }
1121 
hasAttribute(StringRef Kind) const1122 bool AttributeSet::hasAttribute(StringRef Kind) const {
1123   return SetNode ? SetNode->hasAttribute(Kind) : false;
1124 }
1125 
getAttribute(Attribute::AttrKind Kind) const1126 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
1127   return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1128 }
1129 
getAttribute(StringRef Kind) const1130 Attribute AttributeSet::getAttribute(StringRef Kind) const {
1131   return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1132 }
1133 
getAlignment() const1134 MaybeAlign AttributeSet::getAlignment() const {
1135   return SetNode ? SetNode->getAlignment() : std::nullopt;
1136 }
1137 
getStackAlignment() const1138 MaybeAlign AttributeSet::getStackAlignment() const {
1139   return SetNode ? SetNode->getStackAlignment() : std::nullopt;
1140 }
1141 
getDereferenceableBytes() const1142 uint64_t AttributeSet::getDereferenceableBytes() const {
1143   return SetNode ? SetNode->getDereferenceableBytes() : 0;
1144 }
1145 
getDereferenceableOrNullBytes() const1146 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
1147   return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
1148 }
1149 
getByRefType() const1150 Type *AttributeSet::getByRefType() const {
1151   return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
1152 }
1153 
getByValType() const1154 Type *AttributeSet::getByValType() const {
1155   return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
1156 }
1157 
getStructRetType() const1158 Type *AttributeSet::getStructRetType() const {
1159   return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
1160 }
1161 
getPreallocatedType() const1162 Type *AttributeSet::getPreallocatedType() const {
1163   return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
1164 }
1165 
getInAllocaType() const1166 Type *AttributeSet::getInAllocaType() const {
1167   return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
1168 }
1169 
getElementType() const1170 Type *AttributeSet::getElementType() const {
1171   return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
1172 }
1173 
1174 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1175 AttributeSet::getAllocSizeArgs() const {
1176   if (SetNode)
1177     return SetNode->getAllocSizeArgs();
1178   return std::nullopt;
1179 }
1180 
getVScaleRangeMin() const1181 unsigned AttributeSet::getVScaleRangeMin() const {
1182   return SetNode ? SetNode->getVScaleRangeMin() : 1;
1183 }
1184 
getVScaleRangeMax() const1185 std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1186   return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
1187 }
1188 
getUWTableKind() const1189 UWTableKind AttributeSet::getUWTableKind() const {
1190   return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
1191 }
1192 
getAllocKind() const1193 AllocFnKind AttributeSet::getAllocKind() const {
1194   return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
1195 }
1196 
getMemoryEffects() const1197 MemoryEffects AttributeSet::getMemoryEffects() const {
1198   return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
1199 }
1200 
getCaptureInfo() const1201 CaptureInfo AttributeSet::getCaptureInfo() const {
1202   return SetNode ? SetNode->getCaptureInfo() : CaptureInfo::all();
1203 }
1204 
getNoFPClass() const1205 FPClassTest AttributeSet::getNoFPClass() const {
1206   return SetNode ? SetNode->getNoFPClass() : fcNone;
1207 }
1208 
getAsString(bool InAttrGrp) const1209 std::string AttributeSet::getAsString(bool InAttrGrp) const {
1210   return SetNode ? SetNode->getAsString(InAttrGrp) : "";
1211 }
1212 
hasParentContext(LLVMContext & C) const1213 bool AttributeSet::hasParentContext(LLVMContext &C) const {
1214   assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1215   FoldingSetNodeID ID;
1216   SetNode->Profile(ID);
1217   void *Unused;
1218   return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1219 }
1220 
begin() const1221 AttributeSet::iterator AttributeSet::begin() const {
1222   return SetNode ? SetNode->begin() : nullptr;
1223 }
1224 
end() const1225 AttributeSet::iterator AttributeSet::end() const {
1226   return SetNode ? SetNode->end() : nullptr;
1227 }
1228 
1229 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1230 LLVM_DUMP_METHOD void AttributeSet::dump() const {
1231   dbgs() << "AS =\n";
1232     dbgs() << "  { ";
1233     dbgs() << getAsString(true) << " }\n";
1234 }
1235 #endif
1236 
1237 //===----------------------------------------------------------------------===//
1238 // AttributeSetNode Definition
1239 //===----------------------------------------------------------------------===//
1240 
AttributeSetNode(ArrayRef<Attribute> Attrs)1241 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1242     : NumAttrs(Attrs.size()) {
1243   // There's memory after the node where we can store the entries in.
1244   llvm::copy(Attrs, getTrailingObjects());
1245 
1246   for (const auto &I : *this) {
1247     if (I.isStringAttribute())
1248       StringAttrs.insert({ I.getKindAsString(), I });
1249     else
1250       AvailableAttrs.addAttribute(I.getKindAsEnum());
1251   }
1252 }
1253 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)1254 AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
1255                                         ArrayRef<Attribute> Attrs) {
1256   SmallVector<Attribute, 8> SortedAttrs(Attrs);
1257   llvm::sort(SortedAttrs);
1258   return getSorted(C, SortedAttrs);
1259 }
1260 
getSorted(LLVMContext & C,ArrayRef<Attribute> SortedAttrs)1261 AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1262                                               ArrayRef<Attribute> SortedAttrs) {
1263   if (SortedAttrs.empty())
1264     return nullptr;
1265 
1266   // Build a key to look up the existing attributes.
1267   LLVMContextImpl *pImpl = C.pImpl;
1268   FoldingSetNodeID ID;
1269 
1270   assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1271   for (const auto &Attr : SortedAttrs)
1272     Attr.Profile(ID);
1273 
1274   void *InsertPoint;
1275   AttributeSetNode *PA =
1276     pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1277 
1278   // If we didn't find any existing attributes of the same shape then create a
1279   // new one and insert it.
1280   if (!PA) {
1281     // Coallocate entries after the AttributeSetNode itself.
1282     void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1283     PA = new (Mem) AttributeSetNode(SortedAttrs);
1284     pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1285   }
1286 
1287   // Return the AttributeSetNode that we found or created.
1288   return PA;
1289 }
1290 
get(LLVMContext & C,const AttrBuilder & B)1291 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
1292   return getSorted(C, B.attrs());
1293 }
1294 
hasAttribute(StringRef Kind) const1295 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
1296   return StringAttrs.count(Kind);
1297 }
1298 
1299 std::optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const1300 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1301   // Do a quick presence check.
1302   if (!hasAttribute(Kind))
1303     return std::nullopt;
1304 
1305   // Attributes in a set are sorted by enum value, followed by string
1306   // attributes. Binary search the one we want.
1307   const Attribute *I =
1308       std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1309                        [](Attribute A, Attribute::AttrKind Kind) {
1310                          return A.getKindAsEnum() < Kind;
1311                        });
1312   assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1313   return *I;
1314 }
1315 
getAttribute(Attribute::AttrKind Kind) const1316 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
1317   if (auto A = findEnumAttribute(Kind))
1318     return *A;
1319   return {};
1320 }
1321 
getAttribute(StringRef Kind) const1322 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
1323   return StringAttrs.lookup(Kind);
1324 }
1325 
getAlignment() const1326 MaybeAlign AttributeSetNode::getAlignment() const {
1327   if (auto A = findEnumAttribute(Attribute::Alignment))
1328     return A->getAlignment();
1329   return std::nullopt;
1330 }
1331 
getStackAlignment() const1332 MaybeAlign AttributeSetNode::getStackAlignment() const {
1333   if (auto A = findEnumAttribute(Attribute::StackAlignment))
1334     return A->getStackAlignment();
1335   return std::nullopt;
1336 }
1337 
getAttributeType(Attribute::AttrKind Kind) const1338 Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
1339   if (auto A = findEnumAttribute(Kind))
1340     return A->getValueAsType();
1341   return nullptr;
1342 }
1343 
getDereferenceableBytes() const1344 uint64_t AttributeSetNode::getDereferenceableBytes() const {
1345   if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1346     return A->getDereferenceableBytes();
1347   return 0;
1348 }
1349 
getDereferenceableOrNullBytes() const1350 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
1351   if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1352     return A->getDereferenceableOrNullBytes();
1353   return 0;
1354 }
1355 
1356 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1357 AttributeSetNode::getAllocSizeArgs() const {
1358   if (auto A = findEnumAttribute(Attribute::AllocSize))
1359     return A->getAllocSizeArgs();
1360   return std::nullopt;
1361 }
1362 
getVScaleRangeMin() const1363 unsigned AttributeSetNode::getVScaleRangeMin() const {
1364   if (auto A = findEnumAttribute(Attribute::VScaleRange))
1365     return A->getVScaleRangeMin();
1366   return 1;
1367 }
1368 
getVScaleRangeMax() const1369 std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1370   if (auto A = findEnumAttribute(Attribute::VScaleRange))
1371     return A->getVScaleRangeMax();
1372   return std::nullopt;
1373 }
1374 
getUWTableKind() const1375 UWTableKind AttributeSetNode::getUWTableKind() const {
1376   if (auto A = findEnumAttribute(Attribute::UWTable))
1377     return A->getUWTableKind();
1378   return UWTableKind::None;
1379 }
1380 
getAllocKind() const1381 AllocFnKind AttributeSetNode::getAllocKind() const {
1382   if (auto A = findEnumAttribute(Attribute::AllocKind))
1383     return A->getAllocKind();
1384   return AllocFnKind::Unknown;
1385 }
1386 
getMemoryEffects() const1387 MemoryEffects AttributeSetNode::getMemoryEffects() const {
1388   if (auto A = findEnumAttribute(Attribute::Memory))
1389     return A->getMemoryEffects();
1390   return MemoryEffects::unknown();
1391 }
1392 
getCaptureInfo() const1393 CaptureInfo AttributeSetNode::getCaptureInfo() const {
1394   if (auto A = findEnumAttribute(Attribute::Captures))
1395     return A->getCaptureInfo();
1396   return CaptureInfo::all();
1397 }
1398 
getNoFPClass() const1399 FPClassTest AttributeSetNode::getNoFPClass() const {
1400   if (auto A = findEnumAttribute(Attribute::NoFPClass))
1401     return A->getNoFPClass();
1402   return fcNone;
1403 }
1404 
getAsString(bool InAttrGrp) const1405 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1406   std::string Str;
1407   for (iterator I = begin(), E = end(); I != E; ++I) {
1408     if (I != begin())
1409       Str += ' ';
1410     Str += I->getAsString(InAttrGrp);
1411   }
1412   return Str;
1413 }
1414 
1415 //===----------------------------------------------------------------------===//
1416 // AttributeListImpl Definition
1417 //===----------------------------------------------------------------------===//
1418 
1419 /// Map from AttributeList index to the internal array index. Adding one happens
1420 /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)1421 static unsigned attrIdxToArrayIdx(unsigned Index) {
1422   return Index + 1;
1423 }
1424 
AttributeListImpl(ArrayRef<AttributeSet> Sets)1425 AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
1426     : NumAttrSets(Sets.size()) {
1427   assert(!Sets.empty() && "pointless AttributeListImpl");
1428 
1429   // There's memory after the node where we can store the entries in.
1430   llvm::copy(Sets, getTrailingObjects());
1431 
1432   // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1433   // summary bitsets.
1434   for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1435     if (!I.isStringAttribute())
1436       AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1437 
1438   for (const auto &Set : Sets)
1439     for (const auto &I : Set)
1440       if (!I.isStringAttribute())
1441         AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1442 }
1443 
Profile(FoldingSetNodeID & ID) const1444 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
1445   Profile(ID, ArrayRef(begin(), end()));
1446 }
1447 
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)1448 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
1449                                 ArrayRef<AttributeSet> Sets) {
1450   for (const auto &Set : Sets)
1451     ID.AddPointer(Set.SetNode);
1452 }
1453 
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const1454 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
1455                                         unsigned *Index) const {
1456   if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1457     return false;
1458 
1459   if (Index) {
1460     for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1461       if (begin()[I].hasAttribute(Kind)) {
1462         *Index = I - 1;
1463         break;
1464       }
1465     }
1466   }
1467 
1468   return true;
1469 }
1470 
1471 
1472 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1473 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1474   AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1475 }
1476 #endif
1477 
1478 //===----------------------------------------------------------------------===//
1479 // AttributeList Construction and Mutation Methods
1480 //===----------------------------------------------------------------------===//
1481 
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)1482 AttributeList AttributeList::getImpl(LLVMContext &C,
1483                                      ArrayRef<AttributeSet> AttrSets) {
1484   assert(!AttrSets.empty() && "pointless AttributeListImpl");
1485 
1486   LLVMContextImpl *pImpl = C.pImpl;
1487   FoldingSetNodeID ID;
1488   AttributeListImpl::Profile(ID, AttrSets);
1489 
1490   void *InsertPoint;
1491   AttributeListImpl *PA =
1492       pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1493 
1494   // If we didn't find any existing attributes of the same shape then
1495   // create a new one and insert it.
1496   if (!PA) {
1497     // Coallocate entries after the AttributeListImpl itself.
1498     void *Mem = pImpl->Alloc.Allocate(
1499         AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1500         alignof(AttributeListImpl));
1501     PA = new (Mem) AttributeListImpl(AttrSets);
1502     pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1503   }
1504 
1505   // Return the AttributesList that we found or created.
1506   return AttributeList(PA);
1507 }
1508 
1509 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)1510 AttributeList::get(LLVMContext &C,
1511                    ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1512   // If there are no attributes then return a null AttributesList pointer.
1513   if (Attrs.empty())
1514     return {};
1515 
1516   assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1517          "Misordered Attributes list!");
1518   assert(llvm::all_of(Attrs,
1519                       [](const std::pair<unsigned, Attribute> &Pair) {
1520                         return Pair.second.isValid();
1521                       }) &&
1522          "Pointless attribute!");
1523 
1524   // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1525   // list.
1526   SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1527   for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1528          E = Attrs.end(); I != E; ) {
1529     unsigned Index = I->first;
1530     SmallVector<Attribute, 4> AttrVec;
1531     while (I != E && I->first == Index) {
1532       AttrVec.push_back(I->second);
1533       ++I;
1534     }
1535 
1536     AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1537   }
1538 
1539   return get(C, AttrPairVec);
1540 }
1541 
1542 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1543 AttributeList::get(LLVMContext &C,
1544                    ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1545   // If there are no attributes then return a null AttributesList pointer.
1546   if (Attrs.empty())
1547     return {};
1548 
1549   assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1550          "Misordered Attributes list!");
1551   assert(llvm::none_of(Attrs,
1552                        [](const std::pair<unsigned, AttributeSet> &Pair) {
1553                          return !Pair.second.hasAttributes();
1554                        }) &&
1555          "Pointless attribute!");
1556 
1557   unsigned MaxIndex = Attrs.back().first;
1558   // If the MaxIndex is FunctionIndex and there are other indices in front
1559   // of it, we need to use the largest of those to get the right size.
1560   if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1561     MaxIndex = Attrs[Attrs.size() - 2].first;
1562 
1563   SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1564   for (const auto &Pair : Attrs)
1565     AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1566 
1567   return getImpl(C, AttrVec);
1568 }
1569 
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)1570 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1571                                  AttributeSet RetAttrs,
1572                                  ArrayRef<AttributeSet> ArgAttrs) {
1573   // Scan from the end to find the last argument with attributes.  Most
1574   // arguments don't have attributes, so it's nice if we can have fewer unique
1575   // AttributeListImpls by dropping empty attribute sets at the end of the list.
1576   unsigned NumSets = 0;
1577   for (size_t I = ArgAttrs.size(); I != 0; --I) {
1578     if (ArgAttrs[I - 1].hasAttributes()) {
1579       NumSets = I + 2;
1580       break;
1581     }
1582   }
1583   if (NumSets == 0) {
1584     // Check function and return attributes if we didn't have argument
1585     // attributes.
1586     if (RetAttrs.hasAttributes())
1587       NumSets = 2;
1588     else if (FnAttrs.hasAttributes())
1589       NumSets = 1;
1590   }
1591 
1592   // If all attribute sets were empty, we can use the empty attribute list.
1593   if (NumSets == 0)
1594     return {};
1595 
1596   SmallVector<AttributeSet, 8> AttrSets;
1597   AttrSets.reserve(NumSets);
1598   // If we have any attributes, we always have function attributes.
1599   AttrSets.push_back(FnAttrs);
1600   if (NumSets > 1)
1601     AttrSets.push_back(RetAttrs);
1602   if (NumSets > 2) {
1603     // Drop the empty argument attribute sets at the end.
1604     ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1605     llvm::append_range(AttrSets, ArgAttrs);
1606   }
1607 
1608   return getImpl(C, AttrSets);
1609 }
1610 
get(LLVMContext & C,unsigned Index,AttributeSet Attrs)1611 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1612                                  AttributeSet Attrs) {
1613   if (!Attrs.hasAttributes())
1614     return {};
1615   Index = attrIdxToArrayIdx(Index);
1616   SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1617   AttrSets[Index] = Attrs;
1618   return getImpl(C, AttrSets);
1619 }
1620 
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1621 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1622                                  const AttrBuilder &B) {
1623   return get(C, Index, AttributeSet::get(C, B));
1624 }
1625 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1626 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1627                                  ArrayRef<Attribute::AttrKind> Kinds) {
1628   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1629   for (const auto K : Kinds)
1630     Attrs.emplace_back(Index, Attribute::get(C, K));
1631   return get(C, Attrs);
1632 }
1633 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)1634 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1635                                  ArrayRef<Attribute::AttrKind> Kinds,
1636                                  ArrayRef<uint64_t> Values) {
1637   assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1638   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1639   auto VI = Values.begin();
1640   for (const auto K : Kinds)
1641     Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1642   return get(C, Attrs);
1643 }
1644 
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1645 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1646                                  ArrayRef<StringRef> Kinds) {
1647   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1648   for (const auto &K : Kinds)
1649     Attrs.emplace_back(Index, Attribute::get(C, K));
1650   return get(C, Attrs);
1651 }
1652 
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1653 AttributeList AttributeList::get(LLVMContext &C,
1654                                  ArrayRef<AttributeList> Attrs) {
1655   if (Attrs.empty())
1656     return {};
1657   if (Attrs.size() == 1)
1658     return Attrs[0];
1659 
1660   unsigned MaxSize = 0;
1661   for (const auto &List : Attrs)
1662     MaxSize = std::max(MaxSize, List.getNumAttrSets());
1663 
1664   // If every list was empty, there is no point in merging the lists.
1665   if (MaxSize == 0)
1666     return {};
1667 
1668   SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1669   for (unsigned I = 0; I < MaxSize; ++I) {
1670     AttrBuilder CurBuilder(C);
1671     for (const auto &List : Attrs)
1672       CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1673     NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1674   }
1675 
1676   return getImpl(C, NewAttrSets);
1677 }
1678 
1679 AttributeList
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1680 AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1681                                    Attribute::AttrKind Kind) const {
1682   AttributeSet Attrs = getAttributes(Index);
1683   if (Attrs.hasAttribute(Kind))
1684     return *this;
1685   // TODO: Insert at correct position and avoid sort.
1686   SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1687   NewAttrs.push_back(Attribute::get(C, Kind));
1688   return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1689 }
1690 
addAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1691 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1692                                                  StringRef Kind,
1693                                                  StringRef Value) const {
1694   AttrBuilder B(C);
1695   B.addAttribute(Kind, Value);
1696   return addAttributesAtIndex(C, Index, B);
1697 }
1698 
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute A) const1699 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1700                                                  Attribute A) const {
1701   AttrBuilder B(C);
1702   B.addAttribute(A);
1703   return addAttributesAtIndex(C, Index, B);
1704 }
1705 
setAttributesAtIndex(LLVMContext & C,unsigned Index,AttributeSet Attrs) const1706 AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1707                                                   unsigned Index,
1708                                                   AttributeSet Attrs) const {
1709   Index = attrIdxToArrayIdx(Index);
1710   SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1711   if (Index >= AttrSets.size())
1712     AttrSets.resize(Index + 1);
1713   AttrSets[Index] = Attrs;
1714 
1715   // Remove trailing empty attribute sets.
1716   while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1717     AttrSets.pop_back();
1718   if (AttrSets.empty())
1719     return {};
1720   return AttributeList::getImpl(C, AttrSets);
1721 }
1722 
addAttributesAtIndex(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1723 AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1724                                                   unsigned Index,
1725                                                   const AttrBuilder &B) const {
1726   if (!B.hasAttributes())
1727     return *this;
1728 
1729   if (!pImpl)
1730     return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1731 
1732   AttrBuilder Merged(C, getAttributes(Index));
1733   Merged.merge(B);
1734   return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1735 }
1736 
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const1737 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1738                                                ArrayRef<unsigned> ArgNos,
1739                                                Attribute A) const {
1740   assert(llvm::is_sorted(ArgNos));
1741 
1742   SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1743   unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1744   if (MaxIndex >= AttrSets.size())
1745     AttrSets.resize(MaxIndex + 1);
1746 
1747   for (unsigned ArgNo : ArgNos) {
1748     unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1749     AttrBuilder B(C, AttrSets[Index]);
1750     B.addAttribute(A);
1751     AttrSets[Index] = AttributeSet::get(C, B);
1752   }
1753 
1754   return getImpl(C, AttrSets);
1755 }
1756 
1757 AttributeList
removeAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1758 AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1759                                       Attribute::AttrKind Kind) const {
1760   AttributeSet Attrs = getAttributes(Index);
1761   AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1762   if (Attrs == NewAttrs)
1763     return *this;
1764   return setAttributesAtIndex(C, Index, NewAttrs);
1765 }
1766 
removeAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind) const1767 AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1768                                                     unsigned Index,
1769                                                     StringRef Kind) const {
1770   AttributeSet Attrs = getAttributes(Index);
1771   AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1772   if (Attrs == NewAttrs)
1773     return *this;
1774   return setAttributesAtIndex(C, Index, NewAttrs);
1775 }
1776 
removeAttributesAtIndex(LLVMContext & C,unsigned Index,const AttributeMask & AttrsToRemove) const1777 AttributeList AttributeList::removeAttributesAtIndex(
1778     LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1779   AttributeSet Attrs = getAttributes(Index);
1780   AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1781   // If nothing was removed, return the original list.
1782   if (Attrs == NewAttrs)
1783     return *this;
1784   return setAttributesAtIndex(C, Index, NewAttrs);
1785 }
1786 
1787 AttributeList
removeAttributesAtIndex(LLVMContext & C,unsigned WithoutIndex) const1788 AttributeList::removeAttributesAtIndex(LLVMContext &C,
1789                                        unsigned WithoutIndex) const {
1790   if (!pImpl)
1791     return {};
1792   if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1793     return *this;
1794   return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1795 }
1796 
addDereferenceableRetAttr(LLVMContext & C,uint64_t Bytes) const1797 AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1798                                                        uint64_t Bytes) const {
1799   AttrBuilder B(C);
1800   B.addDereferenceableAttr(Bytes);
1801   return addRetAttributes(C, B);
1802 }
1803 
addDereferenceableParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1804 AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1805                                                          unsigned Index,
1806                                                          uint64_t Bytes) const {
1807   AttrBuilder B(C);
1808   B.addDereferenceableAttr(Bytes);
1809   return addParamAttributes(C, Index, B);
1810 }
1811 
1812 AttributeList
addDereferenceableOrNullParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1813 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1814                                                  uint64_t Bytes) const {
1815   AttrBuilder B(C);
1816   B.addDereferenceableOrNullAttr(Bytes);
1817   return addParamAttributes(C, Index, B);
1818 }
1819 
addRangeRetAttr(LLVMContext & C,const ConstantRange & CR) const1820 AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
1821                                              const ConstantRange &CR) const {
1822   AttrBuilder B(C);
1823   B.addRangeAttr(CR);
1824   return addRetAttributes(C, B);
1825 }
1826 
addAllocSizeParamAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg) const1827 AttributeList AttributeList::addAllocSizeParamAttr(
1828     LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1829     const std::optional<unsigned> &NumElemsArg) const {
1830   AttrBuilder B(C);
1831   B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1832   return addParamAttributes(C, Index, B);
1833 }
1834 
1835 std::optional<AttributeList>
intersectWith(LLVMContext & C,AttributeList Other) const1836 AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
1837   // Trivial case, the two lists are equal.
1838   if (*this == Other)
1839     return *this;
1840 
1841   SmallVector<std::pair<unsigned, AttributeSet>> IntersectedAttrs;
1842   auto IndexIt =
1843       index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1844   for (unsigned Idx : IndexIt) {
1845     auto IntersectedAS =
1846         getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1847     // If any index fails to intersect, fail.
1848     if (!IntersectedAS)
1849       return std::nullopt;
1850     if (!IntersectedAS->hasAttributes())
1851       continue;
1852     IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1853   }
1854 
1855   llvm::sort(IntersectedAttrs, llvm::less_first());
1856   return AttributeList::get(C, IntersectedAttrs);
1857 }
1858 
1859 //===----------------------------------------------------------------------===//
1860 // AttributeList Accessor Methods
1861 //===----------------------------------------------------------------------===//
1862 
getParamAttrs(unsigned ArgNo) const1863 AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1864   return getAttributes(ArgNo + FirstArgIndex);
1865 }
1866 
getRetAttrs() const1867 AttributeSet AttributeList::getRetAttrs() const {
1868   return getAttributes(ReturnIndex);
1869 }
1870 
getFnAttrs() const1871 AttributeSet AttributeList::getFnAttrs() const {
1872   return getAttributes(FunctionIndex);
1873 }
1874 
hasAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1875 bool AttributeList::hasAttributeAtIndex(unsigned Index,
1876                                         Attribute::AttrKind Kind) const {
1877   return getAttributes(Index).hasAttribute(Kind);
1878 }
1879 
hasAttributeAtIndex(unsigned Index,StringRef Kind) const1880 bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1881   return getAttributes(Index).hasAttribute(Kind);
1882 }
1883 
hasAttributesAtIndex(unsigned Index) const1884 bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1885   return getAttributes(Index).hasAttributes();
1886 }
1887 
hasFnAttr(Attribute::AttrKind Kind) const1888 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1889   return pImpl && pImpl->hasFnAttribute(Kind);
1890 }
1891 
hasFnAttr(StringRef Kind) const1892 bool AttributeList::hasFnAttr(StringRef Kind) const {
1893   return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1894 }
1895 
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1896 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1897                                      unsigned *Index) const {
1898   return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1899 }
1900 
getAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1901 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1902                                              Attribute::AttrKind Kind) const {
1903   return getAttributes(Index).getAttribute(Kind);
1904 }
1905 
getAttributeAtIndex(unsigned Index,StringRef Kind) const1906 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1907                                              StringRef Kind) const {
1908   return getAttributes(Index).getAttribute(Kind);
1909 }
1910 
getRetAlignment() const1911 MaybeAlign AttributeList::getRetAlignment() const {
1912   return getAttributes(ReturnIndex).getAlignment();
1913 }
1914 
getParamAlignment(unsigned ArgNo) const1915 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1916   return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1917 }
1918 
getParamStackAlignment(unsigned ArgNo) const1919 MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1920   return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1921 }
1922 
getParamByValType(unsigned Index) const1923 Type *AttributeList::getParamByValType(unsigned Index) const {
1924   return getAttributes(Index+FirstArgIndex).getByValType();
1925 }
1926 
getParamStructRetType(unsigned Index) const1927 Type *AttributeList::getParamStructRetType(unsigned Index) const {
1928   return getAttributes(Index + FirstArgIndex).getStructRetType();
1929 }
1930 
getParamByRefType(unsigned Index) const1931 Type *AttributeList::getParamByRefType(unsigned Index) const {
1932   return getAttributes(Index + FirstArgIndex).getByRefType();
1933 }
1934 
getParamPreallocatedType(unsigned Index) const1935 Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1936   return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1937 }
1938 
getParamInAllocaType(unsigned Index) const1939 Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1940   return getAttributes(Index + FirstArgIndex).getInAllocaType();
1941 }
1942 
getParamElementType(unsigned Index) const1943 Type *AttributeList::getParamElementType(unsigned Index) const {
1944   return getAttributes(Index + FirstArgIndex).getElementType();
1945 }
1946 
getFnStackAlignment() const1947 MaybeAlign AttributeList::getFnStackAlignment() const {
1948   return getFnAttrs().getStackAlignment();
1949 }
1950 
getRetStackAlignment() const1951 MaybeAlign AttributeList::getRetStackAlignment() const {
1952   return getRetAttrs().getStackAlignment();
1953 }
1954 
getRetDereferenceableBytes() const1955 uint64_t AttributeList::getRetDereferenceableBytes() const {
1956   return getRetAttrs().getDereferenceableBytes();
1957 }
1958 
getParamDereferenceableBytes(unsigned Index) const1959 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1960   return getParamAttrs(Index).getDereferenceableBytes();
1961 }
1962 
getRetDereferenceableOrNullBytes() const1963 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1964   return getRetAttrs().getDereferenceableOrNullBytes();
1965 }
1966 
1967 uint64_t
getParamDereferenceableOrNullBytes(unsigned Index) const1968 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1969   return getParamAttrs(Index).getDereferenceableOrNullBytes();
1970 }
1971 
1972 std::optional<ConstantRange>
getParamRange(unsigned ArgNo) const1973 AttributeList::getParamRange(unsigned ArgNo) const {
1974   auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
1975   if (RangeAttr.isValid())
1976     return RangeAttr.getRange();
1977   return std::nullopt;
1978 }
1979 
getRetNoFPClass() const1980 FPClassTest AttributeList::getRetNoFPClass() const {
1981   return getRetAttrs().getNoFPClass();
1982 }
1983 
getParamNoFPClass(unsigned Index) const1984 FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {
1985   return getParamAttrs(Index).getNoFPClass();
1986 }
1987 
getUWTableKind() const1988 UWTableKind AttributeList::getUWTableKind() const {
1989   return getFnAttrs().getUWTableKind();
1990 }
1991 
getAllocKind() const1992 AllocFnKind AttributeList::getAllocKind() const {
1993   return getFnAttrs().getAllocKind();
1994 }
1995 
getMemoryEffects() const1996 MemoryEffects AttributeList::getMemoryEffects() const {
1997   return getFnAttrs().getMemoryEffects();
1998 }
1999 
getAsString(unsigned Index,bool InAttrGrp) const2000 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
2001   return getAttributes(Index).getAsString(InAttrGrp);
2002 }
2003 
getAttributes(unsigned Index) const2004 AttributeSet AttributeList::getAttributes(unsigned Index) const {
2005   Index = attrIdxToArrayIdx(Index);
2006   if (!pImpl || Index >= getNumAttrSets())
2007     return {};
2008   return pImpl->begin()[Index];
2009 }
2010 
hasParentContext(LLVMContext & C) const2011 bool AttributeList::hasParentContext(LLVMContext &C) const {
2012   assert(!isEmpty() && "an empty attribute list has no parent context");
2013   FoldingSetNodeID ID;
2014   pImpl->Profile(ID);
2015   void *Unused;
2016   return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
2017 }
2018 
begin() const2019 AttributeList::iterator AttributeList::begin() const {
2020   return pImpl ? pImpl->begin() : nullptr;
2021 }
2022 
end() const2023 AttributeList::iterator AttributeList::end() const {
2024   return pImpl ? pImpl->end() : nullptr;
2025 }
2026 
2027 //===----------------------------------------------------------------------===//
2028 // AttributeList Introspection Methods
2029 //===----------------------------------------------------------------------===//
2030 
getNumAttrSets() const2031 unsigned AttributeList::getNumAttrSets() const {
2032   return pImpl ? pImpl->NumAttrSets : 0;
2033 }
2034 
print(raw_ostream & O) const2035 void AttributeList::print(raw_ostream &O) const {
2036   O << "AttributeList[\n";
2037 
2038   for (unsigned i : indexes()) {
2039     if (!getAttributes(i).hasAttributes())
2040       continue;
2041     O << "  { ";
2042     switch (i) {
2043     case AttrIndex::ReturnIndex:
2044       O << "return";
2045       break;
2046     case AttrIndex::FunctionIndex:
2047       O << "function";
2048       break;
2049     default:
2050       O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2051     }
2052     O << " => " << getAsString(i) << " }\n";
2053   }
2054 
2055   O << "]\n";
2056 }
2057 
2058 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const2059 LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
2060 #endif
2061 
2062 //===----------------------------------------------------------------------===//
2063 // AttrBuilder Method Implementations
2064 //===----------------------------------------------------------------------===//
2065 
AttrBuilder(LLVMContext & Ctx,AttributeSet AS)2066 AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
2067   append_range(Attrs, AS);
2068   assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2069 }
2070 
clear()2071 void AttrBuilder::clear() { Attrs.clear(); }
2072 
2073 /// Attribute comparator that only compares attribute keys. Enum attributes are
2074 /// sorted before string attributes.
2075 struct AttributeComparator {
operator ()AttributeComparator2076   bool operator()(Attribute A0, Attribute A1) const {
2077     bool A0IsString = A0.isStringAttribute();
2078     bool A1IsString = A1.isStringAttribute();
2079     if (A0IsString) {
2080       if (A1IsString)
2081         return A0.getKindAsString() < A1.getKindAsString();
2082       else
2083         return false;
2084     }
2085     if (A1IsString)
2086       return true;
2087     return A0.getKindAsEnum() < A1.getKindAsEnum();
2088   }
operator ()AttributeComparator2089   bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
2090     if (A0.isStringAttribute())
2091       return false;
2092     return A0.getKindAsEnum() < Kind;
2093   }
operator ()AttributeComparator2094   bool operator()(Attribute A0, StringRef Kind) const {
2095     if (A0.isStringAttribute())
2096       return A0.getKindAsString() < Kind;
2097     return true;
2098   }
2099 };
2100 
2101 template <typename K>
addAttributeImpl(SmallVectorImpl<Attribute> & Attrs,K Kind,Attribute Attr)2102 static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
2103                              Attribute Attr) {
2104   auto It = lower_bound(Attrs, Kind, AttributeComparator());
2105   if (It != Attrs.end() && It->hasAttribute(Kind))
2106     std::swap(*It, Attr);
2107   else
2108     Attrs.insert(It, Attr);
2109 }
2110 
addAttribute(Attribute Attr)2111 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
2112   if (Attr.isStringAttribute())
2113     addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2114   else
2115     addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2116   return *this;
2117 }
2118 
addAttribute(Attribute::AttrKind Kind)2119 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
2120   addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2121   return *this;
2122 }
2123 
addAttribute(StringRef A,StringRef V)2124 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
2125   addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2126   return *this;
2127 }
2128 
removeAttribute(Attribute::AttrKind Val)2129 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
2130   assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2131   auto It = lower_bound(Attrs, Val, AttributeComparator());
2132   if (It != Attrs.end() && It->hasAttribute(Val))
2133     Attrs.erase(It);
2134   return *this;
2135 }
2136 
removeAttribute(StringRef A)2137 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
2138   auto It = lower_bound(Attrs, A, AttributeComparator());
2139   if (It != Attrs.end() && It->hasAttribute(A))
2140     Attrs.erase(It);
2141   return *this;
2142 }
2143 
2144 std::optional<uint64_t>
getRawIntAttr(Attribute::AttrKind Kind) const2145 AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
2146   assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2147   Attribute A = getAttribute(Kind);
2148   if (A.isValid())
2149     return A.getValueAsInt();
2150   return std::nullopt;
2151 }
2152 
addRawIntAttr(Attribute::AttrKind Kind,uint64_t Value)2153 AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
2154                                         uint64_t Value) {
2155   return addAttribute(Attribute::get(Ctx, Kind, Value));
2156 }
2157 
2158 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const2159 AttrBuilder::getAllocSizeArgs() const {
2160   Attribute A = getAttribute(Attribute::AllocSize);
2161   if (A.isValid())
2162     return A.getAllocSizeArgs();
2163   return std::nullopt;
2164 }
2165 
addAlignmentAttr(MaybeAlign Align)2166 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
2167   if (!Align)
2168     return *this;
2169 
2170   assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2171   return addRawIntAttr(Attribute::Alignment, Align->value());
2172 }
2173 
addStackAlignmentAttr(MaybeAlign Align)2174 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
2175   // Default alignment, allow the target to define how to align it.
2176   if (!Align)
2177     return *this;
2178 
2179   assert(*Align <= 0x100 && "Alignment too large.");
2180   return addRawIntAttr(Attribute::StackAlignment, Align->value());
2181 }
2182 
addDereferenceableAttr(uint64_t Bytes)2183 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
2184   if (Bytes == 0) return *this;
2185 
2186   return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2187 }
2188 
addDereferenceableOrNullAttr(uint64_t Bytes)2189 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
2190   if (Bytes == 0)
2191     return *this;
2192 
2193   return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2194 }
2195 
2196 AttrBuilder &
addAllocSizeAttr(unsigned ElemSize,const std::optional<unsigned> & NumElems)2197 AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
2198                               const std::optional<unsigned> &NumElems) {
2199   return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2200 }
2201 
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)2202 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
2203   // (0, 0) is our "not present" value, so we need to check for it here.
2204   assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2205   return addRawIntAttr(Attribute::AllocSize, RawArgs);
2206 }
2207 
addVScaleRangeAttr(unsigned MinValue,std::optional<unsigned> MaxValue)2208 AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
2209                                              std::optional<unsigned> MaxValue) {
2210   return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2211 }
2212 
addVScaleRangeAttrFromRawRepr(uint64_t RawArgs)2213 AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
2214   // (0, 0) is not present hence ignore this case
2215   if (RawArgs == 0)
2216     return *this;
2217 
2218   return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2219 }
2220 
addUWTableAttr(UWTableKind Kind)2221 AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
2222   if (Kind == UWTableKind::None)
2223     return *this;
2224   return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2225 }
2226 
addMemoryAttr(MemoryEffects ME)2227 AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
2228   return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2229 }
2230 
addCapturesAttr(CaptureInfo CI)2231 AttrBuilder &AttrBuilder::addCapturesAttr(CaptureInfo CI) {
2232   return addRawIntAttr(Attribute::Captures, CI.toIntValue());
2233 }
2234 
addNoFPClassAttr(FPClassTest Mask)2235 AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
2236   if (Mask == fcNone)
2237     return *this;
2238 
2239   return addRawIntAttr(Attribute::NoFPClass, Mask);
2240 }
2241 
addAllocKindAttr(AllocFnKind Kind)2242 AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
2243   return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2244 }
2245 
getTypeAttr(Attribute::AttrKind Kind) const2246 Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
2247   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2248   Attribute A = getAttribute(Kind);
2249   return A.isValid() ? A.getValueAsType() : nullptr;
2250 }
2251 
addTypeAttr(Attribute::AttrKind Kind,Type * Ty)2252 AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
2253   return addAttribute(Attribute::get(Ctx, Kind, Ty));
2254 }
2255 
addByValAttr(Type * Ty)2256 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
2257   return addTypeAttr(Attribute::ByVal, Ty);
2258 }
2259 
addStructRetAttr(Type * Ty)2260 AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
2261   return addTypeAttr(Attribute::StructRet, Ty);
2262 }
2263 
addByRefAttr(Type * Ty)2264 AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
2265   return addTypeAttr(Attribute::ByRef, Ty);
2266 }
2267 
addPreallocatedAttr(Type * Ty)2268 AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
2269   return addTypeAttr(Attribute::Preallocated, Ty);
2270 }
2271 
addInAllocaAttr(Type * Ty)2272 AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
2273   return addTypeAttr(Attribute::InAlloca, Ty);
2274 }
2275 
addConstantRangeAttr(Attribute::AttrKind Kind,const ConstantRange & CR)2276 AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,
2277                                                const ConstantRange &CR) {
2278   if (CR.isFullSet())
2279     return *this;
2280 
2281   return addAttribute(Attribute::get(Ctx, Kind, CR));
2282 }
2283 
addRangeAttr(const ConstantRange & CR)2284 AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
2285   return addConstantRangeAttr(Attribute::Range, CR);
2286 }
2287 
2288 AttrBuilder &
addConstantRangeListAttr(Attribute::AttrKind Kind,ArrayRef<ConstantRange> Val)2289 AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
2290                                       ArrayRef<ConstantRange> Val) {
2291   return addAttribute(Attribute::get(Ctx, Kind, Val));
2292 }
2293 
addInitializesAttr(const ConstantRangeList & CRL)2294 AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
2295   return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2296 }
2297 
addFromEquivalentMetadata(const Instruction & I)2298 AttrBuilder &AttrBuilder::addFromEquivalentMetadata(const Instruction &I) {
2299   if (I.hasMetadata(LLVMContext::MD_nonnull))
2300     addAttribute(Attribute::NonNull);
2301 
2302   if (I.hasMetadata(LLVMContext::MD_noundef))
2303     addAttribute(Attribute::NoUndef);
2304 
2305   if (const MDNode *Align = I.getMetadata(LLVMContext::MD_align)) {
2306     ConstantInt *CI = mdconst::extract<ConstantInt>(Align->getOperand(0));
2307     addAlignmentAttr(CI->getZExtValue());
2308   }
2309 
2310   if (const MDNode *Dereferenceable =
2311           I.getMetadata(LLVMContext::MD_dereferenceable)) {
2312     ConstantInt *CI =
2313         mdconst::extract<ConstantInt>(Dereferenceable->getOperand(0));
2314     addDereferenceableAttr(CI->getZExtValue());
2315   }
2316 
2317   if (const MDNode *DereferenceableOrNull =
2318           I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) {
2319     ConstantInt *CI =
2320         mdconst::extract<ConstantInt>(DereferenceableOrNull->getOperand(0));
2321     addDereferenceableAttr(CI->getZExtValue());
2322   }
2323 
2324   if (const MDNode *Range = I.getMetadata(LLVMContext::MD_range))
2325     addRangeAttr(getConstantRangeFromMetadata(*Range));
2326 
2327   return *this;
2328 }
2329 
merge(const AttrBuilder & B)2330 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
2331   // TODO: Could make this O(n) as we're merging two sorted lists.
2332   for (const auto &I : B.attrs())
2333     addAttribute(I);
2334 
2335   return *this;
2336 }
2337 
remove(const AttributeMask & AM)2338 AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
2339   erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2340   return *this;
2341 }
2342 
overlaps(const AttributeMask & AM) const2343 bool AttrBuilder::overlaps(const AttributeMask &AM) const {
2344   return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2345 }
2346 
getAttribute(Attribute::AttrKind A) const2347 Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
2348   assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2349   auto It = lower_bound(Attrs, A, AttributeComparator());
2350   if (It != Attrs.end() && It->hasAttribute(A))
2351     return *It;
2352   return {};
2353 }
2354 
getAttribute(StringRef A) const2355 Attribute AttrBuilder::getAttribute(StringRef A) const {
2356   auto It = lower_bound(Attrs, A, AttributeComparator());
2357   if (It != Attrs.end() && It->hasAttribute(A))
2358     return *It;
2359   return {};
2360 }
2361 
getRange() const2362 std::optional<ConstantRange> AttrBuilder::getRange() const {
2363   const Attribute RangeAttr = getAttribute(Attribute::Range);
2364   if (RangeAttr.isValid())
2365     return RangeAttr.getRange();
2366   return std::nullopt;
2367 }
2368 
contains(Attribute::AttrKind A) const2369 bool AttrBuilder::contains(Attribute::AttrKind A) const {
2370   return getAttribute(A).isValid();
2371 }
2372 
contains(StringRef A) const2373 bool AttrBuilder::contains(StringRef A) const {
2374   return getAttribute(A).isValid();
2375 }
2376 
operator ==(const AttrBuilder & B) const2377 bool AttrBuilder::operator==(const AttrBuilder &B) const {
2378   return Attrs == B.Attrs;
2379 }
2380 
2381 //===----------------------------------------------------------------------===//
2382 // AttributeFuncs Function Defintions
2383 //===----------------------------------------------------------------------===//
2384 
2385 /// Returns true if this is a type legal for the 'nofpclass' attribute. This
2386 /// follows the same type rules as FPMathOperator.
isNoFPClassCompatibleType(Type * Ty)2387 bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2388   return FPMathOperator::isSupportedFloatingPointType(Ty);
2389 }
2390 
2391 /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty,AttributeSet AS,AttributeSafetyKind ASK)2392 AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
2393                                                AttributeSafetyKind ASK) {
2394   AttributeMask Incompatible;
2395 
2396   if (!Ty->isIntegerTy()) {
2397     // Attributes that only apply to integers.
2398     if (ASK & ASK_SAFE_TO_DROP)
2399       Incompatible.addAttribute(Attribute::AllocAlign);
2400     if (ASK & ASK_UNSAFE_TO_DROP)
2401       Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2402   }
2403 
2404   if (!Ty->isIntOrIntVectorTy()) {
2405     // Attributes that only apply to integers or vector of integers.
2406     if (ASK & ASK_SAFE_TO_DROP)
2407       Incompatible.addAttribute(Attribute::Range);
2408   } else {
2409     Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2410     if (RangeAttr.isValid() &&
2411         RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2412       Incompatible.addAttribute(Attribute::Range);
2413   }
2414 
2415   if (!Ty->isPointerTy()) {
2416     // Attributes that only apply to pointers.
2417     if (ASK & ASK_SAFE_TO_DROP)
2418       Incompatible.addAttribute(Attribute::NoAlias)
2419           .addAttribute(Attribute::NonNull)
2420           .addAttribute(Attribute::ReadNone)
2421           .addAttribute(Attribute::ReadOnly)
2422           .addAttribute(Attribute::Dereferenceable)
2423           .addAttribute(Attribute::DereferenceableOrNull)
2424           .addAttribute(Attribute::Writable)
2425           .addAttribute(Attribute::DeadOnUnwind)
2426           .addAttribute(Attribute::Initializes)
2427           .addAttribute(Attribute::Captures)
2428           .addAttribute(Attribute::DeadOnReturn);
2429     if (ASK & ASK_UNSAFE_TO_DROP)
2430       Incompatible.addAttribute(Attribute::Nest)
2431           .addAttribute(Attribute::SwiftError)
2432           .addAttribute(Attribute::Preallocated)
2433           .addAttribute(Attribute::InAlloca)
2434           .addAttribute(Attribute::ByVal)
2435           .addAttribute(Attribute::StructRet)
2436           .addAttribute(Attribute::ByRef)
2437           .addAttribute(Attribute::ElementType)
2438           .addAttribute(Attribute::AllocatedPointer);
2439   }
2440 
2441     // Attributes that only apply to pointers or vectors of pointers.
2442   if (!Ty->isPtrOrPtrVectorTy()) {
2443     if (ASK & ASK_SAFE_TO_DROP)
2444       Incompatible.addAttribute(Attribute::Alignment);
2445   }
2446 
2447   if (ASK & ASK_SAFE_TO_DROP) {
2448     if (!isNoFPClassCompatibleType(Ty))
2449       Incompatible.addAttribute(Attribute::NoFPClass);
2450   }
2451 
2452   // Some attributes can apply to all "values" but there are no `void` values.
2453   if (Ty->isVoidTy()) {
2454     if (ASK & ASK_SAFE_TO_DROP)
2455       Incompatible.addAttribute(Attribute::NoUndef);
2456   }
2457 
2458   return Incompatible;
2459 }
2460 
getUBImplyingAttributes()2461 AttributeMask AttributeFuncs::getUBImplyingAttributes() {
2462   AttributeMask AM;
2463   AM.addAttribute(Attribute::NoUndef);
2464   AM.addAttribute(Attribute::Dereferenceable);
2465   AM.addAttribute(Attribute::DereferenceableOrNull);
2466   return AM;
2467 }
2468 
2469 /// Callees with dynamic denormal modes are compatible with any caller mode.
denormModeCompatible(DenormalMode CallerMode,DenormalMode CalleeMode)2470 static bool denormModeCompatible(DenormalMode CallerMode,
2471                                  DenormalMode CalleeMode) {
2472   if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2473     return true;
2474 
2475   // If they don't exactly match, it's OK if the mismatched component is
2476   // dynamic.
2477   if (CalleeMode.Input == CallerMode.Input &&
2478       CalleeMode.Output == DenormalMode::Dynamic)
2479     return true;
2480 
2481   if (CalleeMode.Output == CallerMode.Output &&
2482       CalleeMode.Input == DenormalMode::Dynamic)
2483     return true;
2484   return false;
2485 }
2486 
checkDenormMode(const Function & Caller,const Function & Callee)2487 static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2488   DenormalMode CallerMode = Caller.getDenormalModeRaw();
2489   DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2490 
2491   if (denormModeCompatible(CallerMode, CalleeMode)) {
2492     DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2493     DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2494     if (CallerModeF32 == DenormalMode::getInvalid())
2495       CallerModeF32 = CallerMode;
2496     if (CalleeModeF32 == DenormalMode::getInvalid())
2497       CalleeModeF32 = CalleeMode;
2498     return denormModeCompatible(CallerModeF32, CalleeModeF32);
2499   }
2500 
2501   return false;
2502 }
2503 
checkStrictFP(const Function & Caller,const Function & Callee)2504 static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2505   // Do not inline strictfp function into non-strictfp one. It would require
2506   // conversion of all FP operations in host function to constrained intrinsics.
2507   return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2508          Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2509 }
2510 
2511 template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)2512 static bool isEqual(const Function &Caller, const Function &Callee) {
2513   return Caller.getFnAttribute(AttrClass::getKind()) ==
2514          Callee.getFnAttribute(AttrClass::getKind());
2515 }
2516 
isEqual(const Function & Caller,const Function & Callee,const StringRef & AttrName)2517 static bool isEqual(const Function &Caller, const Function &Callee,
2518                     const StringRef &AttrName) {
2519   return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2520 }
2521 
2522 /// Compute the logical AND of the attributes of the caller and the
2523 /// callee.
2524 ///
2525 /// This function sets the caller's attribute to false if the callee's attribute
2526 /// is false.
2527 template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)2528 static void setAND(Function &Caller, const Function &Callee) {
2529   if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2530       !AttrClass::isSet(Callee, AttrClass::getKind()))
2531     AttrClass::set(Caller, AttrClass::getKind(), false);
2532 }
2533 
2534 /// Compute the logical OR of the attributes of the caller and the
2535 /// callee.
2536 ///
2537 /// This function sets the caller's attribute to true if the callee's attribute
2538 /// is true.
2539 template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)2540 static void setOR(Function &Caller, const Function &Callee) {
2541   if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2542       AttrClass::isSet(Callee, AttrClass::getKind()))
2543     AttrClass::set(Caller, AttrClass::getKind(), true);
2544 }
2545 
2546 /// If the inlined function had a higher stack protection level than the
2547 /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)2548 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2549   // If the calling function has *no* stack protection level (e.g. it was built
2550   // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2551   // change it as that could change the program's semantics.
2552   if (!Caller.hasStackProtectorFnAttr())
2553     return;
2554 
2555   // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2556   // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2557   // clutter to the IR.
2558   AttributeMask OldSSPAttr;
2559   OldSSPAttr.addAttribute(Attribute::StackProtect)
2560       .addAttribute(Attribute::StackProtectStrong)
2561       .addAttribute(Attribute::StackProtectReq);
2562 
2563   if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2564     Caller.removeFnAttrs(OldSSPAttr);
2565     Caller.addFnAttr(Attribute::StackProtectReq);
2566   } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2567              !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2568     Caller.removeFnAttrs(OldSSPAttr);
2569     Caller.addFnAttr(Attribute::StackProtectStrong);
2570   } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2571              !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2572              !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2573     Caller.addFnAttr(Attribute::StackProtect);
2574 }
2575 
2576 /// If the inlined function required stack probes, then ensure that
2577 /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)2578 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2579   if (!Caller.hasFnAttribute("probe-stack") &&
2580       Callee.hasFnAttribute("probe-stack")) {
2581     Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2582   }
2583 }
2584 
2585 /// If the inlined function defines the size of guard region
2586 /// on the stack, then ensure that the calling function defines a guard region
2587 /// that is no larger.
2588 static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)2589 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
2590   Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2591   if (CalleeAttr.isValid()) {
2592     Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2593     if (CallerAttr.isValid()) {
2594       uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2595       CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2596       CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2597 
2598       if (CallerStackProbeSize > CalleeStackProbeSize) {
2599         Caller.addFnAttr(CalleeAttr);
2600       }
2601     } else {
2602       Caller.addFnAttr(CalleeAttr);
2603     }
2604   }
2605 }
2606 
2607 /// If the inlined function defines a min legal vector width, then ensure
2608 /// the calling function has the same or larger min legal vector width. If the
2609 /// caller has the attribute, but the callee doesn't, we need to remove the
2610 /// attribute from the caller since we can't make any guarantees about the
2611 /// caller's requirements.
2612 /// This function is called after the inlining decision has been made so we have
2613 /// to merge the attribute this way. Heuristics that would use
2614 /// min-legal-vector-width to determine inline compatibility would need to be
2615 /// handled as part of inline cost analysis.
2616 static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)2617 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
2618   Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2619   if (CallerAttr.isValid()) {
2620     Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2621     if (CalleeAttr.isValid()) {
2622       uint64_t CallerVectorWidth, CalleeVectorWidth;
2623       CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2624       CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2625       if (CallerVectorWidth < CalleeVectorWidth)
2626         Caller.addFnAttr(CalleeAttr);
2627     } else {
2628       // If the callee doesn't have the attribute then we don't know anything
2629       // and must drop the attribute from the caller.
2630       Caller.removeFnAttr("min-legal-vector-width");
2631     }
2632   }
2633 }
2634 
2635 /// If the inlined function has null_pointer_is_valid attribute,
2636 /// set this attribute in the caller post inlining.
2637 static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)2638 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2639   if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2640     Caller.addFnAttr(Attribute::NullPointerIsValid);
2641   }
2642 }
2643 
2644 struct EnumAttr {
isSetEnumAttr2645   static bool isSet(const Function &Fn,
2646                     Attribute::AttrKind Kind) {
2647     return Fn.hasFnAttribute(Kind);
2648   }
2649 
setEnumAttr2650   static void set(Function &Fn,
2651                   Attribute::AttrKind Kind, bool Val) {
2652     if (Val)
2653       Fn.addFnAttr(Kind);
2654     else
2655       Fn.removeFnAttr(Kind);
2656   }
2657 };
2658 
2659 struct StrBoolAttr {
isSetStrBoolAttr2660   static bool isSet(const Function &Fn,
2661                     StringRef Kind) {
2662     auto A = Fn.getFnAttribute(Kind);
2663     return A.getValueAsString() == "true";
2664   }
2665 
setStrBoolAttr2666   static void set(Function &Fn,
2667                   StringRef Kind, bool Val) {
2668     Fn.addFnAttr(Kind, Val ? "true" : "false");
2669   }
2670 };
2671 
2672 #define GET_ATTR_NAMES
2673 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
2674   struct ENUM_NAME##Attr : EnumAttr {                                          \
2675     static enum Attribute::AttrKind getKind() {                                \
2676       return llvm::Attribute::ENUM_NAME;                                       \
2677     }                                                                          \
2678   };
2679 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME)                             \
2680   struct ENUM_NAME##Attr : StrBoolAttr {                                       \
2681     static StringRef getKind() { return #DISPLAY_NAME; }                       \
2682   };
2683 #include "llvm/IR/Attributes.inc"
2684 
2685 #define GET_ATTR_COMPAT_FUNC
2686 #include "llvm/IR/Attributes.inc"
2687 
areInlineCompatible(const Function & Caller,const Function & Callee)2688 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2689                                          const Function &Callee) {
2690   return hasCompatibleFnAttrs(Caller, Callee);
2691 }
2692 
areOutlineCompatible(const Function & A,const Function & B)2693 bool AttributeFuncs::areOutlineCompatible(const Function &A,
2694                                           const Function &B) {
2695   return hasCompatibleFnAttrs(A, B);
2696 }
2697 
mergeAttributesForInlining(Function & Caller,const Function & Callee)2698 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2699                                                 const Function &Callee) {
2700   mergeFnAttrs(Caller, Callee);
2701 }
2702 
mergeAttributesForOutlining(Function & Base,const Function & ToMerge)2703 void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2704                                                 const Function &ToMerge) {
2705 
2706   // We merge functions so that they meet the most general case.
2707   // For example, if the NoNansFPMathAttr is set in one function, but not in
2708   // the other, in the merged function we can say that the NoNansFPMathAttr
2709   // is not set.
2710   // However if we have the SpeculativeLoadHardeningAttr set true in one
2711   // function, but not the other, we make sure that the function retains
2712   // that aspect in the merged function.
2713   mergeFnAttrs(Base, ToMerge);
2714 }
2715 
updateMinLegalVectorWidthAttr(Function & Fn,uint64_t Width)2716 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2717                                                    uint64_t Width) {
2718   Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2719   if (Attr.isValid()) {
2720     uint64_t OldWidth;
2721     Attr.getValueAsString().getAsInteger(0, OldWidth);
2722     if (Width > OldWidth)
2723       Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2724   }
2725 }
2726