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