[lld/COFF] Demangle symbol name in discarded section relocation error message (#119726)
[llvm-project.git] / llvm / lib / IR / Attributes.cpp
blobe9daa01b899e8f3c0cc40ff00f543a5f9a6a03e5
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.
13 //===----------------------------------------------------------------------===//
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>
47 using namespace llvm;
49 //===----------------------------------------------------------------------===//
50 // Attribute Construction Methods
51 //===----------------------------------------------------------------------===//
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.
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;
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");
66 return uint64_t(ElemSizeArg) << 32 |
67 NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
70 static std::pair<unsigned, std::optional<unsigned>>
71 unpackAllocSizeArgs(uint64_t Num) {
72 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
73 unsigned ElemSizeArg = Num >> 32;
75 std::optional<unsigned> NumElemsArg;
76 if (NumElems != AllocSizeNumElemsNotPresent)
77 NumElemsArg = NumElems;
78 return std::make_pair(ElemSizeArg, NumElemsArg);
81 static uint64_t packVScaleRangeArgs(unsigned MinValue,
82 std::optional<unsigned> MaxValue) {
83 return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
86 static std::pair<unsigned, std::optional<unsigned>>
87 unpackVScaleRangeArgs(uint64_t Value) {
88 unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
89 unsigned MinValue = Value >> 32;
91 return std::make_pair(MinValue,
92 MaxValue > 0 ? MaxValue : std::optional<unsigned>());
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");
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");
109 void *InsertPoint;
110 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
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);
122 // Return the Attribute that we found or created.
123 return Attribute(PA);
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);
132 void *InsertPoint;
133 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
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);
145 // Return the Attribute that we found or created.
146 return Attribute(PA);
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);
157 void *InsertPoint;
158 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
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);
167 // Return the Attribute that we found or created.
168 return Attribute(PA);
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);
182 void *InsertPoint;
183 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
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);
193 // Return the Attribute that we found or created.
194 return Attribute(PA);
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);
210 void *InsertPoint;
211 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
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));
230 // Return the Attribute that we found or created.
231 return Attribute(PA);
234 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
235 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
236 return get(Context, Alignment, A.value());
239 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
240 assert(A <= 0x100 && "Alignment too large.");
241 return get(Context, StackAlignment, A.value());
244 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
245 uint64_t Bytes) {
246 assert(Bytes && "Bytes must be non-zero.");
247 return get(Context, Dereferenceable, 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);
256 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
257 return get(Context, ByVal, Ty);
260 Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
261 return get(Context, StructRet, Ty);
264 Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
265 return get(Context, ByRef, Ty);
268 Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
269 return get(Context, Preallocated, Ty);
272 Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
273 return get(Context, InAlloca, Ty);
276 Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
277 UWTableKind Kind) {
278 return get(Context, UWTable, uint64_t(Kind));
281 Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
282 MemoryEffects ME) {
283 return get(Context, Memory, ME.toIntValue());
286 Attribute Attribute::getWithNoFPClass(LLVMContext &Context,
287 FPClassTest ClassMask) {
288 return get(Context, NoFPClass, ClassMask);
291 Attribute
292 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
293 const std::optional<unsigned> &NumElemsArg) {
294 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
295 "Invalid allocsize arguments -- given allocsize(0, 0)");
296 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
299 Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
300 unsigned MinValue,
301 unsigned MaxValue) {
302 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
305 Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
306 return StringSwitch<Attribute::AttrKind>(AttrName)
307 #define GET_ATTR_NAMES
308 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
309 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
310 #include "llvm/IR/Attributes.inc"
311 .Default(Attribute::None);
314 StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
315 switch (AttrKind) {
316 #define GET_ATTR_NAMES
317 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
318 case Attribute::ENUM_NAME: \
319 return #DISPLAY_NAME;
320 #include "llvm/IR/Attributes.inc"
321 case Attribute::None:
322 return "none";
323 default:
324 llvm_unreachable("invalid Kind");
328 bool Attribute::isExistingAttribute(StringRef Name) {
329 return StringSwitch<bool>(Name)
330 #define GET_ATTR_NAMES
331 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
332 #include "llvm/IR/Attributes.inc"
333 .Default(false);
336 //===----------------------------------------------------------------------===//
337 // Attribute Accessor Methods
338 //===----------------------------------------------------------------------===//
340 bool Attribute::isEnumAttribute() const {
341 return pImpl && pImpl->isEnumAttribute();
344 bool Attribute::isIntAttribute() const {
345 return pImpl && pImpl->isIntAttribute();
348 bool Attribute::isStringAttribute() const {
349 return pImpl && pImpl->isStringAttribute();
352 bool Attribute::isTypeAttribute() const {
353 return pImpl && pImpl->isTypeAttribute();
356 bool Attribute::isConstantRangeAttribute() const {
357 return pImpl && pImpl->isConstantRangeAttribute();
360 bool Attribute::isConstantRangeListAttribute() const {
361 return pImpl && pImpl->isConstantRangeListAttribute();
364 Attribute::AttrKind Attribute::getKindAsEnum() const {
365 if (!pImpl) return None;
366 assert(hasKindAsEnum() &&
367 "Invalid attribute type to get the kind as an enum!");
368 return pImpl->getKindAsEnum();
371 uint64_t Attribute::getValueAsInt() const {
372 if (!pImpl) return 0;
373 assert(isIntAttribute() &&
374 "Expected the attribute to be an integer attribute!");
375 return pImpl->getValueAsInt();
378 bool Attribute::getValueAsBool() const {
379 if (!pImpl) return false;
380 assert(isStringAttribute() &&
381 "Expected the attribute to be a string attribute!");
382 return pImpl->getValueAsBool();
385 StringRef Attribute::getKindAsString() const {
386 if (!pImpl) return {};
387 assert(isStringAttribute() &&
388 "Invalid attribute type to get the kind as a string!");
389 return pImpl->getKindAsString();
392 StringRef Attribute::getValueAsString() const {
393 if (!pImpl) return {};
394 assert(isStringAttribute() &&
395 "Invalid attribute type to get the value as a string!");
396 return pImpl->getValueAsString();
399 Type *Attribute::getValueAsType() const {
400 if (!pImpl) return {};
401 assert(isTypeAttribute() &&
402 "Invalid attribute type to get the value as a type!");
403 return pImpl->getValueAsType();
406 const ConstantRange &Attribute::getValueAsConstantRange() const {
407 assert(isConstantRangeAttribute() &&
408 "Invalid attribute type to get the value as a ConstantRange!");
409 return pImpl->getValueAsConstantRange();
412 ArrayRef<ConstantRange> Attribute::getValueAsConstantRangeList() const {
413 assert(isConstantRangeListAttribute() &&
414 "Invalid attribute type to get the value as a ConstantRangeList!");
415 return pImpl->getValueAsConstantRangeList();
418 bool Attribute::hasAttribute(AttrKind Kind) const {
419 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
422 bool Attribute::hasAttribute(StringRef Kind) const {
423 if (!isStringAttribute()) return false;
424 return pImpl && pImpl->hasAttribute(Kind);
427 MaybeAlign Attribute::getAlignment() const {
428 assert(hasAttribute(Attribute::Alignment) &&
429 "Trying to get alignment from non-alignment attribute!");
430 return MaybeAlign(pImpl->getValueAsInt());
433 MaybeAlign Attribute::getStackAlignment() const {
434 assert(hasAttribute(Attribute::StackAlignment) &&
435 "Trying to get alignment from non-alignment attribute!");
436 return MaybeAlign(pImpl->getValueAsInt());
439 uint64_t Attribute::getDereferenceableBytes() const {
440 assert(hasAttribute(Attribute::Dereferenceable) &&
441 "Trying to get dereferenceable bytes from "
442 "non-dereferenceable attribute!");
443 return pImpl->getValueAsInt();
446 uint64_t Attribute::getDereferenceableOrNullBytes() const {
447 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
448 "Trying to get dereferenceable bytes from "
449 "non-dereferenceable attribute!");
450 return pImpl->getValueAsInt();
453 std::pair<unsigned, std::optional<unsigned>>
454 Attribute::getAllocSizeArgs() const {
455 assert(hasAttribute(Attribute::AllocSize) &&
456 "Trying to get allocsize args from non-allocsize attribute");
457 return unpackAllocSizeArgs(pImpl->getValueAsInt());
460 unsigned Attribute::getVScaleRangeMin() const {
461 assert(hasAttribute(Attribute::VScaleRange) &&
462 "Trying to get vscale args from non-vscale attribute");
463 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
466 std::optional<unsigned> Attribute::getVScaleRangeMax() const {
467 assert(hasAttribute(Attribute::VScaleRange) &&
468 "Trying to get vscale args from non-vscale attribute");
469 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
472 UWTableKind Attribute::getUWTableKind() const {
473 assert(hasAttribute(Attribute::UWTable) &&
474 "Trying to get unwind table kind from non-uwtable attribute");
475 return UWTableKind(pImpl->getValueAsInt());
478 AllocFnKind Attribute::getAllocKind() const {
479 assert(hasAttribute(Attribute::AllocKind) &&
480 "Trying to get allockind value from non-allockind attribute");
481 return AllocFnKind(pImpl->getValueAsInt());
484 MemoryEffects Attribute::getMemoryEffects() const {
485 assert(hasAttribute(Attribute::Memory) &&
486 "Can only call getMemoryEffects() on memory attribute");
487 return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
490 FPClassTest Attribute::getNoFPClass() const {
491 assert(hasAttribute(Attribute::NoFPClass) &&
492 "Can only call getNoFPClass() on nofpclass attribute");
493 return static_cast<FPClassTest>(pImpl->getValueAsInt());
496 const ConstantRange &Attribute::getRange() const {
497 assert(hasAttribute(Attribute::Range) &&
498 "Trying to get range args from non-range attribute");
499 return pImpl->getValueAsConstantRange();
502 ArrayRef<ConstantRange> Attribute::getInitializes() const {
503 assert(hasAttribute(Attribute::Initializes) &&
504 "Trying to get initializes attr from non-ConstantRangeList attribute");
505 return pImpl->getValueAsConstantRangeList();
508 static const char *getModRefStr(ModRefInfo MR) {
509 switch (MR) {
510 case ModRefInfo::NoModRef:
511 return "none";
512 case ModRefInfo::Ref:
513 return "read";
514 case ModRefInfo::Mod:
515 return "write";
516 case ModRefInfo::ModRef:
517 return "readwrite";
519 llvm_unreachable("Invalid ModRefInfo");
522 std::string Attribute::getAsString(bool InAttrGrp) const {
523 if (!pImpl) return {};
525 if (isEnumAttribute())
526 return getNameFromAttrKind(getKindAsEnum()).str();
528 if (isTypeAttribute()) {
529 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
530 Result += '(';
531 raw_string_ostream OS(Result);
532 getValueAsType()->print(OS, false, true);
533 OS.flush();
534 Result += ')';
535 return Result;
538 // FIXME: These should be output like this:
540 // align=4
541 // alignstack=8
543 if (hasAttribute(Attribute::Alignment))
544 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
545 : "align " + Twine(getValueAsInt()))
546 .str();
548 auto AttrWithBytesToString = [&](const char *Name) {
549 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
550 : Name + ("(" + Twine(getValueAsInt())) + ")")
551 .str();
554 if (hasAttribute(Attribute::StackAlignment))
555 return AttrWithBytesToString("alignstack");
557 if (hasAttribute(Attribute::Dereferenceable))
558 return AttrWithBytesToString("dereferenceable");
560 if (hasAttribute(Attribute::DereferenceableOrNull))
561 return AttrWithBytesToString("dereferenceable_or_null");
563 if (hasAttribute(Attribute::AllocSize)) {
564 unsigned ElemSize;
565 std::optional<unsigned> NumElems;
566 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
568 return (NumElems
569 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
570 : "allocsize(" + Twine(ElemSize) + ")")
571 .str();
574 if (hasAttribute(Attribute::VScaleRange)) {
575 unsigned MinValue = getVScaleRangeMin();
576 std::optional<unsigned> MaxValue = getVScaleRangeMax();
577 return ("vscale_range(" + Twine(MinValue) + "," +
578 Twine(MaxValue.value_or(0)) + ")")
579 .str();
582 if (hasAttribute(Attribute::UWTable)) {
583 UWTableKind Kind = getUWTableKind();
584 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
585 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
588 if (hasAttribute(Attribute::AllocKind)) {
589 AllocFnKind Kind = getAllocKind();
590 SmallVector<StringRef> parts;
591 if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
592 parts.push_back("alloc");
593 if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
594 parts.push_back("realloc");
595 if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
596 parts.push_back("free");
597 if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
598 parts.push_back("uninitialized");
599 if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
600 parts.push_back("zeroed");
601 if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
602 parts.push_back("aligned");
603 return ("allockind(\"" +
604 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
605 .str();
608 if (hasAttribute(Attribute::Memory)) {
609 std::string Result;
610 raw_string_ostream OS(Result);
611 bool First = true;
612 OS << "memory(";
614 MemoryEffects ME = getMemoryEffects();
616 // Print access kind for "other" as the default access kind. This way it
617 // will apply to any new location kinds that get split out of "other".
618 ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other);
619 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
620 First = false;
621 OS << getModRefStr(OtherMR);
624 for (auto Loc : MemoryEffects::locations()) {
625 ModRefInfo MR = ME.getModRef(Loc);
626 if (MR == OtherMR)
627 continue;
629 if (!First)
630 OS << ", ";
631 First = false;
633 switch (Loc) {
634 case IRMemLocation::ArgMem:
635 OS << "argmem: ";
636 break;
637 case IRMemLocation::InaccessibleMem:
638 OS << "inaccessiblemem: ";
639 break;
640 case IRMemLocation::Other:
641 llvm_unreachable("This is represented as the default access kind");
643 OS << getModRefStr(MR);
645 OS << ")";
646 OS.flush();
647 return Result;
650 if (hasAttribute(Attribute::NoFPClass)) {
651 std::string Result = "nofpclass";
652 raw_string_ostream OS(Result);
653 OS << getNoFPClass();
654 return Result;
657 if (hasAttribute(Attribute::Range)) {
658 std::string Result;
659 raw_string_ostream OS(Result);
660 const ConstantRange &CR = getValueAsConstantRange();
661 OS << "range(";
662 OS << "i" << CR.getBitWidth() << " ";
663 OS << CR.getLower() << ", " << CR.getUpper();
664 OS << ")";
665 OS.flush();
666 return Result;
669 if (hasAttribute(Attribute::Initializes)) {
670 std::string Result;
671 raw_string_ostream OS(Result);
672 ConstantRangeList CRL = getInitializes();
673 OS << "initializes(";
674 CRL.print(OS);
675 OS << ")";
676 OS.flush();
677 return Result;
680 // Convert target-dependent attributes to strings of the form:
682 // "kind"
683 // "kind" = "value"
685 if (isStringAttribute()) {
686 std::string Result;
688 raw_string_ostream OS(Result);
689 OS << '"' << getKindAsString() << '"';
691 // Since some attribute strings contain special characters that cannot be
692 // printable, those have to be escaped to make the attribute value
693 // printable as is. e.g. "\01__gnu_mcount_nc"
694 const auto &AttrVal = pImpl->getValueAsString();
695 if (!AttrVal.empty()) {
696 OS << "=\"";
697 printEscapedString(AttrVal, OS);
698 OS << "\"";
701 return Result;
704 llvm_unreachable("Unknown attribute");
707 bool Attribute::hasParentContext(LLVMContext &C) const {
708 assert(isValid() && "invalid Attribute doesn't refer to any context");
709 FoldingSetNodeID ID;
710 pImpl->Profile(ID);
711 void *Unused;
712 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
715 int Attribute::cmpKind(Attribute A) const {
716 if (!pImpl && !A.pImpl)
717 return 0;
718 if (!pImpl)
719 return 1;
720 if (!A.pImpl)
721 return -1;
722 return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
725 bool Attribute::operator<(Attribute A) const {
726 if (!pImpl && !A.pImpl) return false;
727 if (!pImpl) return true;
728 if (!A.pImpl) return false;
729 return *pImpl < *A.pImpl;
732 void Attribute::Profile(FoldingSetNodeID &ID) const {
733 ID.AddPointer(pImpl);
736 enum AttributeProperty {
737 FnAttr = (1 << 0),
738 ParamAttr = (1 << 1),
739 RetAttr = (1 << 2),
740 IntersectPreserve = (0 << 3),
741 IntersectAnd = (1 << 3),
742 IntersectMin = (2 << 3),
743 IntersectCustom = (3 << 3),
744 IntersectPropertyMask = (3 << 3),
747 #define GET_ATTR_PROP_TABLE
748 #include "llvm/IR/Attributes.inc"
750 static unsigned getAttributeProperties(Attribute::AttrKind Kind) {
751 unsigned Index = Kind - 1;
752 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
753 return AttrPropTable[Index];
756 static bool hasAttributeProperty(Attribute::AttrKind Kind,
757 AttributeProperty Prop) {
758 return getAttributeProperties(Kind) & Prop;
761 bool Attribute::canUseAsFnAttr(AttrKind Kind) {
762 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
765 bool Attribute::canUseAsParamAttr(AttrKind Kind) {
766 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
769 bool Attribute::canUseAsRetAttr(AttrKind Kind) {
770 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
773 static bool hasIntersectProperty(Attribute::AttrKind Kind,
774 AttributeProperty Prop) {
775 assert((Prop == AttributeProperty::IntersectPreserve ||
776 Prop == AttributeProperty::IntersectAnd ||
777 Prop == AttributeProperty::IntersectMin ||
778 Prop == AttributeProperty::IntersectCustom) &&
779 "Unknown intersect property");
780 return (getAttributeProperties(Kind) &
781 AttributeProperty::IntersectPropertyMask) == Prop;
784 bool Attribute::intersectMustPreserve(AttrKind Kind) {
785 return hasIntersectProperty(Kind, AttributeProperty::IntersectPreserve);
787 bool Attribute::intersectWithAnd(AttrKind Kind) {
788 return hasIntersectProperty(Kind, AttributeProperty::IntersectAnd);
790 bool Attribute::intersectWithMin(AttrKind Kind) {
791 return hasIntersectProperty(Kind, AttributeProperty::IntersectMin);
793 bool Attribute::intersectWithCustom(AttrKind Kind) {
794 return hasIntersectProperty(Kind, AttributeProperty::IntersectCustom);
797 //===----------------------------------------------------------------------===//
798 // AttributeImpl Definition
799 //===----------------------------------------------------------------------===//
801 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
802 if (isStringAttribute()) return false;
803 return getKindAsEnum() == A;
806 bool AttributeImpl::hasAttribute(StringRef Kind) const {
807 if (!isStringAttribute()) return false;
808 return getKindAsString() == Kind;
811 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
812 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
813 isConstantRangeAttribute() || isConstantRangeListAttribute());
814 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
817 uint64_t AttributeImpl::getValueAsInt() const {
818 assert(isIntAttribute());
819 return static_cast<const IntAttributeImpl *>(this)->getValue();
822 bool AttributeImpl::getValueAsBool() const {
823 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
824 return getValueAsString() == "true";
827 StringRef AttributeImpl::getKindAsString() const {
828 assert(isStringAttribute());
829 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
832 StringRef AttributeImpl::getValueAsString() const {
833 assert(isStringAttribute());
834 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
837 Type *AttributeImpl::getValueAsType() const {
838 assert(isTypeAttribute());
839 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
842 const ConstantRange &AttributeImpl::getValueAsConstantRange() const {
843 assert(isConstantRangeAttribute());
844 return static_cast<const ConstantRangeAttributeImpl *>(this)
845 ->getConstantRangeValue();
848 ArrayRef<ConstantRange> AttributeImpl::getValueAsConstantRangeList() const {
849 assert(isConstantRangeListAttribute());
850 return static_cast<const ConstantRangeListAttributeImpl *>(this)
851 ->getConstantRangeListValue();
854 int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
855 if (this == &AI)
856 return 0;
858 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
859 // relative to their enum value) and then strings.
860 if (!isStringAttribute()) {
861 if (AI.isStringAttribute())
862 return -1;
864 if (getKindAsEnum() != AI.getKindAsEnum())
865 return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
866 else if (KindOnly)
867 return 0;
869 assert(!AI.isEnumAttribute() && "Non-unique attribute");
870 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
871 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
872 assert(!AI.isConstantRangeListAttribute() &&
873 "Unclear how to compare range list");
874 // TODO: Is this actually needed?
875 assert(AI.isIntAttribute() && "Only possibility left");
876 if (getValueAsInt() < AI.getValueAsInt())
877 return -1;
878 return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
880 if (!AI.isStringAttribute())
881 return 1;
882 if (KindOnly)
883 return getKindAsString().compare(AI.getKindAsString());
884 if (getKindAsString() == AI.getKindAsString())
885 return getValueAsString().compare(AI.getValueAsString());
886 return getKindAsString().compare(AI.getKindAsString());
889 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
890 return cmp(AI, /*KindOnly=*/false) < 0;
893 //===----------------------------------------------------------------------===//
894 // AttributeSet Definition
895 //===----------------------------------------------------------------------===//
897 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
898 return AttributeSet(AttributeSetNode::get(C, B));
901 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
902 return AttributeSet(AttributeSetNode::get(C, Attrs));
905 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
906 Attribute::AttrKind Kind) const {
907 if (hasAttribute(Kind)) return *this;
908 AttrBuilder B(C);
909 B.addAttribute(Kind);
910 return addAttributes(C, AttributeSet::get(C, B));
913 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
914 StringRef Value) const {
915 AttrBuilder B(C);
916 B.addAttribute(Kind, Value);
917 return addAttributes(C, AttributeSet::get(C, B));
920 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
921 const AttributeSet AS) const {
922 if (!hasAttributes())
923 return AS;
925 if (!AS.hasAttributes())
926 return *this;
928 AttrBuilder B(C, *this);
929 B.merge(AttrBuilder(C, AS));
930 return get(C, B);
933 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
934 Attribute::AttrKind Kind) const {
935 if (!hasAttribute(Kind)) return *this;
936 AttrBuilder B(C, *this);
937 B.removeAttribute(Kind);
938 return get(C, B);
941 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
942 StringRef Kind) const {
943 if (!hasAttribute(Kind)) return *this;
944 AttrBuilder B(C, *this);
945 B.removeAttribute(Kind);
946 return get(C, B);
949 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
950 const AttributeMask &Attrs) const {
951 AttrBuilder B(C, *this);
952 // If there is nothing to remove, directly return the original set.
953 if (!B.overlaps(Attrs))
954 return *this;
956 B.remove(Attrs);
957 return get(C, B);
960 std::optional<AttributeSet>
961 AttributeSet::intersectWith(LLVMContext &C, AttributeSet Other) const {
962 if (*this == Other)
963 return *this;
965 AttrBuilder Intersected(C);
966 // Iterate over both attr sets at once.
967 auto ItBegin0 = begin();
968 auto ItEnd0 = end();
969 auto ItBegin1 = Other.begin();
970 auto ItEnd1 = Other.end();
972 while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
973 // Loop through all attributes in both this and Other in sorted order. If
974 // the attribute is only present in one of the sets, it will be set in
975 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
976 Attribute Attr0, Attr1;
977 if (ItBegin1 == ItEnd1)
978 Attr0 = *ItBegin0++;
979 else if (ItBegin0 == ItEnd0)
980 Attr0 = *ItBegin1++;
981 else {
982 int Cmp = ItBegin0->cmpKind(*ItBegin1);
983 if (Cmp == 0) {
984 Attr0 = *ItBegin0++;
985 Attr1 = *ItBegin1++;
986 } else if (Cmp < 0)
987 Attr0 = *ItBegin0++;
988 else
989 Attr0 = *ItBegin1++;
991 assert(Attr0.isValid() && "Iteration should always yield a valid attr");
993 auto IntersectEq = [&]() {
994 if (!Attr1.isValid())
995 return false;
996 if (Attr0 != Attr1)
997 return false;
998 Intersected.addAttribute(Attr0);
999 return true;
1002 // Non-enum assume we must preserve. Handle early so we can unconditionally
1003 // use Kind below.
1004 if (!Attr0.hasKindAsEnum()) {
1005 if (!IntersectEq())
1006 return std::nullopt;
1007 continue;
1010 Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1011 // If we don't have both attributes, then fail if the attribute is
1012 // must-preserve or drop it otherwise.
1013 if (!Attr1.isValid()) {
1014 if (Attribute::intersectMustPreserve(Kind))
1015 return std::nullopt;
1016 continue;
1019 // We have both attributes so apply the intersection rule.
1020 assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1021 "Iterator picked up two different attributes in the same iteration");
1023 // Attribute we can intersect with "and"
1024 if (Attribute::intersectWithAnd(Kind)) {
1025 assert(Attribute::isEnumAttrKind(Kind) &&
1026 "Invalid attr type of intersectAnd");
1027 Intersected.addAttribute(Kind);
1028 continue;
1031 // Attribute we can intersect with "min"
1032 if (Attribute::intersectWithMin(Kind)) {
1033 assert(Attribute::isIntAttrKind(Kind) &&
1034 "Invalid attr type of intersectMin");
1035 uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1036 Intersected.addRawIntAttr(Kind, NewVal);
1037 continue;
1039 // Attribute we can intersect but need a custom rule for.
1040 if (Attribute::intersectWithCustom(Kind)) {
1041 switch (Kind) {
1042 case Attribute::Alignment:
1043 // If `byval` is present, alignment become must-preserve. This is
1044 // handled below if we have `byval`.
1045 Intersected.addAlignmentAttr(
1046 std::min(Attr0.getAlignment().valueOrOne(),
1047 Attr1.getAlignment().valueOrOne()));
1048 break;
1049 case Attribute::Memory:
1050 Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1051 Attr1.getMemoryEffects());
1052 break;
1053 case Attribute::NoFPClass:
1054 Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1055 Attr1.getNoFPClass());
1056 break;
1057 case Attribute::Range: {
1058 ConstantRange Range0 = Attr0.getRange();
1059 ConstantRange Range1 = Attr1.getRange();
1060 ConstantRange NewRange = Range0.unionWith(Range1);
1061 if (!NewRange.isFullSet())
1062 Intersected.addRangeAttr(NewRange);
1063 } break;
1064 default:
1065 llvm_unreachable("Unknown attribute with custom intersection rule");
1067 continue;
1070 // Attributes with no intersection rule. Only intersect if they are equal.
1071 // Otherwise fail.
1072 if (!IntersectEq())
1073 return std::nullopt;
1075 // Special handling of `byval`. `byval` essentially turns align attr into
1076 // must-preserve
1077 if (Kind == Attribute::ByVal &&
1078 getAttribute(Attribute::Alignment) !=
1079 Other.getAttribute(Attribute::Alignment))
1080 return std::nullopt;
1083 return get(C, Intersected);
1086 unsigned AttributeSet::getNumAttributes() const {
1087 return SetNode ? SetNode->getNumAttributes() : 0;
1090 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
1091 return SetNode ? SetNode->hasAttribute(Kind) : false;
1094 bool AttributeSet::hasAttribute(StringRef Kind) const {
1095 return SetNode ? SetNode->hasAttribute(Kind) : false;
1098 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
1099 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1102 Attribute AttributeSet::getAttribute(StringRef Kind) const {
1103 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1106 MaybeAlign AttributeSet::getAlignment() const {
1107 return SetNode ? SetNode->getAlignment() : std::nullopt;
1110 MaybeAlign AttributeSet::getStackAlignment() const {
1111 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
1114 uint64_t AttributeSet::getDereferenceableBytes() const {
1115 return SetNode ? SetNode->getDereferenceableBytes() : 0;
1118 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
1119 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
1122 Type *AttributeSet::getByRefType() const {
1123 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
1126 Type *AttributeSet::getByValType() const {
1127 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
1130 Type *AttributeSet::getStructRetType() const {
1131 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
1134 Type *AttributeSet::getPreallocatedType() const {
1135 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
1138 Type *AttributeSet::getInAllocaType() const {
1139 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
1142 Type *AttributeSet::getElementType() const {
1143 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
1146 std::optional<std::pair<unsigned, std::optional<unsigned>>>
1147 AttributeSet::getAllocSizeArgs() const {
1148 if (SetNode)
1149 return SetNode->getAllocSizeArgs();
1150 return std::nullopt;
1153 unsigned AttributeSet::getVScaleRangeMin() const {
1154 return SetNode ? SetNode->getVScaleRangeMin() : 1;
1157 std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1158 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
1161 UWTableKind AttributeSet::getUWTableKind() const {
1162 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
1165 AllocFnKind AttributeSet::getAllocKind() const {
1166 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
1169 MemoryEffects AttributeSet::getMemoryEffects() const {
1170 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
1173 FPClassTest AttributeSet::getNoFPClass() const {
1174 return SetNode ? SetNode->getNoFPClass() : fcNone;
1177 std::string AttributeSet::getAsString(bool InAttrGrp) const {
1178 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
1181 bool AttributeSet::hasParentContext(LLVMContext &C) const {
1182 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1183 FoldingSetNodeID ID;
1184 SetNode->Profile(ID);
1185 void *Unused;
1186 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1189 AttributeSet::iterator AttributeSet::begin() const {
1190 return SetNode ? SetNode->begin() : nullptr;
1193 AttributeSet::iterator AttributeSet::end() const {
1194 return SetNode ? SetNode->end() : nullptr;
1197 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1198 LLVM_DUMP_METHOD void AttributeSet::dump() const {
1199 dbgs() << "AS =\n";
1200 dbgs() << " { ";
1201 dbgs() << getAsString(true) << " }\n";
1203 #endif
1205 //===----------------------------------------------------------------------===//
1206 // AttributeSetNode Definition
1207 //===----------------------------------------------------------------------===//
1209 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1210 : NumAttrs(Attrs.size()) {
1211 // There's memory after the node where we can store the entries in.
1212 llvm::copy(Attrs, getTrailingObjects<Attribute>());
1214 for (const auto &I : *this) {
1215 if (I.isStringAttribute())
1216 StringAttrs.insert({ I.getKindAsString(), I });
1217 else
1218 AvailableAttrs.addAttribute(I.getKindAsEnum());
1222 AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
1223 ArrayRef<Attribute> Attrs) {
1224 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1225 llvm::sort(SortedAttrs);
1226 return getSorted(C, SortedAttrs);
1229 AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1230 ArrayRef<Attribute> SortedAttrs) {
1231 if (SortedAttrs.empty())
1232 return nullptr;
1234 // Build a key to look up the existing attributes.
1235 LLVMContextImpl *pImpl = C.pImpl;
1236 FoldingSetNodeID ID;
1238 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1239 for (const auto &Attr : SortedAttrs)
1240 Attr.Profile(ID);
1242 void *InsertPoint;
1243 AttributeSetNode *PA =
1244 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1246 // If we didn't find any existing attributes of the same shape then create a
1247 // new one and insert it.
1248 if (!PA) {
1249 // Coallocate entries after the AttributeSetNode itself.
1250 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1251 PA = new (Mem) AttributeSetNode(SortedAttrs);
1252 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1255 // Return the AttributeSetNode that we found or created.
1256 return PA;
1259 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
1260 return getSorted(C, B.attrs());
1263 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
1264 return StringAttrs.count(Kind);
1267 std::optional<Attribute>
1268 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1269 // Do a quick presence check.
1270 if (!hasAttribute(Kind))
1271 return std::nullopt;
1273 // Attributes in a set are sorted by enum value, followed by string
1274 // attributes. Binary search the one we want.
1275 const Attribute *I =
1276 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1277 [](Attribute A, Attribute::AttrKind Kind) {
1278 return A.getKindAsEnum() < Kind;
1280 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1281 return *I;
1284 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
1285 if (auto A = findEnumAttribute(Kind))
1286 return *A;
1287 return {};
1290 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
1291 return StringAttrs.lookup(Kind);
1294 MaybeAlign AttributeSetNode::getAlignment() const {
1295 if (auto A = findEnumAttribute(Attribute::Alignment))
1296 return A->getAlignment();
1297 return std::nullopt;
1300 MaybeAlign AttributeSetNode::getStackAlignment() const {
1301 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1302 return A->getStackAlignment();
1303 return std::nullopt;
1306 Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
1307 if (auto A = findEnumAttribute(Kind))
1308 return A->getValueAsType();
1309 return nullptr;
1312 uint64_t AttributeSetNode::getDereferenceableBytes() const {
1313 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1314 return A->getDereferenceableBytes();
1315 return 0;
1318 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
1319 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1320 return A->getDereferenceableOrNullBytes();
1321 return 0;
1324 std::optional<std::pair<unsigned, std::optional<unsigned>>>
1325 AttributeSetNode::getAllocSizeArgs() const {
1326 if (auto A = findEnumAttribute(Attribute::AllocSize))
1327 return A->getAllocSizeArgs();
1328 return std::nullopt;
1331 unsigned AttributeSetNode::getVScaleRangeMin() const {
1332 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1333 return A->getVScaleRangeMin();
1334 return 1;
1337 std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1338 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1339 return A->getVScaleRangeMax();
1340 return std::nullopt;
1343 UWTableKind AttributeSetNode::getUWTableKind() const {
1344 if (auto A = findEnumAttribute(Attribute::UWTable))
1345 return A->getUWTableKind();
1346 return UWTableKind::None;
1349 AllocFnKind AttributeSetNode::getAllocKind() const {
1350 if (auto A = findEnumAttribute(Attribute::AllocKind))
1351 return A->getAllocKind();
1352 return AllocFnKind::Unknown;
1355 MemoryEffects AttributeSetNode::getMemoryEffects() const {
1356 if (auto A = findEnumAttribute(Attribute::Memory))
1357 return A->getMemoryEffects();
1358 return MemoryEffects::unknown();
1361 FPClassTest AttributeSetNode::getNoFPClass() const {
1362 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1363 return A->getNoFPClass();
1364 return fcNone;
1367 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1368 std::string Str;
1369 for (iterator I = begin(), E = end(); I != E; ++I) {
1370 if (I != begin())
1371 Str += ' ';
1372 Str += I->getAsString(InAttrGrp);
1374 return Str;
1377 //===----------------------------------------------------------------------===//
1378 // AttributeListImpl Definition
1379 //===----------------------------------------------------------------------===//
1381 /// Map from AttributeList index to the internal array index. Adding one happens
1382 /// to work, because -1 wraps around to 0.
1383 static unsigned attrIdxToArrayIdx(unsigned Index) {
1384 return Index + 1;
1387 AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
1388 : NumAttrSets(Sets.size()) {
1389 assert(!Sets.empty() && "pointless AttributeListImpl");
1391 // There's memory after the node where we can store the entries in.
1392 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1394 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1395 // summary bitsets.
1396 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1397 if (!I.isStringAttribute())
1398 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1400 for (const auto &Set : Sets)
1401 for (const auto &I : Set)
1402 if (!I.isStringAttribute())
1403 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1406 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
1407 Profile(ID, ArrayRef(begin(), end()));
1410 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
1411 ArrayRef<AttributeSet> Sets) {
1412 for (const auto &Set : Sets)
1413 ID.AddPointer(Set.SetNode);
1416 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
1417 unsigned *Index) const {
1418 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1419 return false;
1421 if (Index) {
1422 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1423 if (begin()[I].hasAttribute(Kind)) {
1424 *Index = I - 1;
1425 break;
1430 return true;
1434 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1435 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1436 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1438 #endif
1440 //===----------------------------------------------------------------------===//
1441 // AttributeList Construction and Mutation Methods
1442 //===----------------------------------------------------------------------===//
1444 AttributeList AttributeList::getImpl(LLVMContext &C,
1445 ArrayRef<AttributeSet> AttrSets) {
1446 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1448 LLVMContextImpl *pImpl = C.pImpl;
1449 FoldingSetNodeID ID;
1450 AttributeListImpl::Profile(ID, AttrSets);
1452 void *InsertPoint;
1453 AttributeListImpl *PA =
1454 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1456 // If we didn't find any existing attributes of the same shape then
1457 // create a new one and insert it.
1458 if (!PA) {
1459 // Coallocate entries after the AttributeListImpl itself.
1460 void *Mem = pImpl->Alloc.Allocate(
1461 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1462 alignof(AttributeListImpl));
1463 PA = new (Mem) AttributeListImpl(AttrSets);
1464 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1467 // Return the AttributesList that we found or created.
1468 return AttributeList(PA);
1471 AttributeList
1472 AttributeList::get(LLVMContext &C,
1473 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1474 // If there are no attributes then return a null AttributesList pointer.
1475 if (Attrs.empty())
1476 return {};
1478 assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1479 "Misordered Attributes list!");
1480 assert(llvm::all_of(Attrs,
1481 [](const std::pair<unsigned, Attribute> &Pair) {
1482 return Pair.second.isValid();
1483 }) &&
1484 "Pointless attribute!");
1486 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1487 // list.
1488 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1489 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1490 E = Attrs.end(); I != E; ) {
1491 unsigned Index = I->first;
1492 SmallVector<Attribute, 4> AttrVec;
1493 while (I != E && I->first == Index) {
1494 AttrVec.push_back(I->second);
1495 ++I;
1498 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1501 return get(C, AttrPairVec);
1504 AttributeList
1505 AttributeList::get(LLVMContext &C,
1506 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1507 // If there are no attributes then return a null AttributesList pointer.
1508 if (Attrs.empty())
1509 return {};
1511 assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1512 "Misordered Attributes list!");
1513 assert(llvm::none_of(Attrs,
1514 [](const std::pair<unsigned, AttributeSet> &Pair) {
1515 return !Pair.second.hasAttributes();
1516 }) &&
1517 "Pointless attribute!");
1519 unsigned MaxIndex = Attrs.back().first;
1520 // If the MaxIndex is FunctionIndex and there are other indices in front
1521 // of it, we need to use the largest of those to get the right size.
1522 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1523 MaxIndex = Attrs[Attrs.size() - 2].first;
1525 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1526 for (const auto &Pair : Attrs)
1527 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1529 return getImpl(C, AttrVec);
1532 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1533 AttributeSet RetAttrs,
1534 ArrayRef<AttributeSet> ArgAttrs) {
1535 // Scan from the end to find the last argument with attributes. Most
1536 // arguments don't have attributes, so it's nice if we can have fewer unique
1537 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1538 unsigned NumSets = 0;
1539 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1540 if (ArgAttrs[I - 1].hasAttributes()) {
1541 NumSets = I + 2;
1542 break;
1545 if (NumSets == 0) {
1546 // Check function and return attributes if we didn't have argument
1547 // attributes.
1548 if (RetAttrs.hasAttributes())
1549 NumSets = 2;
1550 else if (FnAttrs.hasAttributes())
1551 NumSets = 1;
1554 // If all attribute sets were empty, we can use the empty attribute list.
1555 if (NumSets == 0)
1556 return {};
1558 SmallVector<AttributeSet, 8> AttrSets;
1559 AttrSets.reserve(NumSets);
1560 // If we have any attributes, we always have function attributes.
1561 AttrSets.push_back(FnAttrs);
1562 if (NumSets > 1)
1563 AttrSets.push_back(RetAttrs);
1564 if (NumSets > 2) {
1565 // Drop the empty argument attribute sets at the end.
1566 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1567 llvm::append_range(AttrSets, ArgAttrs);
1570 return getImpl(C, AttrSets);
1573 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1574 AttributeSet Attrs) {
1575 if (!Attrs.hasAttributes())
1576 return {};
1577 Index = attrIdxToArrayIdx(Index);
1578 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1579 AttrSets[Index] = Attrs;
1580 return getImpl(C, AttrSets);
1583 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1584 const AttrBuilder &B) {
1585 return get(C, Index, AttributeSet::get(C, B));
1588 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1589 ArrayRef<Attribute::AttrKind> Kinds) {
1590 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1591 for (const auto K : Kinds)
1592 Attrs.emplace_back(Index, Attribute::get(C, K));
1593 return get(C, Attrs);
1596 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1597 ArrayRef<Attribute::AttrKind> Kinds,
1598 ArrayRef<uint64_t> Values) {
1599 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1600 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1601 auto VI = Values.begin();
1602 for (const auto K : Kinds)
1603 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1604 return get(C, Attrs);
1607 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1608 ArrayRef<StringRef> Kinds) {
1609 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1610 for (const auto &K : Kinds)
1611 Attrs.emplace_back(Index, Attribute::get(C, K));
1612 return get(C, Attrs);
1615 AttributeList AttributeList::get(LLVMContext &C,
1616 ArrayRef<AttributeList> Attrs) {
1617 if (Attrs.empty())
1618 return {};
1619 if (Attrs.size() == 1)
1620 return Attrs[0];
1622 unsigned MaxSize = 0;
1623 for (const auto &List : Attrs)
1624 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1626 // If every list was empty, there is no point in merging the lists.
1627 if (MaxSize == 0)
1628 return {};
1630 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1631 for (unsigned I = 0; I < MaxSize; ++I) {
1632 AttrBuilder CurBuilder(C);
1633 for (const auto &List : Attrs)
1634 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1635 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1638 return getImpl(C, NewAttrSets);
1641 AttributeList
1642 AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1643 Attribute::AttrKind Kind) const {
1644 AttributeSet Attrs = getAttributes(Index);
1645 if (Attrs.hasAttribute(Kind))
1646 return *this;
1647 // TODO: Insert at correct position and avoid sort.
1648 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1649 NewAttrs.push_back(Attribute::get(C, Kind));
1650 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1653 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1654 StringRef Kind,
1655 StringRef Value) const {
1656 AttrBuilder B(C);
1657 B.addAttribute(Kind, Value);
1658 return addAttributesAtIndex(C, Index, B);
1661 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1662 Attribute A) const {
1663 AttrBuilder B(C);
1664 B.addAttribute(A);
1665 return addAttributesAtIndex(C, Index, B);
1668 AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1669 unsigned Index,
1670 AttributeSet Attrs) const {
1671 Index = attrIdxToArrayIdx(Index);
1672 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1673 if (Index >= AttrSets.size())
1674 AttrSets.resize(Index + 1);
1675 AttrSets[Index] = Attrs;
1677 // Remove trailing empty attribute sets.
1678 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1679 AttrSets.pop_back();
1680 if (AttrSets.empty())
1681 return {};
1682 return AttributeList::getImpl(C, AttrSets);
1685 AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1686 unsigned Index,
1687 const AttrBuilder &B) const {
1688 if (!B.hasAttributes())
1689 return *this;
1691 if (!pImpl)
1692 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1694 AttrBuilder Merged(C, getAttributes(Index));
1695 Merged.merge(B);
1696 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1699 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1700 ArrayRef<unsigned> ArgNos,
1701 Attribute A) const {
1702 assert(llvm::is_sorted(ArgNos));
1704 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1705 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1706 if (MaxIndex >= AttrSets.size())
1707 AttrSets.resize(MaxIndex + 1);
1709 for (unsigned ArgNo : ArgNos) {
1710 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1711 AttrBuilder B(C, AttrSets[Index]);
1712 B.addAttribute(A);
1713 AttrSets[Index] = AttributeSet::get(C, B);
1716 return getImpl(C, AttrSets);
1719 AttributeList
1720 AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1721 Attribute::AttrKind Kind) const {
1722 AttributeSet Attrs = getAttributes(Index);
1723 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1724 if (Attrs == NewAttrs)
1725 return *this;
1726 return setAttributesAtIndex(C, Index, NewAttrs);
1729 AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1730 unsigned Index,
1731 StringRef Kind) const {
1732 AttributeSet Attrs = getAttributes(Index);
1733 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1734 if (Attrs == NewAttrs)
1735 return *this;
1736 return setAttributesAtIndex(C, Index, NewAttrs);
1739 AttributeList AttributeList::removeAttributesAtIndex(
1740 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1741 AttributeSet Attrs = getAttributes(Index);
1742 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1743 // If nothing was removed, return the original list.
1744 if (Attrs == NewAttrs)
1745 return *this;
1746 return setAttributesAtIndex(C, Index, NewAttrs);
1749 AttributeList
1750 AttributeList::removeAttributesAtIndex(LLVMContext &C,
1751 unsigned WithoutIndex) const {
1752 if (!pImpl)
1753 return {};
1754 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1755 return *this;
1756 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1759 AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1760 uint64_t Bytes) const {
1761 AttrBuilder B(C);
1762 B.addDereferenceableAttr(Bytes);
1763 return addRetAttributes(C, B);
1766 AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1767 unsigned Index,
1768 uint64_t Bytes) const {
1769 AttrBuilder B(C);
1770 B.addDereferenceableAttr(Bytes);
1771 return addParamAttributes(C, Index, B);
1774 AttributeList
1775 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1776 uint64_t Bytes) const {
1777 AttrBuilder B(C);
1778 B.addDereferenceableOrNullAttr(Bytes);
1779 return addParamAttributes(C, Index, B);
1782 AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
1783 const ConstantRange &CR) const {
1784 AttrBuilder B(C);
1785 B.addRangeAttr(CR);
1786 return addRetAttributes(C, B);
1789 AttributeList AttributeList::addAllocSizeParamAttr(
1790 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1791 const std::optional<unsigned> &NumElemsArg) const {
1792 AttrBuilder B(C);
1793 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1794 return addParamAttributes(C, Index, B);
1797 std::optional<AttributeList>
1798 AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
1799 // Trivial case, the two lists are equal.
1800 if (*this == Other)
1801 return *this;
1803 SmallVector<std::pair<unsigned, AttributeSet>> IntersectedAttrs;
1804 auto IndexIt =
1805 index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1806 for (unsigned Idx : IndexIt) {
1807 auto IntersectedAS =
1808 getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1809 // If any index fails to intersect, fail.
1810 if (!IntersectedAS)
1811 return std::nullopt;
1812 if (!IntersectedAS->hasAttributes())
1813 continue;
1814 IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1817 llvm::sort(IntersectedAttrs, llvm::less_first());
1818 return AttributeList::get(C, IntersectedAttrs);
1821 //===----------------------------------------------------------------------===//
1822 // AttributeList Accessor Methods
1823 //===----------------------------------------------------------------------===//
1825 AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1826 return getAttributes(ArgNo + FirstArgIndex);
1829 AttributeSet AttributeList::getRetAttrs() const {
1830 return getAttributes(ReturnIndex);
1833 AttributeSet AttributeList::getFnAttrs() const {
1834 return getAttributes(FunctionIndex);
1837 bool AttributeList::hasAttributeAtIndex(unsigned Index,
1838 Attribute::AttrKind Kind) const {
1839 return getAttributes(Index).hasAttribute(Kind);
1842 bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1843 return getAttributes(Index).hasAttribute(Kind);
1846 bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1847 return getAttributes(Index).hasAttributes();
1850 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1851 return pImpl && pImpl->hasFnAttribute(Kind);
1854 bool AttributeList::hasFnAttr(StringRef Kind) const {
1855 return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1858 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1859 unsigned *Index) const {
1860 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1863 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1864 Attribute::AttrKind Kind) const {
1865 return getAttributes(Index).getAttribute(Kind);
1868 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1869 StringRef Kind) const {
1870 return getAttributes(Index).getAttribute(Kind);
1873 MaybeAlign AttributeList::getRetAlignment() const {
1874 return getAttributes(ReturnIndex).getAlignment();
1877 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1878 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1881 MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1882 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1885 Type *AttributeList::getParamByValType(unsigned Index) const {
1886 return getAttributes(Index+FirstArgIndex).getByValType();
1889 Type *AttributeList::getParamStructRetType(unsigned Index) const {
1890 return getAttributes(Index + FirstArgIndex).getStructRetType();
1893 Type *AttributeList::getParamByRefType(unsigned Index) const {
1894 return getAttributes(Index + FirstArgIndex).getByRefType();
1897 Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1898 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1901 Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1902 return getAttributes(Index + FirstArgIndex).getInAllocaType();
1905 Type *AttributeList::getParamElementType(unsigned Index) const {
1906 return getAttributes(Index + FirstArgIndex).getElementType();
1909 MaybeAlign AttributeList::getFnStackAlignment() const {
1910 return getFnAttrs().getStackAlignment();
1913 MaybeAlign AttributeList::getRetStackAlignment() const {
1914 return getRetAttrs().getStackAlignment();
1917 uint64_t AttributeList::getRetDereferenceableBytes() const {
1918 return getRetAttrs().getDereferenceableBytes();
1921 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1922 return getParamAttrs(Index).getDereferenceableBytes();
1925 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1926 return getRetAttrs().getDereferenceableOrNullBytes();
1929 uint64_t
1930 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1931 return getParamAttrs(Index).getDereferenceableOrNullBytes();
1934 std::optional<ConstantRange>
1935 AttributeList::getParamRange(unsigned ArgNo) const {
1936 auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
1937 if (RangeAttr.isValid())
1938 return RangeAttr.getRange();
1939 return std::nullopt;
1942 FPClassTest AttributeList::getRetNoFPClass() const {
1943 return getRetAttrs().getNoFPClass();
1946 FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {
1947 return getParamAttrs(Index).getNoFPClass();
1950 UWTableKind AttributeList::getUWTableKind() const {
1951 return getFnAttrs().getUWTableKind();
1954 AllocFnKind AttributeList::getAllocKind() const {
1955 return getFnAttrs().getAllocKind();
1958 MemoryEffects AttributeList::getMemoryEffects() const {
1959 return getFnAttrs().getMemoryEffects();
1962 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1963 return getAttributes(Index).getAsString(InAttrGrp);
1966 AttributeSet AttributeList::getAttributes(unsigned Index) const {
1967 Index = attrIdxToArrayIdx(Index);
1968 if (!pImpl || Index >= getNumAttrSets())
1969 return {};
1970 return pImpl->begin()[Index];
1973 bool AttributeList::hasParentContext(LLVMContext &C) const {
1974 assert(!isEmpty() && "an empty attribute list has no parent context");
1975 FoldingSetNodeID ID;
1976 pImpl->Profile(ID);
1977 void *Unused;
1978 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1981 AttributeList::iterator AttributeList::begin() const {
1982 return pImpl ? pImpl->begin() : nullptr;
1985 AttributeList::iterator AttributeList::end() const {
1986 return pImpl ? pImpl->end() : nullptr;
1989 //===----------------------------------------------------------------------===//
1990 // AttributeList Introspection Methods
1991 //===----------------------------------------------------------------------===//
1993 unsigned AttributeList::getNumAttrSets() const {
1994 return pImpl ? pImpl->NumAttrSets : 0;
1997 void AttributeList::print(raw_ostream &O) const {
1998 O << "AttributeList[\n";
2000 for (unsigned i : indexes()) {
2001 if (!getAttributes(i).hasAttributes())
2002 continue;
2003 O << " { ";
2004 switch (i) {
2005 case AttrIndex::ReturnIndex:
2006 O << "return";
2007 break;
2008 case AttrIndex::FunctionIndex:
2009 O << "function";
2010 break;
2011 default:
2012 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2014 O << " => " << getAsString(i) << " }\n";
2017 O << "]\n";
2020 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2021 LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
2022 #endif
2024 //===----------------------------------------------------------------------===//
2025 // AttrBuilder Method Implementations
2026 //===----------------------------------------------------------------------===//
2028 AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
2029 append_range(Attrs, AS);
2030 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2033 void AttrBuilder::clear() { Attrs.clear(); }
2035 /// Attribute comparator that only compares attribute keys. Enum attributes are
2036 /// sorted before string attributes.
2037 struct AttributeComparator {
2038 bool operator()(Attribute A0, Attribute A1) const {
2039 bool A0IsString = A0.isStringAttribute();
2040 bool A1IsString = A1.isStringAttribute();
2041 if (A0IsString) {
2042 if (A1IsString)
2043 return A0.getKindAsString() < A1.getKindAsString();
2044 else
2045 return false;
2047 if (A1IsString)
2048 return true;
2049 return A0.getKindAsEnum() < A1.getKindAsEnum();
2051 bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
2052 if (A0.isStringAttribute())
2053 return false;
2054 return A0.getKindAsEnum() < Kind;
2056 bool operator()(Attribute A0, StringRef Kind) const {
2057 if (A0.isStringAttribute())
2058 return A0.getKindAsString() < Kind;
2059 return true;
2063 template <typename K>
2064 static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
2065 Attribute Attr) {
2066 auto It = lower_bound(Attrs, Kind, AttributeComparator());
2067 if (It != Attrs.end() && It->hasAttribute(Kind))
2068 std::swap(*It, Attr);
2069 else
2070 Attrs.insert(It, Attr);
2073 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
2074 if (Attr.isStringAttribute())
2075 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2076 else
2077 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2078 return *this;
2081 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
2082 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2083 return *this;
2086 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
2087 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2088 return *this;
2091 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
2092 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2093 auto It = lower_bound(Attrs, Val, AttributeComparator());
2094 if (It != Attrs.end() && It->hasAttribute(Val))
2095 Attrs.erase(It);
2096 return *this;
2099 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
2100 auto It = lower_bound(Attrs, A, AttributeComparator());
2101 if (It != Attrs.end() && It->hasAttribute(A))
2102 Attrs.erase(It);
2103 return *this;
2106 std::optional<uint64_t>
2107 AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
2108 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2109 Attribute A = getAttribute(Kind);
2110 if (A.isValid())
2111 return A.getValueAsInt();
2112 return std::nullopt;
2115 AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
2116 uint64_t Value) {
2117 return addAttribute(Attribute::get(Ctx, Kind, Value));
2120 std::optional<std::pair<unsigned, std::optional<unsigned>>>
2121 AttrBuilder::getAllocSizeArgs() const {
2122 Attribute A = getAttribute(Attribute::AllocSize);
2123 if (A.isValid())
2124 return A.getAllocSizeArgs();
2125 return std::nullopt;
2128 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
2129 if (!Align)
2130 return *this;
2132 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2133 return addRawIntAttr(Attribute::Alignment, Align->value());
2136 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
2137 // Default alignment, allow the target to define how to align it.
2138 if (!Align)
2139 return *this;
2141 assert(*Align <= 0x100 && "Alignment too large.");
2142 return addRawIntAttr(Attribute::StackAlignment, Align->value());
2145 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
2146 if (Bytes == 0) return *this;
2148 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2151 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
2152 if (Bytes == 0)
2153 return *this;
2155 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2158 AttrBuilder &
2159 AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
2160 const std::optional<unsigned> &NumElems) {
2161 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2164 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
2165 // (0, 0) is our "not present" value, so we need to check for it here.
2166 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2167 return addRawIntAttr(Attribute::AllocSize, RawArgs);
2170 AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
2171 std::optional<unsigned> MaxValue) {
2172 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2175 AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
2176 // (0, 0) is not present hence ignore this case
2177 if (RawArgs == 0)
2178 return *this;
2180 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2183 AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
2184 if (Kind == UWTableKind::None)
2185 return *this;
2186 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2189 AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
2190 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2193 AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
2194 if (Mask == fcNone)
2195 return *this;
2197 return addRawIntAttr(Attribute::NoFPClass, Mask);
2200 AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
2201 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2204 Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
2205 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2206 Attribute A = getAttribute(Kind);
2207 return A.isValid() ? A.getValueAsType() : nullptr;
2210 AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
2211 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2214 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
2215 return addTypeAttr(Attribute::ByVal, Ty);
2218 AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
2219 return addTypeAttr(Attribute::StructRet, Ty);
2222 AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
2223 return addTypeAttr(Attribute::ByRef, Ty);
2226 AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
2227 return addTypeAttr(Attribute::Preallocated, Ty);
2230 AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
2231 return addTypeAttr(Attribute::InAlloca, Ty);
2234 AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,
2235 const ConstantRange &CR) {
2236 if (CR.isFullSet())
2237 return *this;
2239 return addAttribute(Attribute::get(Ctx, Kind, CR));
2242 AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
2243 return addConstantRangeAttr(Attribute::Range, CR);
2246 AttrBuilder &
2247 AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
2248 ArrayRef<ConstantRange> Val) {
2249 return addAttribute(Attribute::get(Ctx, Kind, Val));
2252 AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
2253 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2256 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
2257 // TODO: Could make this O(n) as we're merging two sorted lists.
2258 for (const auto &I : B.attrs())
2259 addAttribute(I);
2261 return *this;
2264 AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
2265 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2266 return *this;
2269 bool AttrBuilder::overlaps(const AttributeMask &AM) const {
2270 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2273 Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
2274 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2275 auto It = lower_bound(Attrs, A, AttributeComparator());
2276 if (It != Attrs.end() && It->hasAttribute(A))
2277 return *It;
2278 return {};
2281 Attribute AttrBuilder::getAttribute(StringRef A) const {
2282 auto It = lower_bound(Attrs, A, AttributeComparator());
2283 if (It != Attrs.end() && It->hasAttribute(A))
2284 return *It;
2285 return {};
2288 std::optional<ConstantRange> AttrBuilder::getRange() const {
2289 const Attribute RangeAttr = getAttribute(Attribute::Range);
2290 if (RangeAttr.isValid())
2291 return RangeAttr.getRange();
2292 return std::nullopt;
2295 bool AttrBuilder::contains(Attribute::AttrKind A) const {
2296 return getAttribute(A).isValid();
2299 bool AttrBuilder::contains(StringRef A) const {
2300 return getAttribute(A).isValid();
2303 bool AttrBuilder::operator==(const AttrBuilder &B) const {
2304 return Attrs == B.Attrs;
2307 //===----------------------------------------------------------------------===//
2308 // AttributeFuncs Function Defintions
2309 //===----------------------------------------------------------------------===//
2311 /// Returns true if this is a type legal for the 'nofpclass' attribute. This
2312 /// follows the same type rules as FPMathOperator.
2313 bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2314 return FPMathOperator::isSupportedFloatingPointType(Ty);
2317 /// Which attributes cannot be applied to a type.
2318 AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
2319 AttributeSafetyKind ASK) {
2320 AttributeMask Incompatible;
2322 if (!Ty->isIntegerTy()) {
2323 // Attributes that only apply to integers.
2324 if (ASK & ASK_SAFE_TO_DROP)
2325 Incompatible.addAttribute(Attribute::AllocAlign);
2326 if (ASK & ASK_UNSAFE_TO_DROP)
2327 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2330 if (!Ty->isIntOrIntVectorTy()) {
2331 // Attributes that only apply to integers or vector of integers.
2332 if (ASK & ASK_SAFE_TO_DROP)
2333 Incompatible.addAttribute(Attribute::Range);
2334 } else {
2335 Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2336 if (RangeAttr.isValid() &&
2337 RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2338 Incompatible.addAttribute(Attribute::Range);
2341 if (!Ty->isPointerTy()) {
2342 // Attributes that only apply to pointers.
2343 if (ASK & ASK_SAFE_TO_DROP)
2344 Incompatible.addAttribute(Attribute::NoAlias)
2345 .addAttribute(Attribute::NoCapture)
2346 .addAttribute(Attribute::NonNull)
2347 .addAttribute(Attribute::ReadNone)
2348 .addAttribute(Attribute::ReadOnly)
2349 .addAttribute(Attribute::Dereferenceable)
2350 .addAttribute(Attribute::DereferenceableOrNull)
2351 .addAttribute(Attribute::Writable)
2352 .addAttribute(Attribute::DeadOnUnwind)
2353 .addAttribute(Attribute::Initializes);
2354 if (ASK & ASK_UNSAFE_TO_DROP)
2355 Incompatible.addAttribute(Attribute::Nest)
2356 .addAttribute(Attribute::SwiftError)
2357 .addAttribute(Attribute::Preallocated)
2358 .addAttribute(Attribute::InAlloca)
2359 .addAttribute(Attribute::ByVal)
2360 .addAttribute(Attribute::StructRet)
2361 .addAttribute(Attribute::ByRef)
2362 .addAttribute(Attribute::ElementType)
2363 .addAttribute(Attribute::AllocatedPointer);
2366 // Attributes that only apply to pointers or vectors of pointers.
2367 if (!Ty->isPtrOrPtrVectorTy()) {
2368 if (ASK & ASK_SAFE_TO_DROP)
2369 Incompatible.addAttribute(Attribute::Alignment);
2372 if (ASK & ASK_SAFE_TO_DROP) {
2373 if (!isNoFPClassCompatibleType(Ty))
2374 Incompatible.addAttribute(Attribute::NoFPClass);
2377 // Some attributes can apply to all "values" but there are no `void` values.
2378 if (Ty->isVoidTy()) {
2379 if (ASK & ASK_SAFE_TO_DROP)
2380 Incompatible.addAttribute(Attribute::NoUndef);
2383 return Incompatible;
2386 AttributeMask AttributeFuncs::getUBImplyingAttributes() {
2387 AttributeMask AM;
2388 AM.addAttribute(Attribute::NoUndef);
2389 AM.addAttribute(Attribute::Dereferenceable);
2390 AM.addAttribute(Attribute::DereferenceableOrNull);
2391 return AM;
2394 /// Callees with dynamic denormal modes are compatible with any caller mode.
2395 static bool denormModeCompatible(DenormalMode CallerMode,
2396 DenormalMode CalleeMode) {
2397 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2398 return true;
2400 // If they don't exactly match, it's OK if the mismatched component is
2401 // dynamic.
2402 if (CalleeMode.Input == CallerMode.Input &&
2403 CalleeMode.Output == DenormalMode::Dynamic)
2404 return true;
2406 if (CalleeMode.Output == CallerMode.Output &&
2407 CalleeMode.Input == DenormalMode::Dynamic)
2408 return true;
2409 return false;
2412 static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2413 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2414 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2416 if (denormModeCompatible(CallerMode, CalleeMode)) {
2417 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2418 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2419 if (CallerModeF32 == DenormalMode::getInvalid())
2420 CallerModeF32 = CallerMode;
2421 if (CalleeModeF32 == DenormalMode::getInvalid())
2422 CalleeModeF32 = CalleeMode;
2423 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2426 return false;
2429 static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2430 // Do not inline strictfp function into non-strictfp one. It would require
2431 // conversion of all FP operations in host function to constrained intrinsics.
2432 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2433 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2436 template<typename AttrClass>
2437 static bool isEqual(const Function &Caller, const Function &Callee) {
2438 return Caller.getFnAttribute(AttrClass::getKind()) ==
2439 Callee.getFnAttribute(AttrClass::getKind());
2442 static bool isEqual(const Function &Caller, const Function &Callee,
2443 const StringRef &AttrName) {
2444 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2447 /// Compute the logical AND of the attributes of the caller and the
2448 /// callee.
2450 /// This function sets the caller's attribute to false if the callee's attribute
2451 /// is false.
2452 template<typename AttrClass>
2453 static void setAND(Function &Caller, const Function &Callee) {
2454 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2455 !AttrClass::isSet(Callee, AttrClass::getKind()))
2456 AttrClass::set(Caller, AttrClass::getKind(), false);
2459 /// Compute the logical OR of the attributes of the caller and the
2460 /// callee.
2462 /// This function sets the caller's attribute to true if the callee's attribute
2463 /// is true.
2464 template<typename AttrClass>
2465 static void setOR(Function &Caller, const Function &Callee) {
2466 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2467 AttrClass::isSet(Callee, AttrClass::getKind()))
2468 AttrClass::set(Caller, AttrClass::getKind(), true);
2471 /// If the inlined function had a higher stack protection level than the
2472 /// calling function, then bump up the caller's stack protection level.
2473 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2474 // If the calling function has *no* stack protection level (e.g. it was built
2475 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2476 // change it as that could change the program's semantics.
2477 if (!Caller.hasStackProtectorFnAttr())
2478 return;
2480 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2481 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2482 // clutter to the IR.
2483 AttributeMask OldSSPAttr;
2484 OldSSPAttr.addAttribute(Attribute::StackProtect)
2485 .addAttribute(Attribute::StackProtectStrong)
2486 .addAttribute(Attribute::StackProtectReq);
2488 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2489 Caller.removeFnAttrs(OldSSPAttr);
2490 Caller.addFnAttr(Attribute::StackProtectReq);
2491 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2492 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2493 Caller.removeFnAttrs(OldSSPAttr);
2494 Caller.addFnAttr(Attribute::StackProtectStrong);
2495 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2496 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2497 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2498 Caller.addFnAttr(Attribute::StackProtect);
2501 /// If the inlined function required stack probes, then ensure that
2502 /// the calling function has those too.
2503 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2504 if (!Caller.hasFnAttribute("probe-stack") &&
2505 Callee.hasFnAttribute("probe-stack")) {
2506 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2510 /// If the inlined function defines the size of guard region
2511 /// on the stack, then ensure that the calling function defines a guard region
2512 /// that is no larger.
2513 static void
2514 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
2515 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2516 if (CalleeAttr.isValid()) {
2517 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2518 if (CallerAttr.isValid()) {
2519 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2520 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2521 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2523 if (CallerStackProbeSize > CalleeStackProbeSize) {
2524 Caller.addFnAttr(CalleeAttr);
2526 } else {
2527 Caller.addFnAttr(CalleeAttr);
2532 /// If the inlined function defines a min legal vector width, then ensure
2533 /// the calling function has the same or larger min legal vector width. If the
2534 /// caller has the attribute, but the callee doesn't, we need to remove the
2535 /// attribute from the caller since we can't make any guarantees about the
2536 /// caller's requirements.
2537 /// This function is called after the inlining decision has been made so we have
2538 /// to merge the attribute this way. Heuristics that would use
2539 /// min-legal-vector-width to determine inline compatibility would need to be
2540 /// handled as part of inline cost analysis.
2541 static void
2542 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
2543 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2544 if (CallerAttr.isValid()) {
2545 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2546 if (CalleeAttr.isValid()) {
2547 uint64_t CallerVectorWidth, CalleeVectorWidth;
2548 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2549 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2550 if (CallerVectorWidth < CalleeVectorWidth)
2551 Caller.addFnAttr(CalleeAttr);
2552 } else {
2553 // If the callee doesn't have the attribute then we don't know anything
2554 // and must drop the attribute from the caller.
2555 Caller.removeFnAttr("min-legal-vector-width");
2560 /// If the inlined function has null_pointer_is_valid attribute,
2561 /// set this attribute in the caller post inlining.
2562 static void
2563 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2564 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2565 Caller.addFnAttr(Attribute::NullPointerIsValid);
2569 struct EnumAttr {
2570 static bool isSet(const Function &Fn,
2571 Attribute::AttrKind Kind) {
2572 return Fn.hasFnAttribute(Kind);
2575 static void set(Function &Fn,
2576 Attribute::AttrKind Kind, bool Val) {
2577 if (Val)
2578 Fn.addFnAttr(Kind);
2579 else
2580 Fn.removeFnAttr(Kind);
2584 struct StrBoolAttr {
2585 static bool isSet(const Function &Fn,
2586 StringRef Kind) {
2587 auto A = Fn.getFnAttribute(Kind);
2588 return A.getValueAsString() == "true";
2591 static void set(Function &Fn,
2592 StringRef Kind, bool Val) {
2593 Fn.addFnAttr(Kind, Val ? "true" : "false");
2597 #define GET_ATTR_NAMES
2598 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2599 struct ENUM_NAME##Attr : EnumAttr { \
2600 static enum Attribute::AttrKind getKind() { \
2601 return llvm::Attribute::ENUM_NAME; \
2604 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2605 struct ENUM_NAME##Attr : StrBoolAttr { \
2606 static StringRef getKind() { return #DISPLAY_NAME; } \
2608 #include "llvm/IR/Attributes.inc"
2610 #define GET_ATTR_COMPAT_FUNC
2611 #include "llvm/IR/Attributes.inc"
2613 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2614 const Function &Callee) {
2615 return hasCompatibleFnAttrs(Caller, Callee);
2618 bool AttributeFuncs::areOutlineCompatible(const Function &A,
2619 const Function &B) {
2620 return hasCompatibleFnAttrs(A, B);
2623 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2624 const Function &Callee) {
2625 mergeFnAttrs(Caller, Callee);
2628 void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2629 const Function &ToMerge) {
2631 // We merge functions so that they meet the most general case.
2632 // For example, if the NoNansFPMathAttr is set in one function, but not in
2633 // the other, in the merged function we can say that the NoNansFPMathAttr
2634 // is not set.
2635 // However if we have the SpeculativeLoadHardeningAttr set true in one
2636 // function, but not the other, we make sure that the function retains
2637 // that aspect in the merged function.
2638 mergeFnAttrs(Base, ToMerge);
2641 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2642 uint64_t Width) {
2643 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2644 if (Attr.isValid()) {
2645 uint64_t OldWidth;
2646 Attr.getValueAsString().getAsInteger(0, OldWidth);
2647 if (Width > OldWidth)
2648 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));