xref: /freebsd/contrib/llvm-project/llvm/lib/IR/Attributes.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/Type.h"
32 #include "llvm/Support/Compiler.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/ModRef.h"
35 #include "llvm/Support/raw_ostream.h"
36 #include <algorithm>
37 #include <cassert>
38 #include <cstddef>
39 #include <cstdint>
40 #include <limits>
41 #include <optional>
42 #include <string>
43 #include <tuple>
44 #include <utility>
45 
46 using namespace llvm;
47 
48 //===----------------------------------------------------------------------===//
49 // Attribute Construction Methods
50 //===----------------------------------------------------------------------===//
51 
52 // allocsize has two integer arguments, but because they're both 32 bits, we can
53 // pack them into one 64-bit value, at the cost of making said value
54 // nonsensical.
55 //
56 // In order to do this, we need to reserve one value of the second (optional)
57 // allocsize argument to signify "not present."
58 static const unsigned AllocSizeNumElemsNotPresent = -1;
59 
packAllocSizeArgs(unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)60 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
61                                   const std::optional<unsigned> &NumElemsArg) {
62   assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
63          "Attempting to pack a reserved value");
64 
65   return uint64_t(ElemSizeArg) << 32 |
66          NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
67 }
68 
69 static std::pair<unsigned, std::optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)70 unpackAllocSizeArgs(uint64_t Num) {
71   unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
72   unsigned ElemSizeArg = Num >> 32;
73 
74   std::optional<unsigned> NumElemsArg;
75   if (NumElems != AllocSizeNumElemsNotPresent)
76     NumElemsArg = NumElems;
77   return std::make_pair(ElemSizeArg, NumElemsArg);
78 }
79 
packVScaleRangeArgs(unsigned MinValue,std::optional<unsigned> MaxValue)80 static uint64_t packVScaleRangeArgs(unsigned MinValue,
81                                     std::optional<unsigned> MaxValue) {
82   return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
83 }
84 
85 static std::pair<unsigned, std::optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value)86 unpackVScaleRangeArgs(uint64_t Value) {
87   unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
88   unsigned MinValue = Value >> 32;
89 
90   return std::make_pair(MinValue,
91                         MaxValue > 0 ? MaxValue : std::optional<unsigned>());
92 }
93 
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)94 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
95                          uint64_t Val) {
96   bool IsIntAttr = Attribute::isIntAttrKind(Kind);
97   assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
98          "Not an enum or int attribute");
99 
100   LLVMContextImpl *pImpl = Context.pImpl;
101   FoldingSetNodeID ID;
102   ID.AddInteger(Kind);
103   if (IsIntAttr)
104     ID.AddInteger(Val);
105   else
106     assert(Val == 0 && "Value must be zero for enum attributes");
107 
108   void *InsertPoint;
109   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
110 
111   if (!PA) {
112     // If we didn't find any existing attributes of the same shape then create a
113     // new one and insert it.
114     if (!IsIntAttr)
115       PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
116     else
117       PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
118     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
119   }
120 
121   // Return the Attribute that we found or created.
122   return Attribute(PA);
123 }
124 
get(LLVMContext & Context,StringRef Kind,StringRef Val)125 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
126   LLVMContextImpl *pImpl = Context.pImpl;
127   FoldingSetNodeID ID;
128   ID.AddString(Kind);
129   if (!Val.empty()) ID.AddString(Val);
130 
131   void *InsertPoint;
132   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
133 
134   if (!PA) {
135     // If we didn't find any existing attributes of the same shape then create a
136     // new one and insert it.
137     void *Mem =
138         pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
139                               alignof(StringAttributeImpl));
140     PA = new (Mem) StringAttributeImpl(Kind, Val);
141     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
142   }
143 
144   // Return the Attribute that we found or created.
145   return Attribute(PA);
146 }
147 
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)148 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
149                          Type *Ty) {
150   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
151   LLVMContextImpl *pImpl = Context.pImpl;
152   FoldingSetNodeID ID;
153   ID.AddInteger(Kind);
154   ID.AddPointer(Ty);
155 
156   void *InsertPoint;
157   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
158 
159   if (!PA) {
160     // If we didn't find any existing attributes of the same shape then create a
161     // new one and insert it.
162     PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
163     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
164   }
165 
166   // Return the Attribute that we found or created.
167   return Attribute(PA);
168 }
169 
get(LLVMContext & Context,Attribute::AttrKind Kind,const ConstantRange & CR)170 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
171                          const ConstantRange &CR) {
172   assert(Attribute::isConstantRangeAttrKind(Kind) &&
173          "Not a ConstantRange attribute");
174   LLVMContextImpl *pImpl = Context.pImpl;
175   FoldingSetNodeID ID;
176   ID.AddInteger(Kind);
177   CR.getLower().Profile(ID);
178   CR.getUpper().Profile(ID);
179 
180   void *InsertPoint;
181   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
182 
183   if (!PA) {
184     // If we didn't find any existing attributes of the same shape then create a
185     // new one and insert it.
186     PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
187         ConstantRangeAttributeImpl(Kind, CR);
188     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
189   }
190 
191   // Return the Attribute that we found or created.
192   return Attribute(PA);
193 }
194 
get(LLVMContext & Context,Attribute::AttrKind Kind,ArrayRef<ConstantRange> Val)195 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
196                          ArrayRef<ConstantRange> Val) {
197   assert(Attribute::isConstantRangeListAttrKind(Kind) &&
198          "Not a ConstantRangeList attribute");
199   LLVMContextImpl *pImpl = Context.pImpl;
200   FoldingSetNodeID ID;
201   ID.AddInteger(Kind);
202   ID.AddInteger(Val.size());
203   for (auto &CR : Val) {
204     CR.getLower().Profile(ID);
205     CR.getUpper().Profile(ID);
206   }
207 
208   void *InsertPoint;
209   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
210 
211   if (!PA) {
212     // If we didn't find any existing attributes of the same shape then create a
213     // new one and insert it.
214     // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
215     // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
216     // allocation and record the allocated pointer in
217     // `ConstantRangeListAttributes`. LLVMContext destructor will call the
218     // destructor of the allocated pointer explicitly.
219     void *Mem = pImpl->Alloc.Allocate(
220         ConstantRangeListAttributeImpl::totalSizeToAlloc(Val),
221         alignof(ConstantRangeListAttributeImpl));
222     PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
223     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
224     pImpl->ConstantRangeListAttributes.push_back(
225         reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
226   }
227 
228   // Return the Attribute that we found or created.
229   return Attribute(PA);
230 }
231 
getWithAlignment(LLVMContext & Context,Align A)232 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
233   assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
234   return get(Context, Alignment, A.value());
235 }
236 
getWithStackAlignment(LLVMContext & Context,Align A)237 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
238   assert(A <= 0x100 && "Alignment too large.");
239   return get(Context, StackAlignment, A.value());
240 }
241 
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)242 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
243                                                 uint64_t Bytes) {
244   assert(Bytes && "Bytes must be non-zero.");
245   return get(Context, Dereferenceable, Bytes);
246 }
247 
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)248 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
249                                                        uint64_t Bytes) {
250   assert(Bytes && "Bytes must be non-zero.");
251   return get(Context, DereferenceableOrNull, Bytes);
252 }
253 
getWithByValType(LLVMContext & Context,Type * Ty)254 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
255   return get(Context, ByVal, Ty);
256 }
257 
getWithStructRetType(LLVMContext & Context,Type * Ty)258 Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
259   return get(Context, StructRet, Ty);
260 }
261 
getWithByRefType(LLVMContext & Context,Type * Ty)262 Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
263   return get(Context, ByRef, Ty);
264 }
265 
getWithPreallocatedType(LLVMContext & Context,Type * Ty)266 Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
267   return get(Context, Preallocated, Ty);
268 }
269 
getWithInAllocaType(LLVMContext & Context,Type * Ty)270 Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
271   return get(Context, InAlloca, Ty);
272 }
273 
getWithUWTableKind(LLVMContext & Context,UWTableKind Kind)274 Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
275                                         UWTableKind Kind) {
276   return get(Context, UWTable, uint64_t(Kind));
277 }
278 
getWithMemoryEffects(LLVMContext & Context,MemoryEffects ME)279 Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
280                                           MemoryEffects ME) {
281   return get(Context, Memory, ME.toIntValue());
282 }
283 
getWithNoFPClass(LLVMContext & Context,FPClassTest ClassMask)284 Attribute Attribute::getWithNoFPClass(LLVMContext &Context,
285                                       FPClassTest ClassMask) {
286   return get(Context, NoFPClass, ClassMask);
287 }
288 
289 Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)290 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
291                                 const std::optional<unsigned> &NumElemsArg) {
292   assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
293          "Invalid allocsize arguments -- given allocsize(0, 0)");
294   return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
295 }
296 
getWithVScaleRangeArgs(LLVMContext & Context,unsigned MinValue,unsigned MaxValue)297 Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
298                                             unsigned MinValue,
299                                             unsigned MaxValue) {
300   return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
301 }
302 
getAttrKindFromName(StringRef AttrName)303 Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
304   return StringSwitch<Attribute::AttrKind>(AttrName)
305 #define GET_ATTR_NAMES
306 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
307   .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
308 #include "llvm/IR/Attributes.inc"
309       .Default(Attribute::None);
310 }
311 
getNameFromAttrKind(Attribute::AttrKind AttrKind)312 StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
313   switch (AttrKind) {
314 #define GET_ATTR_NAMES
315 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
316   case Attribute::ENUM_NAME:                                                   \
317     return #DISPLAY_NAME;
318 #include "llvm/IR/Attributes.inc"
319   case Attribute::None:
320     return "none";
321   default:
322     llvm_unreachable("invalid Kind");
323   }
324 }
325 
isExistingAttribute(StringRef Name)326 bool Attribute::isExistingAttribute(StringRef Name) {
327   return StringSwitch<bool>(Name)
328 #define GET_ATTR_NAMES
329 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
330 #include "llvm/IR/Attributes.inc"
331       .Default(false);
332 }
333 
334 //===----------------------------------------------------------------------===//
335 // Attribute Accessor Methods
336 //===----------------------------------------------------------------------===//
337 
isEnumAttribute() const338 bool Attribute::isEnumAttribute() const {
339   return pImpl && pImpl->isEnumAttribute();
340 }
341 
isIntAttribute() const342 bool Attribute::isIntAttribute() const {
343   return pImpl && pImpl->isIntAttribute();
344 }
345 
isStringAttribute() const346 bool Attribute::isStringAttribute() const {
347   return pImpl && pImpl->isStringAttribute();
348 }
349 
isTypeAttribute() const350 bool Attribute::isTypeAttribute() const {
351   return pImpl && pImpl->isTypeAttribute();
352 }
353 
isConstantRangeAttribute() const354 bool Attribute::isConstantRangeAttribute() const {
355   return pImpl && pImpl->isConstantRangeAttribute();
356 }
357 
isConstantRangeListAttribute() const358 bool Attribute::isConstantRangeListAttribute() const {
359   return pImpl && pImpl->isConstantRangeListAttribute();
360 }
361 
getKindAsEnum() const362 Attribute::AttrKind Attribute::getKindAsEnum() const {
363   if (!pImpl) return None;
364   assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
365           isConstantRangeAttribute() || isConstantRangeListAttribute()) &&
366          "Invalid attribute type to get the kind as an enum!");
367   return pImpl->getKindAsEnum();
368 }
369 
getValueAsInt() const370 uint64_t Attribute::getValueAsInt() const {
371   if (!pImpl) return 0;
372   assert(isIntAttribute() &&
373          "Expected the attribute to be an integer attribute!");
374   return pImpl->getValueAsInt();
375 }
376 
getValueAsBool() const377 bool Attribute::getValueAsBool() const {
378   if (!pImpl) return false;
379   assert(isStringAttribute() &&
380          "Expected the attribute to be a string attribute!");
381   return pImpl->getValueAsBool();
382 }
383 
getKindAsString() const384 StringRef Attribute::getKindAsString() const {
385   if (!pImpl) return {};
386   assert(isStringAttribute() &&
387          "Invalid attribute type to get the kind as a string!");
388   return pImpl->getKindAsString();
389 }
390 
getValueAsString() const391 StringRef Attribute::getValueAsString() const {
392   if (!pImpl) return {};
393   assert(isStringAttribute() &&
394          "Invalid attribute type to get the value as a string!");
395   return pImpl->getValueAsString();
396 }
397 
getValueAsType() const398 Type *Attribute::getValueAsType() const {
399   if (!pImpl) return {};
400   assert(isTypeAttribute() &&
401          "Invalid attribute type to get the value as a type!");
402   return pImpl->getValueAsType();
403 }
404 
getValueAsConstantRange() const405 const ConstantRange &Attribute::getValueAsConstantRange() const {
406   assert(isConstantRangeAttribute() &&
407          "Invalid attribute type to get the value as a ConstantRange!");
408   return pImpl->getValueAsConstantRange();
409 }
410 
getValueAsConstantRangeList() const411 ArrayRef<ConstantRange> Attribute::getValueAsConstantRangeList() const {
412   assert(isConstantRangeListAttribute() &&
413          "Invalid attribute type to get the value as a ConstantRangeList!");
414   return pImpl->getValueAsConstantRangeList();
415 }
416 
hasAttribute(AttrKind Kind) const417 bool Attribute::hasAttribute(AttrKind Kind) const {
418   return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
419 }
420 
hasAttribute(StringRef Kind) const421 bool Attribute::hasAttribute(StringRef Kind) const {
422   if (!isStringAttribute()) return false;
423   return pImpl && pImpl->hasAttribute(Kind);
424 }
425 
getAlignment() const426 MaybeAlign Attribute::getAlignment() const {
427   assert(hasAttribute(Attribute::Alignment) &&
428          "Trying to get alignment from non-alignment attribute!");
429   return MaybeAlign(pImpl->getValueAsInt());
430 }
431 
getStackAlignment() const432 MaybeAlign Attribute::getStackAlignment() const {
433   assert(hasAttribute(Attribute::StackAlignment) &&
434          "Trying to get alignment from non-alignment attribute!");
435   return MaybeAlign(pImpl->getValueAsInt());
436 }
437 
getDereferenceableBytes() const438 uint64_t Attribute::getDereferenceableBytes() const {
439   assert(hasAttribute(Attribute::Dereferenceable) &&
440          "Trying to get dereferenceable bytes from "
441          "non-dereferenceable attribute!");
442   return pImpl->getValueAsInt();
443 }
444 
getDereferenceableOrNullBytes() const445 uint64_t Attribute::getDereferenceableOrNullBytes() const {
446   assert(hasAttribute(Attribute::DereferenceableOrNull) &&
447          "Trying to get dereferenceable bytes from "
448          "non-dereferenceable attribute!");
449   return pImpl->getValueAsInt();
450 }
451 
452 std::pair<unsigned, std::optional<unsigned>>
getAllocSizeArgs() const453 Attribute::getAllocSizeArgs() const {
454   assert(hasAttribute(Attribute::AllocSize) &&
455          "Trying to get allocsize args from non-allocsize attribute");
456   return unpackAllocSizeArgs(pImpl->getValueAsInt());
457 }
458 
getVScaleRangeMin() const459 unsigned Attribute::getVScaleRangeMin() const {
460   assert(hasAttribute(Attribute::VScaleRange) &&
461          "Trying to get vscale args from non-vscale attribute");
462   return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
463 }
464 
getVScaleRangeMax() const465 std::optional<unsigned> Attribute::getVScaleRangeMax() const {
466   assert(hasAttribute(Attribute::VScaleRange) &&
467          "Trying to get vscale args from non-vscale attribute");
468   return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
469 }
470 
getUWTableKind() const471 UWTableKind Attribute::getUWTableKind() const {
472   assert(hasAttribute(Attribute::UWTable) &&
473          "Trying to get unwind table kind from non-uwtable attribute");
474   return UWTableKind(pImpl->getValueAsInt());
475 }
476 
getAllocKind() const477 AllocFnKind Attribute::getAllocKind() const {
478   assert(hasAttribute(Attribute::AllocKind) &&
479          "Trying to get allockind value from non-allockind attribute");
480   return AllocFnKind(pImpl->getValueAsInt());
481 }
482 
getMemoryEffects() const483 MemoryEffects Attribute::getMemoryEffects() const {
484   assert(hasAttribute(Attribute::Memory) &&
485          "Can only call getMemoryEffects() on memory attribute");
486   return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
487 }
488 
getNoFPClass() const489 FPClassTest Attribute::getNoFPClass() const {
490   assert(hasAttribute(Attribute::NoFPClass) &&
491          "Can only call getNoFPClass() on nofpclass attribute");
492   return static_cast<FPClassTest>(pImpl->getValueAsInt());
493 }
494 
getRange() const495 const ConstantRange &Attribute::getRange() const {
496   assert(hasAttribute(Attribute::Range) &&
497          "Trying to get range args from non-range attribute");
498   return pImpl->getValueAsConstantRange();
499 }
500 
getInitializes() const501 ArrayRef<ConstantRange> Attribute::getInitializes() const {
502   assert(hasAttribute(Attribute::Initializes) &&
503          "Trying to get initializes attr from non-ConstantRangeList attribute");
504   return pImpl->getValueAsConstantRangeList();
505 }
506 
getModRefStr(ModRefInfo MR)507 static const char *getModRefStr(ModRefInfo MR) {
508   switch (MR) {
509   case ModRefInfo::NoModRef:
510     return "none";
511   case ModRefInfo::Ref:
512     return "read";
513   case ModRefInfo::Mod:
514     return "write";
515   case ModRefInfo::ModRef:
516     return "readwrite";
517   }
518   llvm_unreachable("Invalid ModRefInfo");
519 }
520 
getAsString(bool InAttrGrp) const521 std::string Attribute::getAsString(bool InAttrGrp) const {
522   if (!pImpl) return {};
523 
524   if (isEnumAttribute())
525     return getNameFromAttrKind(getKindAsEnum()).str();
526 
527   if (isTypeAttribute()) {
528     std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
529     Result += '(';
530     raw_string_ostream OS(Result);
531     getValueAsType()->print(OS, false, true);
532     OS.flush();
533     Result += ')';
534     return Result;
535   }
536 
537   // FIXME: These should be output like this:
538   //
539   //   align=4
540   //   alignstack=8
541   //
542   if (hasAttribute(Attribute::Alignment))
543     return (InAttrGrp ? "align=" + Twine(getValueAsInt())
544                       : "align " + Twine(getValueAsInt()))
545         .str();
546 
547   auto AttrWithBytesToString = [&](const char *Name) {
548     return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
549                       : Name + ("(" + Twine(getValueAsInt())) + ")")
550         .str();
551   };
552 
553   if (hasAttribute(Attribute::StackAlignment))
554     return AttrWithBytesToString("alignstack");
555 
556   if (hasAttribute(Attribute::Dereferenceable))
557     return AttrWithBytesToString("dereferenceable");
558 
559   if (hasAttribute(Attribute::DereferenceableOrNull))
560     return AttrWithBytesToString("dereferenceable_or_null");
561 
562   if (hasAttribute(Attribute::AllocSize)) {
563     unsigned ElemSize;
564     std::optional<unsigned> NumElems;
565     std::tie(ElemSize, NumElems) = getAllocSizeArgs();
566 
567     return (NumElems
568                 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
569                 : "allocsize(" + Twine(ElemSize) + ")")
570         .str();
571   }
572 
573   if (hasAttribute(Attribute::VScaleRange)) {
574     unsigned MinValue = getVScaleRangeMin();
575     std::optional<unsigned> MaxValue = getVScaleRangeMax();
576     return ("vscale_range(" + Twine(MinValue) + "," +
577             Twine(MaxValue.value_or(0)) + ")")
578         .str();
579   }
580 
581   if (hasAttribute(Attribute::UWTable)) {
582     UWTableKind Kind = getUWTableKind();
583     assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
584     return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
585   }
586 
587   if (hasAttribute(Attribute::AllocKind)) {
588     AllocFnKind Kind = getAllocKind();
589     SmallVector<StringRef> parts;
590     if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
591       parts.push_back("alloc");
592     if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
593       parts.push_back("realloc");
594     if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
595       parts.push_back("free");
596     if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
597       parts.push_back("uninitialized");
598     if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
599       parts.push_back("zeroed");
600     if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
601       parts.push_back("aligned");
602     return ("allockind(\"" +
603             Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
604         .str();
605   }
606 
607   if (hasAttribute(Attribute::Memory)) {
608     std::string Result;
609     raw_string_ostream OS(Result);
610     bool First = true;
611     OS << "memory(";
612 
613     MemoryEffects ME = getMemoryEffects();
614 
615     // Print access kind for "other" as the default access kind. This way it
616     // will apply to any new location kinds that get split out of "other".
617     ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other);
618     if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
619       First = false;
620       OS << getModRefStr(OtherMR);
621     }
622 
623     for (auto Loc : MemoryEffects::locations()) {
624       ModRefInfo MR = ME.getModRef(Loc);
625       if (MR == OtherMR)
626         continue;
627 
628       if (!First)
629         OS << ", ";
630       First = false;
631 
632       switch (Loc) {
633       case IRMemLocation::ArgMem:
634         OS << "argmem: ";
635         break;
636       case IRMemLocation::InaccessibleMem:
637         OS << "inaccessiblemem: ";
638         break;
639       case IRMemLocation::Other:
640         llvm_unreachable("This is represented as the default access kind");
641       }
642       OS << getModRefStr(MR);
643     }
644     OS << ")";
645     OS.flush();
646     return Result;
647   }
648 
649   if (hasAttribute(Attribute::NoFPClass)) {
650     std::string Result = "nofpclass";
651     raw_string_ostream OS(Result);
652     OS << getNoFPClass();
653     return Result;
654   }
655 
656   if (hasAttribute(Attribute::Range)) {
657     std::string Result;
658     raw_string_ostream OS(Result);
659     const ConstantRange &CR = getValueAsConstantRange();
660     OS << "range(";
661     OS << "i" << CR.getBitWidth() << " ";
662     OS << CR.getLower() << ", " << CR.getUpper();
663     OS << ")";
664     OS.flush();
665     return Result;
666   }
667 
668   if (hasAttribute(Attribute::Initializes)) {
669     std::string Result;
670     raw_string_ostream OS(Result);
671     ConstantRangeList CRL = getInitializes();
672     OS << "initializes(";
673     CRL.print(OS);
674     OS << ")";
675     OS.flush();
676     return Result;
677   }
678 
679   // Convert target-dependent attributes to strings of the form:
680   //
681   //   "kind"
682   //   "kind" = "value"
683   //
684   if (isStringAttribute()) {
685     std::string Result;
686     {
687       raw_string_ostream OS(Result);
688       OS << '"' << getKindAsString() << '"';
689 
690       // Since some attribute strings contain special characters that cannot be
691       // printable, those have to be escaped to make the attribute value
692       // printable as is.  e.g. "\01__gnu_mcount_nc"
693       const auto &AttrVal = pImpl->getValueAsString();
694       if (!AttrVal.empty()) {
695         OS << "=\"";
696         printEscapedString(AttrVal, OS);
697         OS << "\"";
698       }
699     }
700     return Result;
701   }
702 
703   llvm_unreachable("Unknown attribute");
704 }
705 
hasParentContext(LLVMContext & C) const706 bool Attribute::hasParentContext(LLVMContext &C) const {
707   assert(isValid() && "invalid Attribute doesn't refer to any context");
708   FoldingSetNodeID ID;
709   pImpl->Profile(ID);
710   void *Unused;
711   return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
712 }
713 
operator <(Attribute A) const714 bool Attribute::operator<(Attribute A) const {
715   if (!pImpl && !A.pImpl) return false;
716   if (!pImpl) return true;
717   if (!A.pImpl) return false;
718   return *pImpl < *A.pImpl;
719 }
720 
Profile(FoldingSetNodeID & ID) const721 void Attribute::Profile(FoldingSetNodeID &ID) const {
722   ID.AddPointer(pImpl);
723 }
724 
725 enum AttributeProperty {
726   FnAttr = (1 << 0),
727   ParamAttr = (1 << 1),
728   RetAttr = (1 << 2),
729 };
730 
731 #define GET_ATTR_PROP_TABLE
732 #include "llvm/IR/Attributes.inc"
733 
hasAttributeProperty(Attribute::AttrKind Kind,AttributeProperty Prop)734 static bool hasAttributeProperty(Attribute::AttrKind Kind,
735                                  AttributeProperty Prop) {
736   unsigned Index = Kind - 1;
737   assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
738   return AttrPropTable[Index] & Prop;
739 }
740 
canUseAsFnAttr(AttrKind Kind)741 bool Attribute::canUseAsFnAttr(AttrKind Kind) {
742   return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
743 }
744 
canUseAsParamAttr(AttrKind Kind)745 bool Attribute::canUseAsParamAttr(AttrKind Kind) {
746   return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
747 }
748 
canUseAsRetAttr(AttrKind Kind)749 bool Attribute::canUseAsRetAttr(AttrKind Kind) {
750   return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
751 }
752 
753 //===----------------------------------------------------------------------===//
754 // AttributeImpl Definition
755 //===----------------------------------------------------------------------===//
756 
hasAttribute(Attribute::AttrKind A) const757 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
758   if (isStringAttribute()) return false;
759   return getKindAsEnum() == A;
760 }
761 
hasAttribute(StringRef Kind) const762 bool AttributeImpl::hasAttribute(StringRef Kind) const {
763   if (!isStringAttribute()) return false;
764   return getKindAsString() == Kind;
765 }
766 
getKindAsEnum() const767 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
768   assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
769          isConstantRangeAttribute() || isConstantRangeListAttribute());
770   return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
771 }
772 
getValueAsInt() const773 uint64_t AttributeImpl::getValueAsInt() const {
774   assert(isIntAttribute());
775   return static_cast<const IntAttributeImpl *>(this)->getValue();
776 }
777 
getValueAsBool() const778 bool AttributeImpl::getValueAsBool() const {
779   assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
780   return getValueAsString() == "true";
781 }
782 
getKindAsString() const783 StringRef AttributeImpl::getKindAsString() const {
784   assert(isStringAttribute());
785   return static_cast<const StringAttributeImpl *>(this)->getStringKind();
786 }
787 
getValueAsString() const788 StringRef AttributeImpl::getValueAsString() const {
789   assert(isStringAttribute());
790   return static_cast<const StringAttributeImpl *>(this)->getStringValue();
791 }
792 
getValueAsType() const793 Type *AttributeImpl::getValueAsType() const {
794   assert(isTypeAttribute());
795   return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
796 }
797 
getValueAsConstantRange() const798 const ConstantRange &AttributeImpl::getValueAsConstantRange() const {
799   assert(isConstantRangeAttribute());
800   return static_cast<const ConstantRangeAttributeImpl *>(this)
801       ->getConstantRangeValue();
802 }
803 
getValueAsConstantRangeList() const804 ArrayRef<ConstantRange> AttributeImpl::getValueAsConstantRangeList() const {
805   assert(isConstantRangeListAttribute());
806   return static_cast<const ConstantRangeListAttributeImpl *>(this)
807       ->getConstantRangeListValue();
808 }
809 
operator <(const AttributeImpl & AI) const810 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
811   if (this == &AI)
812     return false;
813 
814   // This sorts the attributes with Attribute::AttrKinds coming first (sorted
815   // relative to their enum value) and then strings.
816   if (!isStringAttribute()) {
817     if (AI.isStringAttribute())
818       return true;
819     if (getKindAsEnum() != AI.getKindAsEnum())
820       return getKindAsEnum() < AI.getKindAsEnum();
821     assert(!AI.isEnumAttribute() && "Non-unique attribute");
822     assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
823     assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
824     assert(!AI.isConstantRangeListAttribute() &&
825            "Unclear how to compare range list");
826     // TODO: Is this actually needed?
827     assert(AI.isIntAttribute() && "Only possibility left");
828     return getValueAsInt() < AI.getValueAsInt();
829   }
830 
831   if (!AI.isStringAttribute())
832     return false;
833   if (getKindAsString() == AI.getKindAsString())
834     return getValueAsString() < AI.getValueAsString();
835   return getKindAsString() < AI.getKindAsString();
836 }
837 
838 //===----------------------------------------------------------------------===//
839 // AttributeSet Definition
840 //===----------------------------------------------------------------------===//
841 
get(LLVMContext & C,const AttrBuilder & B)842 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
843   return AttributeSet(AttributeSetNode::get(C, B));
844 }
845 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)846 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
847   return AttributeSet(AttributeSetNode::get(C, Attrs));
848 }
849 
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const850 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
851                                         Attribute::AttrKind Kind) const {
852   if (hasAttribute(Kind)) return *this;
853   AttrBuilder B(C);
854   B.addAttribute(Kind);
855   return addAttributes(C, AttributeSet::get(C, B));
856 }
857 
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const858 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
859                                         StringRef Value) const {
860   AttrBuilder B(C);
861   B.addAttribute(Kind, Value);
862   return addAttributes(C, AttributeSet::get(C, B));
863 }
864 
addAttributes(LLVMContext & C,const AttributeSet AS) const865 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
866                                          const AttributeSet AS) const {
867   if (!hasAttributes())
868     return AS;
869 
870   if (!AS.hasAttributes())
871     return *this;
872 
873   AttrBuilder B(C, *this);
874   B.merge(AttrBuilder(C, AS));
875   return get(C, B);
876 }
877 
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const878 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
879                                              Attribute::AttrKind Kind) const {
880   if (!hasAttribute(Kind)) return *this;
881   AttrBuilder B(C, *this);
882   B.removeAttribute(Kind);
883   return get(C, B);
884 }
885 
removeAttribute(LLVMContext & C,StringRef Kind) const886 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
887                                              StringRef Kind) const {
888   if (!hasAttribute(Kind)) return *this;
889   AttrBuilder B(C, *this);
890   B.removeAttribute(Kind);
891   return get(C, B);
892 }
893 
removeAttributes(LLVMContext & C,const AttributeMask & Attrs) const894 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
895                                             const AttributeMask &Attrs) const {
896   AttrBuilder B(C, *this);
897   // If there is nothing to remove, directly return the original set.
898   if (!B.overlaps(Attrs))
899     return *this;
900 
901   B.remove(Attrs);
902   return get(C, B);
903 }
904 
getNumAttributes() const905 unsigned AttributeSet::getNumAttributes() const {
906   return SetNode ? SetNode->getNumAttributes() : 0;
907 }
908 
hasAttribute(Attribute::AttrKind Kind) const909 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
910   return SetNode ? SetNode->hasAttribute(Kind) : false;
911 }
912 
hasAttribute(StringRef Kind) const913 bool AttributeSet::hasAttribute(StringRef Kind) const {
914   return SetNode ? SetNode->hasAttribute(Kind) : false;
915 }
916 
getAttribute(Attribute::AttrKind Kind) const917 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
918   return SetNode ? SetNode->getAttribute(Kind) : Attribute();
919 }
920 
getAttribute(StringRef Kind) const921 Attribute AttributeSet::getAttribute(StringRef Kind) const {
922   return SetNode ? SetNode->getAttribute(Kind) : Attribute();
923 }
924 
getAlignment() const925 MaybeAlign AttributeSet::getAlignment() const {
926   return SetNode ? SetNode->getAlignment() : std::nullopt;
927 }
928 
getStackAlignment() const929 MaybeAlign AttributeSet::getStackAlignment() const {
930   return SetNode ? SetNode->getStackAlignment() : std::nullopt;
931 }
932 
getDereferenceableBytes() const933 uint64_t AttributeSet::getDereferenceableBytes() const {
934   return SetNode ? SetNode->getDereferenceableBytes() : 0;
935 }
936 
getDereferenceableOrNullBytes() const937 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
938   return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
939 }
940 
getByRefType() const941 Type *AttributeSet::getByRefType() const {
942   return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
943 }
944 
getByValType() const945 Type *AttributeSet::getByValType() const {
946   return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
947 }
948 
getStructRetType() const949 Type *AttributeSet::getStructRetType() const {
950   return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
951 }
952 
getPreallocatedType() const953 Type *AttributeSet::getPreallocatedType() const {
954   return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
955 }
956 
getInAllocaType() const957 Type *AttributeSet::getInAllocaType() const {
958   return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
959 }
960 
getElementType() const961 Type *AttributeSet::getElementType() const {
962   return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
963 }
964 
965 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const966 AttributeSet::getAllocSizeArgs() const {
967   if (SetNode)
968     return SetNode->getAllocSizeArgs();
969   return std::nullopt;
970 }
971 
getVScaleRangeMin() const972 unsigned AttributeSet::getVScaleRangeMin() const {
973   return SetNode ? SetNode->getVScaleRangeMin() : 1;
974 }
975 
getVScaleRangeMax() const976 std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
977   return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
978 }
979 
getUWTableKind() const980 UWTableKind AttributeSet::getUWTableKind() const {
981   return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
982 }
983 
getAllocKind() const984 AllocFnKind AttributeSet::getAllocKind() const {
985   return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
986 }
987 
getMemoryEffects() const988 MemoryEffects AttributeSet::getMemoryEffects() const {
989   return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
990 }
991 
getNoFPClass() const992 FPClassTest AttributeSet::getNoFPClass() const {
993   return SetNode ? SetNode->getNoFPClass() : fcNone;
994 }
995 
getAsString(bool InAttrGrp) const996 std::string AttributeSet::getAsString(bool InAttrGrp) const {
997   return SetNode ? SetNode->getAsString(InAttrGrp) : "";
998 }
999 
hasParentContext(LLVMContext & C) const1000 bool AttributeSet::hasParentContext(LLVMContext &C) const {
1001   assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1002   FoldingSetNodeID ID;
1003   SetNode->Profile(ID);
1004   void *Unused;
1005   return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1006 }
1007 
begin() const1008 AttributeSet::iterator AttributeSet::begin() const {
1009   return SetNode ? SetNode->begin() : nullptr;
1010 }
1011 
end() const1012 AttributeSet::iterator AttributeSet::end() const {
1013   return SetNode ? SetNode->end() : nullptr;
1014 }
1015 
1016 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1017 LLVM_DUMP_METHOD void AttributeSet::dump() const {
1018   dbgs() << "AS =\n";
1019     dbgs() << "  { ";
1020     dbgs() << getAsString(true) << " }\n";
1021 }
1022 #endif
1023 
1024 //===----------------------------------------------------------------------===//
1025 // AttributeSetNode Definition
1026 //===----------------------------------------------------------------------===//
1027 
AttributeSetNode(ArrayRef<Attribute> Attrs)1028 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1029     : NumAttrs(Attrs.size()) {
1030   // There's memory after the node where we can store the entries in.
1031   llvm::copy(Attrs, getTrailingObjects<Attribute>());
1032 
1033   for (const auto &I : *this) {
1034     if (I.isStringAttribute())
1035       StringAttrs.insert({ I.getKindAsString(), I });
1036     else
1037       AvailableAttrs.addAttribute(I.getKindAsEnum());
1038   }
1039 }
1040 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)1041 AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
1042                                         ArrayRef<Attribute> Attrs) {
1043   SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
1044   llvm::sort(SortedAttrs);
1045   return getSorted(C, SortedAttrs);
1046 }
1047 
getSorted(LLVMContext & C,ArrayRef<Attribute> SortedAttrs)1048 AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1049                                               ArrayRef<Attribute> SortedAttrs) {
1050   if (SortedAttrs.empty())
1051     return nullptr;
1052 
1053   // Build a key to look up the existing attributes.
1054   LLVMContextImpl *pImpl = C.pImpl;
1055   FoldingSetNodeID ID;
1056 
1057   assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1058   for (const auto &Attr : SortedAttrs)
1059     Attr.Profile(ID);
1060 
1061   void *InsertPoint;
1062   AttributeSetNode *PA =
1063     pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1064 
1065   // If we didn't find any existing attributes of the same shape then create a
1066   // new one and insert it.
1067   if (!PA) {
1068     // Coallocate entries after the AttributeSetNode itself.
1069     void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1070     PA = new (Mem) AttributeSetNode(SortedAttrs);
1071     pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1072   }
1073 
1074   // Return the AttributeSetNode that we found or created.
1075   return PA;
1076 }
1077 
get(LLVMContext & C,const AttrBuilder & B)1078 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
1079   return getSorted(C, B.attrs());
1080 }
1081 
hasAttribute(StringRef Kind) const1082 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
1083   return StringAttrs.count(Kind);
1084 }
1085 
1086 std::optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const1087 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1088   // Do a quick presence check.
1089   if (!hasAttribute(Kind))
1090     return std::nullopt;
1091 
1092   // Attributes in a set are sorted by enum value, followed by string
1093   // attributes. Binary search the one we want.
1094   const Attribute *I =
1095       std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1096                        [](Attribute A, Attribute::AttrKind Kind) {
1097                          return A.getKindAsEnum() < Kind;
1098                        });
1099   assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1100   return *I;
1101 }
1102 
getAttribute(Attribute::AttrKind Kind) const1103 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
1104   if (auto A = findEnumAttribute(Kind))
1105     return *A;
1106   return {};
1107 }
1108 
getAttribute(StringRef Kind) const1109 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
1110   return StringAttrs.lookup(Kind);
1111 }
1112 
getAlignment() const1113 MaybeAlign AttributeSetNode::getAlignment() const {
1114   if (auto A = findEnumAttribute(Attribute::Alignment))
1115     return A->getAlignment();
1116   return std::nullopt;
1117 }
1118 
getStackAlignment() const1119 MaybeAlign AttributeSetNode::getStackAlignment() const {
1120   if (auto A = findEnumAttribute(Attribute::StackAlignment))
1121     return A->getStackAlignment();
1122   return std::nullopt;
1123 }
1124 
getAttributeType(Attribute::AttrKind Kind) const1125 Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
1126   if (auto A = findEnumAttribute(Kind))
1127     return A->getValueAsType();
1128   return nullptr;
1129 }
1130 
getDereferenceableBytes() const1131 uint64_t AttributeSetNode::getDereferenceableBytes() const {
1132   if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1133     return A->getDereferenceableBytes();
1134   return 0;
1135 }
1136 
getDereferenceableOrNullBytes() const1137 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
1138   if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1139     return A->getDereferenceableOrNullBytes();
1140   return 0;
1141 }
1142 
1143 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1144 AttributeSetNode::getAllocSizeArgs() const {
1145   if (auto A = findEnumAttribute(Attribute::AllocSize))
1146     return A->getAllocSizeArgs();
1147   return std::nullopt;
1148 }
1149 
getVScaleRangeMin() const1150 unsigned AttributeSetNode::getVScaleRangeMin() const {
1151   if (auto A = findEnumAttribute(Attribute::VScaleRange))
1152     return A->getVScaleRangeMin();
1153   return 1;
1154 }
1155 
getVScaleRangeMax() const1156 std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1157   if (auto A = findEnumAttribute(Attribute::VScaleRange))
1158     return A->getVScaleRangeMax();
1159   return std::nullopt;
1160 }
1161 
getUWTableKind() const1162 UWTableKind AttributeSetNode::getUWTableKind() const {
1163   if (auto A = findEnumAttribute(Attribute::UWTable))
1164     return A->getUWTableKind();
1165   return UWTableKind::None;
1166 }
1167 
getAllocKind() const1168 AllocFnKind AttributeSetNode::getAllocKind() const {
1169   if (auto A = findEnumAttribute(Attribute::AllocKind))
1170     return A->getAllocKind();
1171   return AllocFnKind::Unknown;
1172 }
1173 
getMemoryEffects() const1174 MemoryEffects AttributeSetNode::getMemoryEffects() const {
1175   if (auto A = findEnumAttribute(Attribute::Memory))
1176     return A->getMemoryEffects();
1177   return MemoryEffects::unknown();
1178 }
1179 
getNoFPClass() const1180 FPClassTest AttributeSetNode::getNoFPClass() const {
1181   if (auto A = findEnumAttribute(Attribute::NoFPClass))
1182     return A->getNoFPClass();
1183   return fcNone;
1184 }
1185 
getAsString(bool InAttrGrp) const1186 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1187   std::string Str;
1188   for (iterator I = begin(), E = end(); I != E; ++I) {
1189     if (I != begin())
1190       Str += ' ';
1191     Str += I->getAsString(InAttrGrp);
1192   }
1193   return Str;
1194 }
1195 
1196 //===----------------------------------------------------------------------===//
1197 // AttributeListImpl Definition
1198 //===----------------------------------------------------------------------===//
1199 
1200 /// Map from AttributeList index to the internal array index. Adding one happens
1201 /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)1202 static unsigned attrIdxToArrayIdx(unsigned Index) {
1203   return Index + 1;
1204 }
1205 
AttributeListImpl(ArrayRef<AttributeSet> Sets)1206 AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
1207     : NumAttrSets(Sets.size()) {
1208   assert(!Sets.empty() && "pointless AttributeListImpl");
1209 
1210   // There's memory after the node where we can store the entries in.
1211   llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1212 
1213   // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1214   // summary bitsets.
1215   for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1216     if (!I.isStringAttribute())
1217       AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1218 
1219   for (const auto &Set : Sets)
1220     for (const auto &I : Set)
1221       if (!I.isStringAttribute())
1222         AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1223 }
1224 
Profile(FoldingSetNodeID & ID) const1225 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
1226   Profile(ID, ArrayRef(begin(), end()));
1227 }
1228 
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)1229 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
1230                                 ArrayRef<AttributeSet> Sets) {
1231   for (const auto &Set : Sets)
1232     ID.AddPointer(Set.SetNode);
1233 }
1234 
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const1235 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
1236                                         unsigned *Index) const {
1237   if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1238     return false;
1239 
1240   if (Index) {
1241     for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1242       if (begin()[I].hasAttribute(Kind)) {
1243         *Index = I - 1;
1244         break;
1245       }
1246     }
1247   }
1248 
1249   return true;
1250 }
1251 
1252 
1253 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1254 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1255   AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1256 }
1257 #endif
1258 
1259 //===----------------------------------------------------------------------===//
1260 // AttributeList Construction and Mutation Methods
1261 //===----------------------------------------------------------------------===//
1262 
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)1263 AttributeList AttributeList::getImpl(LLVMContext &C,
1264                                      ArrayRef<AttributeSet> AttrSets) {
1265   assert(!AttrSets.empty() && "pointless AttributeListImpl");
1266 
1267   LLVMContextImpl *pImpl = C.pImpl;
1268   FoldingSetNodeID ID;
1269   AttributeListImpl::Profile(ID, AttrSets);
1270 
1271   void *InsertPoint;
1272   AttributeListImpl *PA =
1273       pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1274 
1275   // If we didn't find any existing attributes of the same shape then
1276   // create a new one and insert it.
1277   if (!PA) {
1278     // Coallocate entries after the AttributeListImpl itself.
1279     void *Mem = pImpl->Alloc.Allocate(
1280         AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1281         alignof(AttributeListImpl));
1282     PA = new (Mem) AttributeListImpl(AttrSets);
1283     pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1284   }
1285 
1286   // Return the AttributesList that we found or created.
1287   return AttributeList(PA);
1288 }
1289 
1290 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)1291 AttributeList::get(LLVMContext &C,
1292                    ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1293   // If there are no attributes then return a null AttributesList pointer.
1294   if (Attrs.empty())
1295     return {};
1296 
1297   assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1298          "Misordered Attributes list!");
1299   assert(llvm::all_of(Attrs,
1300                       [](const std::pair<unsigned, Attribute> &Pair) {
1301                         return Pair.second.isValid();
1302                       }) &&
1303          "Pointless attribute!");
1304 
1305   // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1306   // list.
1307   SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1308   for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1309          E = Attrs.end(); I != E; ) {
1310     unsigned Index = I->first;
1311     SmallVector<Attribute, 4> AttrVec;
1312     while (I != E && I->first == Index) {
1313       AttrVec.push_back(I->second);
1314       ++I;
1315     }
1316 
1317     AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1318   }
1319 
1320   return get(C, AttrPairVec);
1321 }
1322 
1323 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1324 AttributeList::get(LLVMContext &C,
1325                    ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1326   // If there are no attributes then return a null AttributesList pointer.
1327   if (Attrs.empty())
1328     return {};
1329 
1330   assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1331          "Misordered Attributes list!");
1332   assert(llvm::none_of(Attrs,
1333                        [](const std::pair<unsigned, AttributeSet> &Pair) {
1334                          return !Pair.second.hasAttributes();
1335                        }) &&
1336          "Pointless attribute!");
1337 
1338   unsigned MaxIndex = Attrs.back().first;
1339   // If the MaxIndex is FunctionIndex and there are other indices in front
1340   // of it, we need to use the largest of those to get the right size.
1341   if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1342     MaxIndex = Attrs[Attrs.size() - 2].first;
1343 
1344   SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1345   for (const auto &Pair : Attrs)
1346     AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1347 
1348   return getImpl(C, AttrVec);
1349 }
1350 
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)1351 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1352                                  AttributeSet RetAttrs,
1353                                  ArrayRef<AttributeSet> ArgAttrs) {
1354   // Scan from the end to find the last argument with attributes.  Most
1355   // arguments don't have attributes, so it's nice if we can have fewer unique
1356   // AttributeListImpls by dropping empty attribute sets at the end of the list.
1357   unsigned NumSets = 0;
1358   for (size_t I = ArgAttrs.size(); I != 0; --I) {
1359     if (ArgAttrs[I - 1].hasAttributes()) {
1360       NumSets = I + 2;
1361       break;
1362     }
1363   }
1364   if (NumSets == 0) {
1365     // Check function and return attributes if we didn't have argument
1366     // attributes.
1367     if (RetAttrs.hasAttributes())
1368       NumSets = 2;
1369     else if (FnAttrs.hasAttributes())
1370       NumSets = 1;
1371   }
1372 
1373   // If all attribute sets were empty, we can use the empty attribute list.
1374   if (NumSets == 0)
1375     return {};
1376 
1377   SmallVector<AttributeSet, 8> AttrSets;
1378   AttrSets.reserve(NumSets);
1379   // If we have any attributes, we always have function attributes.
1380   AttrSets.push_back(FnAttrs);
1381   if (NumSets > 1)
1382     AttrSets.push_back(RetAttrs);
1383   if (NumSets > 2) {
1384     // Drop the empty argument attribute sets at the end.
1385     ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1386     llvm::append_range(AttrSets, ArgAttrs);
1387   }
1388 
1389   return getImpl(C, AttrSets);
1390 }
1391 
get(LLVMContext & C,unsigned Index,AttributeSet Attrs)1392 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1393                                  AttributeSet Attrs) {
1394   if (!Attrs.hasAttributes())
1395     return {};
1396   Index = attrIdxToArrayIdx(Index);
1397   SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1398   AttrSets[Index] = Attrs;
1399   return getImpl(C, AttrSets);
1400 }
1401 
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1402 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1403                                  const AttrBuilder &B) {
1404   return get(C, Index, AttributeSet::get(C, B));
1405 }
1406 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1407 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1408                                  ArrayRef<Attribute::AttrKind> Kinds) {
1409   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1410   for (const auto K : Kinds)
1411     Attrs.emplace_back(Index, Attribute::get(C, K));
1412   return get(C, Attrs);
1413 }
1414 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)1415 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1416                                  ArrayRef<Attribute::AttrKind> Kinds,
1417                                  ArrayRef<uint64_t> Values) {
1418   assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1419   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1420   auto VI = Values.begin();
1421   for (const auto K : Kinds)
1422     Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1423   return get(C, Attrs);
1424 }
1425 
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1426 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1427                                  ArrayRef<StringRef> Kinds) {
1428   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1429   for (const auto &K : Kinds)
1430     Attrs.emplace_back(Index, Attribute::get(C, K));
1431   return get(C, Attrs);
1432 }
1433 
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1434 AttributeList AttributeList::get(LLVMContext &C,
1435                                  ArrayRef<AttributeList> Attrs) {
1436   if (Attrs.empty())
1437     return {};
1438   if (Attrs.size() == 1)
1439     return Attrs[0];
1440 
1441   unsigned MaxSize = 0;
1442   for (const auto &List : Attrs)
1443     MaxSize = std::max(MaxSize, List.getNumAttrSets());
1444 
1445   // If every list was empty, there is no point in merging the lists.
1446   if (MaxSize == 0)
1447     return {};
1448 
1449   SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1450   for (unsigned I = 0; I < MaxSize; ++I) {
1451     AttrBuilder CurBuilder(C);
1452     for (const auto &List : Attrs)
1453       CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1454     NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1455   }
1456 
1457   return getImpl(C, NewAttrSets);
1458 }
1459 
1460 AttributeList
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1461 AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1462                                    Attribute::AttrKind Kind) const {
1463   AttributeSet Attrs = getAttributes(Index);
1464   if (Attrs.hasAttribute(Kind))
1465     return *this;
1466   // TODO: Insert at correct position and avoid sort.
1467   SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1468   NewAttrs.push_back(Attribute::get(C, Kind));
1469   return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1470 }
1471 
addAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1472 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1473                                                  StringRef Kind,
1474                                                  StringRef Value) const {
1475   AttrBuilder B(C);
1476   B.addAttribute(Kind, Value);
1477   return addAttributesAtIndex(C, Index, B);
1478 }
1479 
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute A) const1480 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1481                                                  Attribute A) const {
1482   AttrBuilder B(C);
1483   B.addAttribute(A);
1484   return addAttributesAtIndex(C, Index, B);
1485 }
1486 
setAttributesAtIndex(LLVMContext & C,unsigned Index,AttributeSet Attrs) const1487 AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1488                                                   unsigned Index,
1489                                                   AttributeSet Attrs) const {
1490   Index = attrIdxToArrayIdx(Index);
1491   SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1492   if (Index >= AttrSets.size())
1493     AttrSets.resize(Index + 1);
1494   AttrSets[Index] = Attrs;
1495 
1496   // Remove trailing empty attribute sets.
1497   while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1498     AttrSets.pop_back();
1499   if (AttrSets.empty())
1500     return {};
1501   return AttributeList::getImpl(C, AttrSets);
1502 }
1503 
addAttributesAtIndex(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1504 AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1505                                                   unsigned Index,
1506                                                   const AttrBuilder &B) const {
1507   if (!B.hasAttributes())
1508     return *this;
1509 
1510   if (!pImpl)
1511     return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1512 
1513   AttrBuilder Merged(C, getAttributes(Index));
1514   Merged.merge(B);
1515   return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1516 }
1517 
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const1518 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1519                                                ArrayRef<unsigned> ArgNos,
1520                                                Attribute A) const {
1521   assert(llvm::is_sorted(ArgNos));
1522 
1523   SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1524   unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1525   if (MaxIndex >= AttrSets.size())
1526     AttrSets.resize(MaxIndex + 1);
1527 
1528   for (unsigned ArgNo : ArgNos) {
1529     unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1530     AttrBuilder B(C, AttrSets[Index]);
1531     B.addAttribute(A);
1532     AttrSets[Index] = AttributeSet::get(C, B);
1533   }
1534 
1535   return getImpl(C, AttrSets);
1536 }
1537 
1538 AttributeList
removeAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1539 AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1540                                       Attribute::AttrKind Kind) const {
1541   AttributeSet Attrs = getAttributes(Index);
1542   AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1543   if (Attrs == NewAttrs)
1544     return *this;
1545   return setAttributesAtIndex(C, Index, NewAttrs);
1546 }
1547 
removeAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind) const1548 AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1549                                                     unsigned Index,
1550                                                     StringRef Kind) const {
1551   AttributeSet Attrs = getAttributes(Index);
1552   AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1553   if (Attrs == NewAttrs)
1554     return *this;
1555   return setAttributesAtIndex(C, Index, NewAttrs);
1556 }
1557 
removeAttributesAtIndex(LLVMContext & C,unsigned Index,const AttributeMask & AttrsToRemove) const1558 AttributeList AttributeList::removeAttributesAtIndex(
1559     LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1560   AttributeSet Attrs = getAttributes(Index);
1561   AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1562   // If nothing was removed, return the original list.
1563   if (Attrs == NewAttrs)
1564     return *this;
1565   return setAttributesAtIndex(C, Index, NewAttrs);
1566 }
1567 
1568 AttributeList
removeAttributesAtIndex(LLVMContext & C,unsigned WithoutIndex) const1569 AttributeList::removeAttributesAtIndex(LLVMContext &C,
1570                                        unsigned WithoutIndex) const {
1571   if (!pImpl)
1572     return {};
1573   if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1574     return *this;
1575   return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1576 }
1577 
addDereferenceableRetAttr(LLVMContext & C,uint64_t Bytes) const1578 AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1579                                                        uint64_t Bytes) const {
1580   AttrBuilder B(C);
1581   B.addDereferenceableAttr(Bytes);
1582   return addRetAttributes(C, B);
1583 }
1584 
addDereferenceableParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1585 AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1586                                                          unsigned Index,
1587                                                          uint64_t Bytes) const {
1588   AttrBuilder B(C);
1589   B.addDereferenceableAttr(Bytes);
1590   return addParamAttributes(C, Index, B);
1591 }
1592 
1593 AttributeList
addDereferenceableOrNullParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1594 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1595                                                  uint64_t Bytes) const {
1596   AttrBuilder B(C);
1597   B.addDereferenceableOrNullAttr(Bytes);
1598   return addParamAttributes(C, Index, B);
1599 }
1600 
addRangeRetAttr(LLVMContext & C,const ConstantRange & CR) const1601 AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
1602                                              const ConstantRange &CR) const {
1603   AttrBuilder B(C);
1604   B.addRangeAttr(CR);
1605   return addRetAttributes(C, B);
1606 }
1607 
addAllocSizeParamAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)1608 AttributeList AttributeList::addAllocSizeParamAttr(
1609     LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1610     const std::optional<unsigned> &NumElemsArg) {
1611   AttrBuilder B(C);
1612   B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1613   return addParamAttributes(C, Index, B);
1614 }
1615 
1616 //===----------------------------------------------------------------------===//
1617 // AttributeList Accessor Methods
1618 //===----------------------------------------------------------------------===//
1619 
getParamAttrs(unsigned ArgNo) const1620 AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1621   return getAttributes(ArgNo + FirstArgIndex);
1622 }
1623 
getRetAttrs() const1624 AttributeSet AttributeList::getRetAttrs() const {
1625   return getAttributes(ReturnIndex);
1626 }
1627 
getFnAttrs() const1628 AttributeSet AttributeList::getFnAttrs() const {
1629   return getAttributes(FunctionIndex);
1630 }
1631 
hasAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1632 bool AttributeList::hasAttributeAtIndex(unsigned Index,
1633                                         Attribute::AttrKind Kind) const {
1634   return getAttributes(Index).hasAttribute(Kind);
1635 }
1636 
hasAttributeAtIndex(unsigned Index,StringRef Kind) const1637 bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1638   return getAttributes(Index).hasAttribute(Kind);
1639 }
1640 
hasAttributesAtIndex(unsigned Index) const1641 bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1642   return getAttributes(Index).hasAttributes();
1643 }
1644 
hasFnAttr(Attribute::AttrKind Kind) const1645 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1646   return pImpl && pImpl->hasFnAttribute(Kind);
1647 }
1648 
hasFnAttr(StringRef Kind) const1649 bool AttributeList::hasFnAttr(StringRef Kind) const {
1650   return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1651 }
1652 
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1653 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1654                                      unsigned *Index) const {
1655   return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1656 }
1657 
getAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1658 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1659                                              Attribute::AttrKind Kind) const {
1660   return getAttributes(Index).getAttribute(Kind);
1661 }
1662 
getAttributeAtIndex(unsigned Index,StringRef Kind) const1663 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1664                                              StringRef Kind) const {
1665   return getAttributes(Index).getAttribute(Kind);
1666 }
1667 
getRetAlignment() const1668 MaybeAlign AttributeList::getRetAlignment() const {
1669   return getAttributes(ReturnIndex).getAlignment();
1670 }
1671 
getParamAlignment(unsigned ArgNo) const1672 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1673   return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1674 }
1675 
getParamStackAlignment(unsigned ArgNo) const1676 MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1677   return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1678 }
1679 
getParamByValType(unsigned Index) const1680 Type *AttributeList::getParamByValType(unsigned Index) const {
1681   return getAttributes(Index+FirstArgIndex).getByValType();
1682 }
1683 
getParamStructRetType(unsigned Index) const1684 Type *AttributeList::getParamStructRetType(unsigned Index) const {
1685   return getAttributes(Index + FirstArgIndex).getStructRetType();
1686 }
1687 
getParamByRefType(unsigned Index) const1688 Type *AttributeList::getParamByRefType(unsigned Index) const {
1689   return getAttributes(Index + FirstArgIndex).getByRefType();
1690 }
1691 
getParamPreallocatedType(unsigned Index) const1692 Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1693   return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1694 }
1695 
getParamInAllocaType(unsigned Index) const1696 Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1697   return getAttributes(Index + FirstArgIndex).getInAllocaType();
1698 }
1699 
getParamElementType(unsigned Index) const1700 Type *AttributeList::getParamElementType(unsigned Index) const {
1701   return getAttributes(Index + FirstArgIndex).getElementType();
1702 }
1703 
getFnStackAlignment() const1704 MaybeAlign AttributeList::getFnStackAlignment() const {
1705   return getFnAttrs().getStackAlignment();
1706 }
1707 
getRetStackAlignment() const1708 MaybeAlign AttributeList::getRetStackAlignment() const {
1709   return getRetAttrs().getStackAlignment();
1710 }
1711 
getRetDereferenceableBytes() const1712 uint64_t AttributeList::getRetDereferenceableBytes() const {
1713   return getRetAttrs().getDereferenceableBytes();
1714 }
1715 
getParamDereferenceableBytes(unsigned Index) const1716 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1717   return getParamAttrs(Index).getDereferenceableBytes();
1718 }
1719 
getRetDereferenceableOrNullBytes() const1720 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1721   return getRetAttrs().getDereferenceableOrNullBytes();
1722 }
1723 
1724 uint64_t
getParamDereferenceableOrNullBytes(unsigned Index) const1725 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1726   return getParamAttrs(Index).getDereferenceableOrNullBytes();
1727 }
1728 
getRetNoFPClass() const1729 FPClassTest AttributeList::getRetNoFPClass() const {
1730   return getRetAttrs().getNoFPClass();
1731 }
1732 
getParamNoFPClass(unsigned Index) const1733 FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {
1734   return getParamAttrs(Index).getNoFPClass();
1735 }
1736 
getUWTableKind() const1737 UWTableKind AttributeList::getUWTableKind() const {
1738   return getFnAttrs().getUWTableKind();
1739 }
1740 
getAllocKind() const1741 AllocFnKind AttributeList::getAllocKind() const {
1742   return getFnAttrs().getAllocKind();
1743 }
1744 
getMemoryEffects() const1745 MemoryEffects AttributeList::getMemoryEffects() const {
1746   return getFnAttrs().getMemoryEffects();
1747 }
1748 
getAsString(unsigned Index,bool InAttrGrp) const1749 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1750   return getAttributes(Index).getAsString(InAttrGrp);
1751 }
1752 
getAttributes(unsigned Index) const1753 AttributeSet AttributeList::getAttributes(unsigned Index) const {
1754   Index = attrIdxToArrayIdx(Index);
1755   if (!pImpl || Index >= getNumAttrSets())
1756     return {};
1757   return pImpl->begin()[Index];
1758 }
1759 
hasParentContext(LLVMContext & C) const1760 bool AttributeList::hasParentContext(LLVMContext &C) const {
1761   assert(!isEmpty() && "an empty attribute list has no parent context");
1762   FoldingSetNodeID ID;
1763   pImpl->Profile(ID);
1764   void *Unused;
1765   return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1766 }
1767 
begin() const1768 AttributeList::iterator AttributeList::begin() const {
1769   return pImpl ? pImpl->begin() : nullptr;
1770 }
1771 
end() const1772 AttributeList::iterator AttributeList::end() const {
1773   return pImpl ? pImpl->end() : nullptr;
1774 }
1775 
1776 //===----------------------------------------------------------------------===//
1777 // AttributeList Introspection Methods
1778 //===----------------------------------------------------------------------===//
1779 
getNumAttrSets() const1780 unsigned AttributeList::getNumAttrSets() const {
1781   return pImpl ? pImpl->NumAttrSets : 0;
1782 }
1783 
print(raw_ostream & O) const1784 void AttributeList::print(raw_ostream &O) const {
1785   O << "AttributeList[\n";
1786 
1787   for (unsigned i : indexes()) {
1788     if (!getAttributes(i).hasAttributes())
1789       continue;
1790     O << "  { ";
1791     switch (i) {
1792     case AttrIndex::ReturnIndex:
1793       O << "return";
1794       break;
1795     case AttrIndex::FunctionIndex:
1796       O << "function";
1797       break;
1798     default:
1799       O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1800     }
1801     O << " => " << getAsString(i) << " }\n";
1802   }
1803 
1804   O << "]\n";
1805 }
1806 
1807 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1808 LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
1809 #endif
1810 
1811 //===----------------------------------------------------------------------===//
1812 // AttrBuilder Method Implementations
1813 //===----------------------------------------------------------------------===//
1814 
AttrBuilder(LLVMContext & Ctx,AttributeSet AS)1815 AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
1816   append_range(Attrs, AS);
1817   assert(is_sorted(Attrs) && "AttributeSet should be sorted");
1818 }
1819 
clear()1820 void AttrBuilder::clear() { Attrs.clear(); }
1821 
1822 /// Attribute comparator that only compares attribute keys. Enum attributes are
1823 /// sorted before string attributes.
1824 struct AttributeComparator {
operator ()AttributeComparator1825   bool operator()(Attribute A0, Attribute A1) const {
1826     bool A0IsString = A0.isStringAttribute();
1827     bool A1IsString = A1.isStringAttribute();
1828     if (A0IsString) {
1829       if (A1IsString)
1830         return A0.getKindAsString() < A1.getKindAsString();
1831       else
1832         return false;
1833     }
1834     if (A1IsString)
1835       return true;
1836     return A0.getKindAsEnum() < A1.getKindAsEnum();
1837   }
operator ()AttributeComparator1838   bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
1839     if (A0.isStringAttribute())
1840       return false;
1841     return A0.getKindAsEnum() < Kind;
1842   }
operator ()AttributeComparator1843   bool operator()(Attribute A0, StringRef Kind) const {
1844     if (A0.isStringAttribute())
1845       return A0.getKindAsString() < Kind;
1846     return true;
1847   }
1848 };
1849 
1850 template <typename K>
addAttributeImpl(SmallVectorImpl<Attribute> & Attrs,K Kind,Attribute Attr)1851 static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
1852                              Attribute Attr) {
1853   auto It = lower_bound(Attrs, Kind, AttributeComparator());
1854   if (It != Attrs.end() && It->hasAttribute(Kind))
1855     std::swap(*It, Attr);
1856   else
1857     Attrs.insert(It, Attr);
1858 }
1859 
addAttribute(Attribute Attr)1860 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1861   if (Attr.isStringAttribute())
1862     addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1863   else
1864     addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
1865   return *this;
1866 }
1867 
addAttribute(Attribute::AttrKind Kind)1868 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
1869   addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
1870   return *this;
1871 }
1872 
addAttribute(StringRef A,StringRef V)1873 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1874   addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
1875   return *this;
1876 }
1877 
removeAttribute(Attribute::AttrKind Val)1878 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1879   assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1880   auto It = lower_bound(Attrs, Val, AttributeComparator());
1881   if (It != Attrs.end() && It->hasAttribute(Val))
1882     Attrs.erase(It);
1883   return *this;
1884 }
1885 
removeAttribute(StringRef A)1886 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1887   auto It = lower_bound(Attrs, A, AttributeComparator());
1888   if (It != Attrs.end() && It->hasAttribute(A))
1889     Attrs.erase(It);
1890   return *this;
1891 }
1892 
1893 std::optional<uint64_t>
getRawIntAttr(Attribute::AttrKind Kind) const1894 AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
1895   assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
1896   Attribute A = getAttribute(Kind);
1897   if (A.isValid())
1898     return A.getValueAsInt();
1899   return std::nullopt;
1900 }
1901 
addRawIntAttr(Attribute::AttrKind Kind,uint64_t Value)1902 AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
1903                                         uint64_t Value) {
1904   return addAttribute(Attribute::get(Ctx, Kind, Value));
1905 }
1906 
1907 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1908 AttrBuilder::getAllocSizeArgs() const {
1909   Attribute A = getAttribute(Attribute::AllocSize);
1910   if (A.isValid())
1911     return A.getAllocSizeArgs();
1912   return std::nullopt;
1913 }
1914 
addAlignmentAttr(MaybeAlign Align)1915 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1916   if (!Align)
1917     return *this;
1918 
1919   assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1920   return addRawIntAttr(Attribute::Alignment, Align->value());
1921 }
1922 
addStackAlignmentAttr(MaybeAlign Align)1923 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1924   // Default alignment, allow the target to define how to align it.
1925   if (!Align)
1926     return *this;
1927 
1928   assert(*Align <= 0x100 && "Alignment too large.");
1929   return addRawIntAttr(Attribute::StackAlignment, Align->value());
1930 }
1931 
addDereferenceableAttr(uint64_t Bytes)1932 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1933   if (Bytes == 0) return *this;
1934 
1935   return addRawIntAttr(Attribute::Dereferenceable, Bytes);
1936 }
1937 
addDereferenceableOrNullAttr(uint64_t Bytes)1938 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1939   if (Bytes == 0)
1940     return *this;
1941 
1942   return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
1943 }
1944 
1945 AttrBuilder &
addAllocSizeAttr(unsigned ElemSize,const std::optional<unsigned> & NumElems)1946 AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1947                               const std::optional<unsigned> &NumElems) {
1948   return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1949 }
1950 
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1951 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1952   // (0, 0) is our "not present" value, so we need to check for it here.
1953   assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1954   return addRawIntAttr(Attribute::AllocSize, RawArgs);
1955 }
1956 
addVScaleRangeAttr(unsigned MinValue,std::optional<unsigned> MaxValue)1957 AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
1958                                              std::optional<unsigned> MaxValue) {
1959   return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
1960 }
1961 
addVScaleRangeAttrFromRawRepr(uint64_t RawArgs)1962 AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
1963   // (0, 0) is not present hence ignore this case
1964   if (RawArgs == 0)
1965     return *this;
1966 
1967   return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1968 }
1969 
addUWTableAttr(UWTableKind Kind)1970 AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
1971   if (Kind == UWTableKind::None)
1972     return *this;
1973   return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
1974 }
1975 
addMemoryAttr(MemoryEffects ME)1976 AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
1977   return addRawIntAttr(Attribute::Memory, ME.toIntValue());
1978 }
1979 
addNoFPClassAttr(FPClassTest Mask)1980 AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
1981   if (Mask == fcNone)
1982     return *this;
1983 
1984   return addRawIntAttr(Attribute::NoFPClass, Mask);
1985 }
1986 
addAllocKindAttr(AllocFnKind Kind)1987 AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
1988   return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
1989 }
1990 
getTypeAttr(Attribute::AttrKind Kind) const1991 Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
1992   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
1993   Attribute A = getAttribute(Kind);
1994   return A.isValid() ? A.getValueAsType() : nullptr;
1995 }
1996 
addTypeAttr(Attribute::AttrKind Kind,Type * Ty)1997 AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
1998   return addAttribute(Attribute::get(Ctx, Kind, Ty));
1999 }
2000 
addByValAttr(Type * Ty)2001 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
2002   return addTypeAttr(Attribute::ByVal, Ty);
2003 }
2004 
addStructRetAttr(Type * Ty)2005 AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
2006   return addTypeAttr(Attribute::StructRet, Ty);
2007 }
2008 
addByRefAttr(Type * Ty)2009 AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
2010   return addTypeAttr(Attribute::ByRef, Ty);
2011 }
2012 
addPreallocatedAttr(Type * Ty)2013 AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
2014   return addTypeAttr(Attribute::Preallocated, Ty);
2015 }
2016 
addInAllocaAttr(Type * Ty)2017 AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
2018   return addTypeAttr(Attribute::InAlloca, Ty);
2019 }
2020 
addConstantRangeAttr(Attribute::AttrKind Kind,const ConstantRange & CR)2021 AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,
2022                                                const ConstantRange &CR) {
2023   return addAttribute(Attribute::get(Ctx, Kind, CR));
2024 }
2025 
addRangeAttr(const ConstantRange & CR)2026 AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
2027   return addConstantRangeAttr(Attribute::Range, CR);
2028 }
2029 
2030 AttrBuilder &
addConstantRangeListAttr(Attribute::AttrKind Kind,ArrayRef<ConstantRange> Val)2031 AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
2032                                       ArrayRef<ConstantRange> Val) {
2033   return addAttribute(Attribute::get(Ctx, Kind, Val));
2034 }
2035 
addInitializesAttr(const ConstantRangeList & CRL)2036 AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
2037   return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2038 }
2039 
merge(const AttrBuilder & B)2040 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
2041   // TODO: Could make this O(n) as we're merging two sorted lists.
2042   for (const auto &I : B.attrs())
2043     addAttribute(I);
2044 
2045   return *this;
2046 }
2047 
remove(const AttributeMask & AM)2048 AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
2049   erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2050   return *this;
2051 }
2052 
overlaps(const AttributeMask & AM) const2053 bool AttrBuilder::overlaps(const AttributeMask &AM) const {
2054   return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2055 }
2056 
getAttribute(Attribute::AttrKind A) const2057 Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
2058   assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2059   auto It = lower_bound(Attrs, A, AttributeComparator());
2060   if (It != Attrs.end() && It->hasAttribute(A))
2061     return *It;
2062   return {};
2063 }
2064 
getAttribute(StringRef A) const2065 Attribute AttrBuilder::getAttribute(StringRef A) const {
2066   auto It = lower_bound(Attrs, A, AttributeComparator());
2067   if (It != Attrs.end() && It->hasAttribute(A))
2068     return *It;
2069   return {};
2070 }
2071 
contains(Attribute::AttrKind A) const2072 bool AttrBuilder::contains(Attribute::AttrKind A) const {
2073   return getAttribute(A).isValid();
2074 }
2075 
contains(StringRef A) const2076 bool AttrBuilder::contains(StringRef A) const {
2077   return getAttribute(A).isValid();
2078 }
2079 
operator ==(const AttrBuilder & B) const2080 bool AttrBuilder::operator==(const AttrBuilder &B) const {
2081   return Attrs == B.Attrs;
2082 }
2083 
2084 //===----------------------------------------------------------------------===//
2085 // AttributeFuncs Function Defintions
2086 //===----------------------------------------------------------------------===//
2087 
2088 /// Returns true if this is a type legal for the 'nofpclass' attribute. This
2089 /// follows the same type rules as FPMathOperator.
2090 ///
2091 /// TODO: Consider relaxing to any FP type struct fields.
isNoFPClassCompatibleType(Type * Ty)2092 bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2093   while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
2094     Ty = ArrTy->getElementType();
2095   return Ty->isFPOrFPVectorTy();
2096 }
2097 
2098 /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty,AttributeSafetyKind ASK)2099 AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
2100                                                AttributeSafetyKind ASK) {
2101   AttributeMask Incompatible;
2102 
2103   if (!Ty->isIntegerTy()) {
2104     // Attributes that only apply to integers.
2105     if (ASK & ASK_SAFE_TO_DROP)
2106       Incompatible.addAttribute(Attribute::AllocAlign);
2107     if (ASK & ASK_UNSAFE_TO_DROP)
2108       Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2109   }
2110 
2111   if (!Ty->isIntOrIntVectorTy()) {
2112     // Attributes that only apply to integers or vector of integers.
2113     if (ASK & ASK_SAFE_TO_DROP)
2114       Incompatible.addAttribute(Attribute::Range);
2115   }
2116 
2117   if (!Ty->isPointerTy()) {
2118     // Attributes that only apply to pointers.
2119     if (ASK & ASK_SAFE_TO_DROP)
2120       Incompatible.addAttribute(Attribute::NoAlias)
2121           .addAttribute(Attribute::NoCapture)
2122           .addAttribute(Attribute::NonNull)
2123           .addAttribute(Attribute::ReadNone)
2124           .addAttribute(Attribute::ReadOnly)
2125           .addAttribute(Attribute::Dereferenceable)
2126           .addAttribute(Attribute::DereferenceableOrNull)
2127           .addAttribute(Attribute::Writable)
2128           .addAttribute(Attribute::DeadOnUnwind)
2129           .addAttribute(Attribute::Initializes);
2130     if (ASK & ASK_UNSAFE_TO_DROP)
2131       Incompatible.addAttribute(Attribute::Nest)
2132           .addAttribute(Attribute::SwiftError)
2133           .addAttribute(Attribute::Preallocated)
2134           .addAttribute(Attribute::InAlloca)
2135           .addAttribute(Attribute::ByVal)
2136           .addAttribute(Attribute::StructRet)
2137           .addAttribute(Attribute::ByRef)
2138           .addAttribute(Attribute::ElementType)
2139           .addAttribute(Attribute::AllocatedPointer);
2140   }
2141 
2142     // Attributes that only apply to pointers or vectors of pointers.
2143   if (!Ty->isPtrOrPtrVectorTy()) {
2144     if (ASK & ASK_SAFE_TO_DROP)
2145       Incompatible.addAttribute(Attribute::Alignment);
2146   }
2147 
2148   if (ASK & ASK_SAFE_TO_DROP) {
2149     if (!isNoFPClassCompatibleType(Ty))
2150       Incompatible.addAttribute(Attribute::NoFPClass);
2151   }
2152 
2153   // Some attributes can apply to all "values" but there are no `void` values.
2154   if (Ty->isVoidTy()) {
2155     if (ASK & ASK_SAFE_TO_DROP)
2156       Incompatible.addAttribute(Attribute::NoUndef);
2157   }
2158 
2159   return Incompatible;
2160 }
2161 
getUBImplyingAttributes()2162 AttributeMask AttributeFuncs::getUBImplyingAttributes() {
2163   AttributeMask AM;
2164   AM.addAttribute(Attribute::NoUndef);
2165   AM.addAttribute(Attribute::Dereferenceable);
2166   AM.addAttribute(Attribute::DereferenceableOrNull);
2167   return AM;
2168 }
2169 
2170 /// Callees with dynamic denormal modes are compatible with any caller mode.
denormModeCompatible(DenormalMode CallerMode,DenormalMode CalleeMode)2171 static bool denormModeCompatible(DenormalMode CallerMode,
2172                                  DenormalMode CalleeMode) {
2173   if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2174     return true;
2175 
2176   // If they don't exactly match, it's OK if the mismatched component is
2177   // dynamic.
2178   if (CalleeMode.Input == CallerMode.Input &&
2179       CalleeMode.Output == DenormalMode::Dynamic)
2180     return true;
2181 
2182   if (CalleeMode.Output == CallerMode.Output &&
2183       CalleeMode.Input == DenormalMode::Dynamic)
2184     return true;
2185   return false;
2186 }
2187 
checkDenormMode(const Function & Caller,const Function & Callee)2188 static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2189   DenormalMode CallerMode = Caller.getDenormalModeRaw();
2190   DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2191 
2192   if (denormModeCompatible(CallerMode, CalleeMode)) {
2193     DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2194     DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2195     if (CallerModeF32 == DenormalMode::getInvalid())
2196       CallerModeF32 = CallerMode;
2197     if (CalleeModeF32 == DenormalMode::getInvalid())
2198       CalleeModeF32 = CalleeMode;
2199     return denormModeCompatible(CallerModeF32, CalleeModeF32);
2200   }
2201 
2202   return false;
2203 }
2204 
checkStrictFP(const Function & Caller,const Function & Callee)2205 static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2206   // Do not inline strictfp function into non-strictfp one. It would require
2207   // conversion of all FP operations in host function to constrained intrinsics.
2208   return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2209          Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2210 }
2211 
2212 template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)2213 static bool isEqual(const Function &Caller, const Function &Callee) {
2214   return Caller.getFnAttribute(AttrClass::getKind()) ==
2215          Callee.getFnAttribute(AttrClass::getKind());
2216 }
2217 
isEqual(const Function & Caller,const Function & Callee,const StringRef & AttrName)2218 static bool isEqual(const Function &Caller, const Function &Callee,
2219                     const StringRef &AttrName) {
2220   return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2221 }
2222 
2223 /// Compute the logical AND of the attributes of the caller and the
2224 /// callee.
2225 ///
2226 /// This function sets the caller's attribute to false if the callee's attribute
2227 /// is false.
2228 template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)2229 static void setAND(Function &Caller, const Function &Callee) {
2230   if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2231       !AttrClass::isSet(Callee, AttrClass::getKind()))
2232     AttrClass::set(Caller, AttrClass::getKind(), false);
2233 }
2234 
2235 /// Compute the logical OR of the attributes of the caller and the
2236 /// callee.
2237 ///
2238 /// This function sets the caller's attribute to true if the callee's attribute
2239 /// is true.
2240 template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)2241 static void setOR(Function &Caller, const Function &Callee) {
2242   if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2243       AttrClass::isSet(Callee, AttrClass::getKind()))
2244     AttrClass::set(Caller, AttrClass::getKind(), true);
2245 }
2246 
2247 /// If the inlined function had a higher stack protection level than the
2248 /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)2249 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2250   // If the calling function has *no* stack protection level (e.g. it was built
2251   // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2252   // change it as that could change the program's semantics.
2253   if (!Caller.hasStackProtectorFnAttr())
2254     return;
2255 
2256   // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2257   // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2258   // clutter to the IR.
2259   AttributeMask OldSSPAttr;
2260   OldSSPAttr.addAttribute(Attribute::StackProtect)
2261       .addAttribute(Attribute::StackProtectStrong)
2262       .addAttribute(Attribute::StackProtectReq);
2263 
2264   if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2265     Caller.removeFnAttrs(OldSSPAttr);
2266     Caller.addFnAttr(Attribute::StackProtectReq);
2267   } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2268              !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2269     Caller.removeFnAttrs(OldSSPAttr);
2270     Caller.addFnAttr(Attribute::StackProtectStrong);
2271   } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2272              !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2273              !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2274     Caller.addFnAttr(Attribute::StackProtect);
2275 }
2276 
2277 /// If the inlined function required stack probes, then ensure that
2278 /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)2279 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2280   if (!Caller.hasFnAttribute("probe-stack") &&
2281       Callee.hasFnAttribute("probe-stack")) {
2282     Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2283   }
2284 }
2285 
2286 /// If the inlined function defines the size of guard region
2287 /// on the stack, then ensure that the calling function defines a guard region
2288 /// that is no larger.
2289 static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)2290 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
2291   Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2292   if (CalleeAttr.isValid()) {
2293     Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2294     if (CallerAttr.isValid()) {
2295       uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2296       CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2297       CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2298 
2299       if (CallerStackProbeSize > CalleeStackProbeSize) {
2300         Caller.addFnAttr(CalleeAttr);
2301       }
2302     } else {
2303       Caller.addFnAttr(CalleeAttr);
2304     }
2305   }
2306 }
2307 
2308 /// If the inlined function defines a min legal vector width, then ensure
2309 /// the calling function has the same or larger min legal vector width. If the
2310 /// caller has the attribute, but the callee doesn't, we need to remove the
2311 /// attribute from the caller since we can't make any guarantees about the
2312 /// caller's requirements.
2313 /// This function is called after the inlining decision has been made so we have
2314 /// to merge the attribute this way. Heuristics that would use
2315 /// min-legal-vector-width to determine inline compatibility would need to be
2316 /// handled as part of inline cost analysis.
2317 static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)2318 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
2319   Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2320   if (CallerAttr.isValid()) {
2321     Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2322     if (CalleeAttr.isValid()) {
2323       uint64_t CallerVectorWidth, CalleeVectorWidth;
2324       CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2325       CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2326       if (CallerVectorWidth < CalleeVectorWidth)
2327         Caller.addFnAttr(CalleeAttr);
2328     } else {
2329       // If the callee doesn't have the attribute then we don't know anything
2330       // and must drop the attribute from the caller.
2331       Caller.removeFnAttr("min-legal-vector-width");
2332     }
2333   }
2334 }
2335 
2336 /// If the inlined function has null_pointer_is_valid attribute,
2337 /// set this attribute in the caller post inlining.
2338 static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)2339 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2340   if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2341     Caller.addFnAttr(Attribute::NullPointerIsValid);
2342   }
2343 }
2344 
2345 struct EnumAttr {
isSetEnumAttr2346   static bool isSet(const Function &Fn,
2347                     Attribute::AttrKind Kind) {
2348     return Fn.hasFnAttribute(Kind);
2349   }
2350 
setEnumAttr2351   static void set(Function &Fn,
2352                   Attribute::AttrKind Kind, bool Val) {
2353     if (Val)
2354       Fn.addFnAttr(Kind);
2355     else
2356       Fn.removeFnAttr(Kind);
2357   }
2358 };
2359 
2360 struct StrBoolAttr {
isSetStrBoolAttr2361   static bool isSet(const Function &Fn,
2362                     StringRef Kind) {
2363     auto A = Fn.getFnAttribute(Kind);
2364     return A.getValueAsString() == "true";
2365   }
2366 
setStrBoolAttr2367   static void set(Function &Fn,
2368                   StringRef Kind, bool Val) {
2369     Fn.addFnAttr(Kind, Val ? "true" : "false");
2370   }
2371 };
2372 
2373 #define GET_ATTR_NAMES
2374 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
2375   struct ENUM_NAME##Attr : EnumAttr {                                          \
2376     static enum Attribute::AttrKind getKind() {                                \
2377       return llvm::Attribute::ENUM_NAME;                                       \
2378     }                                                                          \
2379   };
2380 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME)                             \
2381   struct ENUM_NAME##Attr : StrBoolAttr {                                       \
2382     static StringRef getKind() { return #DISPLAY_NAME; }                       \
2383   };
2384 #include "llvm/IR/Attributes.inc"
2385 
2386 #define GET_ATTR_COMPAT_FUNC
2387 #include "llvm/IR/Attributes.inc"
2388 
areInlineCompatible(const Function & Caller,const Function & Callee)2389 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2390                                          const Function &Callee) {
2391   return hasCompatibleFnAttrs(Caller, Callee);
2392 }
2393 
areOutlineCompatible(const Function & A,const Function & B)2394 bool AttributeFuncs::areOutlineCompatible(const Function &A,
2395                                           const Function &B) {
2396   return hasCompatibleFnAttrs(A, B);
2397 }
2398 
mergeAttributesForInlining(Function & Caller,const Function & Callee)2399 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2400                                                 const Function &Callee) {
2401   mergeFnAttrs(Caller, Callee);
2402 }
2403 
mergeAttributesForOutlining(Function & Base,const Function & ToMerge)2404 void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2405                                                 const Function &ToMerge) {
2406 
2407   // We merge functions so that they meet the most general case.
2408   // For example, if the NoNansFPMathAttr is set in one function, but not in
2409   // the other, in the merged function we can say that the NoNansFPMathAttr
2410   // is not set.
2411   // However if we have the SpeculativeLoadHardeningAttr set true in one
2412   // function, but not the other, we make sure that the function retains
2413   // that aspect in the merged function.
2414   mergeFnAttrs(Base, ToMerge);
2415 }
2416 
updateMinLegalVectorWidthAttr(Function & Fn,uint64_t Width)2417 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2418                                                    uint64_t Width) {
2419   Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2420   if (Attr.isValid()) {
2421     uint64_t OldWidth;
2422     Attr.getValueAsString().getAsInteger(0, OldWidth);
2423     if (Width > OldWidth)
2424       Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2425   }
2426 }
2427