LLVM 22.0.0git
Attributes.cpp
Go to the documentation of this file.
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"
23#include "llvm/ADT/StringRef.h"
25#include "llvm/Config/llvm-config.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"
35#include "llvm/Support/ModRef.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
47using 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."
59static const unsigned AllocSizeNumElemsNotPresent = -1;
60
61static 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
70static std::pair<unsigned, std::optional<unsigned>>
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
81static uint64_t packVScaleRangeArgs(unsigned MinValue,
82 std::optional<unsigned> MaxValue) {
83 return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
84}
85
86static std::pair<unsigned, std::optional<unsigned>>
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
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;
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
126Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
127 LLVMContextImpl *pImpl = Context.pImpl;
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
150 Type *Ty) {
151 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
152 LLVMContextImpl *pImpl = Context.pImpl;
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
172 const ConstantRange &CR) {
174 "Not a ConstantRange attribute");
175 assert(!CR.isFullSet() && "ConstantRange attribute must not be full");
176 LLVMContextImpl *pImpl = Context.pImpl;
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())
190 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
191 }
192
193 // Return the Attribute that we found or created.
194 return Attribute(PA);
195}
196
200 "Not a ConstantRangeList attribute");
201 LLVMContextImpl *pImpl = Context.pImpl;
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(
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
235 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
236 return get(Context, Alignment, A.value());
237}
238
240 assert(A <= 0x100 && "Alignment too large.");
241 return get(Context, StackAlignment, A.value());
242}
243
245 uint64_t Bytes) {
246 assert(Bytes && "Bytes must be non-zero.");
247 return get(Context, Dereferenceable, Bytes);
248}
249
251 uint64_t Bytes) {
252 assert(Bytes && "Bytes must be non-zero.");
253 return get(Context, DereferenceableOrNull, Bytes);
254}
255
257 return get(Context, ByVal, Ty);
258}
259
261 return get(Context, StructRet, Ty);
262}
263
265 return get(Context, ByRef, Ty);
266}
267
269 return get(Context, Preallocated, Ty);
270}
271
273 return get(Context, InAlloca, Ty);
274}
275
277 UWTableKind Kind) {
278 return get(Context, UWTable, uint64_t(Kind));
279}
280
282 MemoryEffects ME) {
283 return get(Context, Memory, ME.toIntValue());
284}
285
287 FPClassTest ClassMask) {
288 return get(Context, NoFPClass, ClassMask);
289}
290
292 return get(Context, Captures, CI.toIntValue());
293}
294
296Attribute::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
304 return get(Context, AllocKind, static_cast<uint64_t>(Kind));
305}
306
308 unsigned MinValue,
309 unsigned MaxValue) {
310 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
311}
312
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"
320}
321
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
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
349 return pImpl && pImpl->isEnumAttribute();
350}
351
353 return pImpl && pImpl->isIntAttribute();
354}
355
357 return pImpl && pImpl->isStringAttribute();
358}
359
361 return pImpl && pImpl->isTypeAttribute();
362}
363
365 return pImpl && pImpl->isConstantRangeAttribute();
366}
367
369 return pImpl && pImpl->isConstantRangeListAttribute();
370}
371
373 if (!pImpl) return None;
375 "Invalid attribute type to get the kind as an enum!");
376 return pImpl->getKindAsEnum();
377}
378
380 if (!pImpl) return 0;
382 "Expected the attribute to be an integer attribute!");
383 return pImpl->getValueAsInt();
384}
385
387 if (!pImpl) return false;
389 "Expected the attribute to be a string attribute!");
390 return pImpl->getValueAsBool();
391}
392
394 if (!pImpl) return {};
396 "Invalid attribute type to get the kind as a string!");
397 return pImpl->getKindAsString();
398}
399
401 if (!pImpl) return {};
403 "Invalid attribute type to get the value as a string!");
404 return pImpl->getValueAsString();
405}
406
408 if (!pImpl) return {};
410 "Invalid attribute type to get the value as a type!");
411 return pImpl->getValueAsType();
412}
413
416 "Invalid attribute type to get the value as a ConstantRange!");
417 return pImpl->getValueAsConstantRange();
418}
419
422 "Invalid attribute type to get the value as a ConstantRangeList!");
423 return pImpl->getValueAsConstantRangeList();
424}
425
427 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
428}
429
431 if (!isStringAttribute()) return false;
432 return pImpl && pImpl->hasAttribute(Kind);
433}
434
436 assert(hasAttribute(Attribute::Alignment) &&
437 "Trying to get alignment from non-alignment attribute!");
438 return MaybeAlign(pImpl->getValueAsInt());
439}
440
442 assert(hasAttribute(Attribute::StackAlignment) &&
443 "Trying to get alignment from non-alignment attribute!");
444 return MaybeAlign(pImpl->getValueAsInt());
445}
446
448 assert(hasAttribute(Attribute::Dereferenceable) &&
449 "Trying to get dereferenceable bytes from "
450 "non-dereferenceable attribute!");
451 return pImpl->getValueAsInt();
452}
453
455 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
456 "Trying to get dereferenceable bytes from "
457 "non-dereferenceable attribute!");
458 return pImpl->getValueAsInt();
459}
460
461std::pair<unsigned, std::optional<unsigned>>
463 assert(hasAttribute(Attribute::AllocSize) &&
464 "Trying to get allocsize args from non-allocsize attribute");
465 return unpackAllocSizeArgs(pImpl->getValueAsInt());
466}
467
469 assert(hasAttribute(Attribute::VScaleRange) &&
470 "Trying to get vscale args from non-vscale attribute");
471 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
472}
473
474std::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
481 assert(hasAttribute(Attribute::UWTable) &&
482 "Trying to get unwind table kind from non-uwtable attribute");
483 return UWTableKind(pImpl->getValueAsInt());
484}
485
487 assert(hasAttribute(Attribute::AllocKind) &&
488 "Trying to get allockind value from non-allockind attribute");
489 return AllocFnKind(pImpl->getValueAsInt());
490}
491
493 assert(hasAttribute(Attribute::Memory) &&
494 "Can only call getMemoryEffects() on memory attribute");
495 return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
496}
497
499 assert(hasAttribute(Attribute::Captures) &&
500 "Can only call getCaptureInfo() on captures attribute");
501 return CaptureInfo::createFromIntValue(pImpl->getValueAsInt());
502}
503
505 assert(hasAttribute(Attribute::NoFPClass) &&
506 "Can only call getNoFPClass() on nofpclass attribute");
507 return static_cast<FPClassTest>(pImpl->getValueAsInt());
508}
509
511 assert(hasAttribute(Attribute::Range) &&
512 "Trying to get range args from non-range attribute");
513 return pImpl->getValueAsConstantRange();
514}
515
517 assert(hasAttribute(Attribute::Initializes) &&
518 "Trying to get initializes attr from non-ConstantRangeList attribute");
519 return pImpl->getValueAsConstantRangeList();
520}
521
522static const char *getModRefStr(ModRefInfo MR) {
523 switch (MR) {
525 return "none";
526 case ModRefInfo::Ref:
527 return "read";
528 case ModRefInfo::Mod:
529 return "write";
531 return "readwrite";
532 }
533 llvm_unreachable("Invalid ModRefInfo");
534}
535
536std::string Attribute::getAsString(bool InAttrGrp) const {
537 if (!pImpl) return {};
538
539 if (isEnumAttribute())
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)) {
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();
606 parts.push_back("alloc");
608 parts.push_back("realloc");
610 parts.push_back("free");
612 parts.push_back("uninitialized");
614 parts.push_back("zeroed");
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
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".
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) {
649 OS << "argmem: ";
650 break;
652 OS << "inaccessiblemem: ";
653 break;
655 OS << "errnomem: ";
656 break;
658 llvm_unreachable("This is represented as the default access kind");
660 OS << "target_mem0: ";
661 break;
663 OS << "target_mem1: ";
664 break;
665 }
666 OS << getModRefStr(MR);
667 }
668 OS << ")";
669 OS.flush();
670 return Result;
671 }
672
673 if (hasAttribute(Attribute::Captures)) {
674 std::string Result;
675 raw_string_ostream OS(Result);
676 OS << getCaptureInfo();
677 return Result;
678 }
679
680 if (hasAttribute(Attribute::NoFPClass)) {
681 std::string Result = "nofpclass";
682 raw_string_ostream OS(Result);
683 OS << getNoFPClass();
684 return Result;
685 }
686
687 if (hasAttribute(Attribute::Range)) {
688 std::string Result;
689 raw_string_ostream OS(Result);
691 OS << "range(";
692 OS << "i" << CR.getBitWidth() << " ";
693 OS << CR.getLower() << ", " << CR.getUpper();
694 OS << ")";
695 OS.flush();
696 return Result;
697 }
698
699 if (hasAttribute(Attribute::Initializes)) {
700 std::string Result;
701 raw_string_ostream OS(Result);
703 OS << "initializes(";
704 CRL.print(OS);
705 OS << ")";
706 OS.flush();
707 return Result;
708 }
709
710 // Convert target-dependent attributes to strings of the form:
711 //
712 // "kind"
713 // "kind" = "value"
714 //
715 if (isStringAttribute()) {
716 std::string Result;
717 {
718 raw_string_ostream OS(Result);
719 OS << '"' << getKindAsString() << '"';
720
721 // Since some attribute strings contain special characters that cannot be
722 // printable, those have to be escaped to make the attribute value
723 // printable as is. e.g. "\01__gnu_mcount_nc"
724 const auto &AttrVal = pImpl->getValueAsString();
725 if (!AttrVal.empty()) {
726 OS << "=\"";
727 printEscapedString(AttrVal, OS);
728 OS << "\"";
729 }
730 }
731 return Result;
732 }
733
734 llvm_unreachable("Unknown attribute");
735}
736
738 assert(isValid() && "invalid Attribute doesn't refer to any context");
740 pImpl->Profile(ID);
741 void *Unused;
742 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
743}
744
745int Attribute::cmpKind(Attribute A) const {
746 if (!pImpl && !A.pImpl)
747 return 0;
748 if (!pImpl)
749 return 1;
750 if (!A.pImpl)
751 return -1;
752 return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
753}
754
755bool Attribute::operator<(Attribute A) const {
756 if (!pImpl && !A.pImpl) return false;
757 if (!pImpl) return true;
758 if (!A.pImpl) return false;
759 return *pImpl < *A.pImpl;
760}
761
763 ID.AddPointer(pImpl);
764}
765
767 FnAttr = (1 << 0),
768 ParamAttr = (1 << 1),
769 RetAttr = (1 << 2),
771 IntersectAnd = (1 << 3),
772 IntersectMin = (2 << 3),
773 IntersectCustom = (3 << 3),
775};
776
777#define GET_ATTR_PROP_TABLE
778#include "llvm/IR/Attributes.inc"
779
781 unsigned Index = Kind - 1;
782 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
783 return AttrPropTable[Index];
784}
785
787 AttributeProperty Prop) {
788 return getAttributeProperties(Kind) & Prop;
789}
790
794
798
802
804 AttributeProperty Prop) {
809 "Unknown intersect property");
810 return (getAttributeProperties(Kind) &
812}
813
826
827//===----------------------------------------------------------------------===//
828// AttributeImpl Definition
829//===----------------------------------------------------------------------===//
830
832 if (isStringAttribute()) return false;
833 return getKindAsEnum() == A;
834}
835
837 if (!isStringAttribute()) return false;
838 return getKindAsString() == Kind;
839}
840
846
849 return static_cast<const IntAttributeImpl *>(this)->getValue();
850}
851
853 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
854 return getValueAsString() == "true";
855}
856
859 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
860}
861
864 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
865}
866
869 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
870}
871
874 return static_cast<const ConstantRangeAttributeImpl *>(this)
875 ->getConstantRangeValue();
876}
877
880 return static_cast<const ConstantRangeListAttributeImpl *>(this)
881 ->getConstantRangeListValue();
882}
883
884int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
885 if (this == &AI)
886 return 0;
887
888 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
889 // relative to their enum value) and then strings.
890 if (!isStringAttribute()) {
891 if (AI.isStringAttribute())
892 return -1;
893
894 if (getKindAsEnum() != AI.getKindAsEnum())
895 return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
896 else if (KindOnly)
897 return 0;
898
899 assert(!AI.isEnumAttribute() && "Non-unique attribute");
900 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
901 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
903 "Unclear how to compare range list");
904 // TODO: Is this actually needed?
905 assert(AI.isIntAttribute() && "Only possibility left");
906 if (getValueAsInt() < AI.getValueAsInt())
907 return -1;
908 return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
909 }
910 if (!AI.isStringAttribute())
911 return 1;
912 if (KindOnly)
914 if (getKindAsString() == AI.getKindAsString())
917}
918
920 return cmp(AI, /*KindOnly=*/false) < 0;
921}
922
923//===----------------------------------------------------------------------===//
924// AttributeSet Definition
925//===----------------------------------------------------------------------===//
926
927AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
929}
930
934
936 Attribute::AttrKind Kind) const {
937 if (hasAttribute(Kind)) return *this;
938 AttrBuilder B(C);
939 B.addAttribute(Kind);
941}
942
944 StringRef Value) const {
945 AttrBuilder B(C);
946 B.addAttribute(Kind, Value);
948}
949
951 const AttributeSet AS) const {
952 if (!hasAttributes())
953 return AS;
954
955 if (!AS.hasAttributes())
956 return *this;
957
958 AttrBuilder B(C, *this);
959 B.merge(AttrBuilder(C, AS));
960 return get(C, B);
961}
962
964 const AttrBuilder &B) const {
965 if (!hasAttributes())
966 return get(C, B);
967
968 if (!B.hasAttributes())
969 return *this;
970
971 AttrBuilder Merged(C, *this);
972 Merged.merge(B);
973 return get(C, Merged);
974}
975
977 Attribute::AttrKind Kind) const {
978 if (!hasAttribute(Kind)) return *this;
979 AttrBuilder B(C, *this);
980 B.removeAttribute(Kind);
981 return get(C, B);
982}
983
985 StringRef Kind) const {
986 if (!hasAttribute(Kind)) return *this;
987 AttrBuilder B(C, *this);
988 B.removeAttribute(Kind);
989 return get(C, B);
990}
991
993 const AttributeMask &Attrs) const {
994 AttrBuilder B(C, *this);
995 // If there is nothing to remove, directly return the original set.
996 if (!B.overlaps(Attrs))
997 return *this;
998
999 B.remove(Attrs);
1000 return get(C, B);
1001}
1002
1003std::optional<AttributeSet>
1005 if (*this == Other)
1006 return *this;
1007
1008 AttrBuilder Intersected(C);
1009 // Iterate over both attr sets at once.
1010 auto ItBegin0 = begin();
1011 auto ItEnd0 = end();
1012 auto ItBegin1 = Other.begin();
1013 auto ItEnd1 = Other.end();
1014
1015 while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
1016 // Loop through all attributes in both this and Other in sorted order. If
1017 // the attribute is only present in one of the sets, it will be set in
1018 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
1019 Attribute Attr0, Attr1;
1020 if (ItBegin1 == ItEnd1)
1021 Attr0 = *ItBegin0++;
1022 else if (ItBegin0 == ItEnd0)
1023 Attr0 = *ItBegin1++;
1024 else {
1025 int Cmp = ItBegin0->cmpKind(*ItBegin1);
1026 if (Cmp == 0) {
1027 Attr0 = *ItBegin0++;
1028 Attr1 = *ItBegin1++;
1029 } else if (Cmp < 0)
1030 Attr0 = *ItBegin0++;
1031 else
1032 Attr0 = *ItBegin1++;
1033 }
1034 assert(Attr0.isValid() && "Iteration should always yield a valid attr");
1035
1036 auto IntersectEq = [&]() {
1037 if (!Attr1.isValid())
1038 return false;
1039 if (Attr0 != Attr1)
1040 return false;
1041 Intersected.addAttribute(Attr0);
1042 return true;
1043 };
1044
1045 // Non-enum assume we must preserve. Handle early so we can unconditionally
1046 // use Kind below.
1047 if (!Attr0.hasKindAsEnum()) {
1048 if (!IntersectEq())
1049 return std::nullopt;
1050 continue;
1051 }
1052
1053 Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1054 // If we don't have both attributes, then fail if the attribute is
1055 // must-preserve or drop it otherwise.
1056 if (!Attr1.isValid()) {
1058 return std::nullopt;
1059 continue;
1060 }
1061
1062 // We have both attributes so apply the intersection rule.
1063 assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1064 "Iterator picked up two different attributes in the same iteration");
1065
1066 // Attribute we can intersect with "and"
1067 if (Attribute::intersectWithAnd(Kind)) {
1069 "Invalid attr type of intersectAnd");
1070 Intersected.addAttribute(Kind);
1071 continue;
1072 }
1073
1074 // Attribute we can intersect with "min"
1075 if (Attribute::intersectWithMin(Kind)) {
1077 "Invalid attr type of intersectMin");
1078 uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1079 Intersected.addRawIntAttr(Kind, NewVal);
1080 continue;
1081 }
1082 // Attribute we can intersect but need a custom rule for.
1084 switch (Kind) {
1085 case Attribute::Alignment:
1086 // If `byval` is present, alignment become must-preserve. This is
1087 // handled below if we have `byval`.
1088 Intersected.addAlignmentAttr(
1089 std::min(Attr0.getAlignment().valueOrOne(),
1090 Attr1.getAlignment().valueOrOne()));
1091 break;
1092 case Attribute::Memory:
1093 Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1094 Attr1.getMemoryEffects());
1095 break;
1096 case Attribute::Captures:
1097 Intersected.addCapturesAttr(Attr0.getCaptureInfo() |
1098 Attr1.getCaptureInfo());
1099 break;
1100 case Attribute::NoFPClass:
1101 Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1102 Attr1.getNoFPClass());
1103 break;
1104 case Attribute::Range: {
1105 ConstantRange Range0 = Attr0.getRange();
1106 ConstantRange Range1 = Attr1.getRange();
1107 ConstantRange NewRange = Range0.unionWith(Range1);
1108 if (!NewRange.isFullSet())
1109 Intersected.addRangeAttr(NewRange);
1110 } break;
1111 default:
1112 llvm_unreachable("Unknown attribute with custom intersection rule");
1113 }
1114 continue;
1115 }
1116
1117 // Attributes with no intersection rule. Only intersect if they are equal.
1118 // Otherwise fail.
1119 if (!IntersectEq())
1120 return std::nullopt;
1121
1122 // Special handling of `byval`. `byval` essentially turns align attr into
1123 // must-preserve
1124 if (Kind == Attribute::ByVal &&
1125 getAttribute(Attribute::Alignment) !=
1126 Other.getAttribute(Attribute::Alignment))
1127 return std::nullopt;
1128 }
1129
1130 return get(C, Intersected);
1131}
1132
1134 return SetNode ? SetNode->getNumAttributes() : 0;
1135}
1136
1138 return SetNode ? SetNode->hasAttribute(Kind) : false;
1139}
1140
1142 return SetNode ? SetNode->hasAttribute(Kind) : false;
1143}
1144
1146 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1147}
1148
1150 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1151}
1152
1154 return SetNode ? SetNode->getAlignment() : std::nullopt;
1155}
1156
1158 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
1159}
1160
1162 return SetNode ? SetNode->getDereferenceableBytes() : 0;
1163}
1164
1166 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
1167}
1168
1170 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
1171}
1172
1174 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
1175}
1176
1178 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
1179}
1180
1182 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
1183}
1184
1186 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
1187}
1188
1190 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
1191}
1192
1193std::optional<std::pair<unsigned, std::optional<unsigned>>>
1195 if (SetNode)
1196 return SetNode->getAllocSizeArgs();
1197 return std::nullopt;
1198}
1199
1201 return SetNode ? SetNode->getVScaleRangeMin() : 1;
1202}
1203
1204std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1205 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
1206}
1207
1209 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
1210}
1211
1213 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
1214}
1215
1217 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
1218}
1219
1221 return SetNode ? SetNode->getCaptureInfo() : CaptureInfo::all();
1222}
1223
1225 return SetNode ? SetNode->getNoFPClass() : fcNone;
1226}
1227
1228std::string AttributeSet::getAsString(bool InAttrGrp) const {
1229 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
1230}
1231
1233 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1235 SetNode->Profile(ID);
1236 void *Unused;
1237 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1238}
1239
1241 return SetNode ? SetNode->begin() : nullptr;
1242}
1243
1245 return SetNode ? SetNode->end() : nullptr;
1246}
1247
1248#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1250 dbgs() << "AS =\n";
1251 dbgs() << " { ";
1252 dbgs() << getAsString(true) << " }\n";
1253}
1254#endif
1255
1256//===----------------------------------------------------------------------===//
1257// AttributeSetNode Definition
1258//===----------------------------------------------------------------------===//
1259
1260AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1261 : NumAttrs(Attrs.size()) {
1262 // There's memory after the node where we can store the entries in.
1263 llvm::copy(Attrs, getTrailingObjects());
1264
1265 for (const auto &I : *this) {
1266 if (I.isStringAttribute())
1267 StringAttrs.insert({ I.getKindAsString(), I });
1268 else
1269 AvailableAttrs.addAttribute(I.getKindAsEnum());
1270 }
1271}
1272
1274 ArrayRef<Attribute> Attrs) {
1275 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1276 llvm::sort(SortedAttrs);
1277 return getSorted(C, SortedAttrs);
1278}
1279
1280AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1281 ArrayRef<Attribute> SortedAttrs) {
1282 if (SortedAttrs.empty())
1283 return nullptr;
1284
1285 // Build a key to look up the existing attributes.
1286 LLVMContextImpl *pImpl = C.pImpl;
1288
1289 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1290 for (const auto &Attr : SortedAttrs)
1291 Attr.Profile(ID);
1292
1293 void *InsertPoint;
1294 AttributeSetNode *PA =
1295 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1296
1297 // If we didn't find any existing attributes of the same shape then create a
1298 // new one and insert it.
1299 if (!PA) {
1300 // Coallocate entries after the AttributeSetNode itself.
1301 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1302 PA = new (Mem) AttributeSetNode(SortedAttrs);
1303 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1304 }
1305
1306 // Return the AttributeSetNode that we found or created.
1307 return PA;
1308}
1309
1310AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
1311 return getSorted(C, B.attrs());
1312}
1313
1315 return StringAttrs.count(Kind);
1316}
1317
1318std::optional<Attribute>
1319AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1320 // Do a quick presence check.
1321 if (!hasAttribute(Kind))
1322 return std::nullopt;
1323
1324 // Attributes in a set are sorted by enum value, followed by string
1325 // attributes. Binary search the one we want.
1326 const Attribute *I =
1327 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1328 [](Attribute A, Attribute::AttrKind Kind) {
1329 return A.getKindAsEnum() < Kind;
1330 });
1331 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1332 return *I;
1333}
1334
1336 if (auto A = findEnumAttribute(Kind))
1337 return *A;
1338 return {};
1339}
1340
1342 return StringAttrs.lookup(Kind);
1343}
1344
1346 if (auto A = findEnumAttribute(Attribute::Alignment))
1347 return A->getAlignment();
1348 return std::nullopt;
1349}
1350
1352 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1353 return A->getStackAlignment();
1354 return std::nullopt;
1355}
1356
1358 if (auto A = findEnumAttribute(Kind))
1359 return A->getValueAsType();
1360 return nullptr;
1361}
1362
1364 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1365 return A->getDereferenceableBytes();
1366 return 0;
1367}
1368
1370 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1371 return A->getDereferenceableOrNullBytes();
1372 return 0;
1373}
1374
1375std::optional<std::pair<unsigned, std::optional<unsigned>>>
1377 if (auto A = findEnumAttribute(Attribute::AllocSize))
1378 return A->getAllocSizeArgs();
1379 return std::nullopt;
1380}
1381
1383 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1384 return A->getVScaleRangeMin();
1385 return 1;
1386}
1387
1388std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1389 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1390 return A->getVScaleRangeMax();
1391 return std::nullopt;
1392}
1393
1395 if (auto A = findEnumAttribute(Attribute::UWTable))
1396 return A->getUWTableKind();
1397 return UWTableKind::None;
1398}
1399
1401 if (auto A = findEnumAttribute(Attribute::AllocKind))
1402 return A->getAllocKind();
1403 return AllocFnKind::Unknown;
1404}
1405
1407 if (auto A = findEnumAttribute(Attribute::Memory))
1408 return A->getMemoryEffects();
1409 return MemoryEffects::unknown();
1410}
1411
1413 if (auto A = findEnumAttribute(Attribute::Captures))
1414 return A->getCaptureInfo();
1415 return CaptureInfo::all();
1416}
1417
1419 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1420 return A->getNoFPClass();
1421 return fcNone;
1422}
1423
1424std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1425 std::string Str;
1426 for (iterator I = begin(), E = end(); I != E; ++I) {
1427 if (I != begin())
1428 Str += ' ';
1429 Str += I->getAsString(InAttrGrp);
1430 }
1431 return Str;
1432}
1433
1434//===----------------------------------------------------------------------===//
1435// AttributeListImpl Definition
1436//===----------------------------------------------------------------------===//
1437
1438/// Map from AttributeList index to the internal array index. Adding one happens
1439/// to work, because -1 wraps around to 0.
1440static unsigned attrIdxToArrayIdx(unsigned Index) {
1441 return Index + 1;
1442}
1443
1445 : NumAttrSets(Sets.size()) {
1446 assert(!Sets.empty() && "pointless AttributeListImpl");
1447
1448 // There's memory after the node where we can store the entries in.
1450
1451 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1452 // summary bitsets.
1453 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1454 if (!I.isStringAttribute())
1455 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1456
1457 for (const auto &Set : Sets)
1458 for (const auto &I : Set)
1459 if (!I.isStringAttribute())
1460 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1461}
1462
1466
1469 for (const auto &Set : Sets)
1470 ID.AddPointer(Set.SetNode);
1471}
1472
1474 unsigned *Index) const {
1475 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1476 return false;
1477
1478 if (Index) {
1479 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1480 if (begin()[I].hasAttribute(Kind)) {
1481 *Index = I - 1;
1482 break;
1483 }
1484 }
1485 }
1486
1487 return true;
1488}
1489
1490
1491#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1493 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1494}
1495#endif
1496
1497//===----------------------------------------------------------------------===//
1498// AttributeList Construction and Mutation Methods
1499//===----------------------------------------------------------------------===//
1500
1501AttributeList AttributeList::getImpl(LLVMContext &C,
1502 ArrayRef<AttributeSet> AttrSets) {
1503 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1504
1505 LLVMContextImpl *pImpl = C.pImpl;
1507 AttributeListImpl::Profile(ID, AttrSets);
1508
1509 void *InsertPoint;
1510 AttributeListImpl *PA =
1511 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1512
1513 // If we didn't find any existing attributes of the same shape then
1514 // create a new one and insert it.
1515 if (!PA) {
1516 // Coallocate entries after the AttributeListImpl itself.
1517 void *Mem = pImpl->Alloc.Allocate(
1519 alignof(AttributeListImpl));
1520 PA = new (Mem) AttributeListImpl(AttrSets);
1521 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1522 }
1523
1524 // Return the AttributesList that we found or created.
1525 return AttributeList(PA);
1526}
1527
1528AttributeList
1529AttributeList::get(LLVMContext &C,
1530 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1531 // If there are no attributes then return a null AttributesList pointer.
1532 if (Attrs.empty())
1533 return {};
1534
1536 "Misordered Attributes list!");
1537 assert(llvm::all_of(Attrs,
1538 [](const std::pair<unsigned, Attribute> &Pair) {
1539 return Pair.second.isValid();
1540 }) &&
1541 "Pointless attribute!");
1542
1543 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1544 // list.
1546 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1547 E = Attrs.end(); I != E; ) {
1548 unsigned Index = I->first;
1550 while (I != E && I->first == Index) {
1551 AttrVec.push_back(I->second);
1552 ++I;
1553 }
1554
1555 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1556 }
1557
1558 return get(C, AttrPairVec);
1559}
1560
1561AttributeList
1562AttributeList::get(LLVMContext &C,
1563 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1564 // If there are no attributes then return a null AttributesList pointer.
1565 if (Attrs.empty())
1566 return {};
1567
1569 "Misordered Attributes list!");
1570 assert(llvm::none_of(Attrs,
1571 [](const std::pair<unsigned, AttributeSet> &Pair) {
1572 return !Pair.second.hasAttributes();
1573 }) &&
1574 "Pointless attribute!");
1575
1576 unsigned MaxIndex = Attrs.back().first;
1577 // If the MaxIndex is FunctionIndex and there are other indices in front
1578 // of it, we need to use the largest of those to get the right size.
1579 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1580 MaxIndex = Attrs[Attrs.size() - 2].first;
1581
1582 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1583 for (const auto &Pair : Attrs)
1584 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1585
1586 return getImpl(C, AttrVec);
1587}
1588
1589AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1590 AttributeSet RetAttrs,
1591 ArrayRef<AttributeSet> ArgAttrs) {
1592 // Scan from the end to find the last argument with attributes. Most
1593 // arguments don't have attributes, so it's nice if we can have fewer unique
1594 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1595 unsigned NumSets = 0;
1596 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1597 if (ArgAttrs[I - 1].hasAttributes()) {
1598 NumSets = I + 2;
1599 break;
1600 }
1601 }
1602 if (NumSets == 0) {
1603 // Check function and return attributes if we didn't have argument
1604 // attributes.
1605 if (RetAttrs.hasAttributes())
1606 NumSets = 2;
1607 else if (FnAttrs.hasAttributes())
1608 NumSets = 1;
1609 }
1610
1611 // If all attribute sets were empty, we can use the empty attribute list.
1612 if (NumSets == 0)
1613 return {};
1614
1616 AttrSets.reserve(NumSets);
1617 // If we have any attributes, we always have function attributes.
1618 AttrSets.push_back(FnAttrs);
1619 if (NumSets > 1)
1620 AttrSets.push_back(RetAttrs);
1621 if (NumSets > 2) {
1622 // Drop the empty argument attribute sets at the end.
1623 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1624 llvm::append_range(AttrSets, ArgAttrs);
1625 }
1626
1627 return getImpl(C, AttrSets);
1628}
1629
1630AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1631 AttributeSet Attrs) {
1632 if (!Attrs.hasAttributes())
1633 return {};
1634 Index = attrIdxToArrayIdx(Index);
1635 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1636 AttrSets[Index] = Attrs;
1637 return getImpl(C, AttrSets);
1638}
1639
1640AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1641 const AttrBuilder &B) {
1642 return get(C, Index, AttributeSet::get(C, B));
1643}
1644
1645AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1648 for (const auto K : Kinds)
1649 Attrs.emplace_back(Index, Attribute::get(C, K));
1650 return get(C, Attrs);
1651}
1652
1653AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1655 ArrayRef<uint64_t> Values) {
1656 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1658 auto VI = Values.begin();
1659 for (const auto K : Kinds)
1660 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1661 return get(C, Attrs);
1662}
1663
1664AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1665 ArrayRef<StringRef> Kinds) {
1667 for (const auto &K : Kinds)
1668 Attrs.emplace_back(Index, Attribute::get(C, K));
1669 return get(C, Attrs);
1670}
1671
1672AttributeList AttributeList::get(LLVMContext &C,
1674 if (Attrs.empty())
1675 return {};
1676 if (Attrs.size() == 1)
1677 return Attrs[0];
1678
1679 unsigned MaxSize = 0;
1680 for (const auto &List : Attrs)
1681 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1682
1683 // If every list was empty, there is no point in merging the lists.
1684 if (MaxSize == 0)
1685 return {};
1686
1687 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1688 for (unsigned I = 0; I < MaxSize; ++I) {
1689 AttrBuilder CurBuilder(C);
1690 for (const auto &List : Attrs)
1691 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1692 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1693 }
1694
1695 return getImpl(C, NewAttrSets);
1696}
1697
1698AttributeList
1699AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1700 Attribute::AttrKind Kind) const {
1702 if (Attrs.hasAttribute(Kind))
1703 return *this;
1704 // TODO: Insert at correct position and avoid sort.
1705 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1706 NewAttrs.push_back(Attribute::get(C, Kind));
1707 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1708}
1709
1710AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1711 StringRef Kind,
1712 StringRef Value) const {
1713 AttrBuilder B(C);
1714 B.addAttribute(Kind, Value);
1715 return addAttributesAtIndex(C, Index, B);
1716}
1717
1718AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1719 Attribute A) const {
1720 AttrBuilder B(C);
1721 B.addAttribute(A);
1722 return addAttributesAtIndex(C, Index, B);
1723}
1724
1725AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1726 unsigned Index,
1727 AttributeSet Attrs) const {
1728 Index = attrIdxToArrayIdx(Index);
1729 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1730 if (Index >= AttrSets.size())
1731 AttrSets.resize(Index + 1);
1732 AttrSets[Index] = Attrs;
1733
1734 // Remove trailing empty attribute sets.
1735 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1736 AttrSets.pop_back();
1737 if (AttrSets.empty())
1738 return {};
1739 return AttributeList::getImpl(C, AttrSets);
1740}
1741
1742AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1743 unsigned Index,
1744 const AttrBuilder &B) const {
1745 if (!B.hasAttributes())
1746 return *this;
1747
1748 if (!pImpl)
1749 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1750
1751 AttrBuilder Merged(C, getAttributes(Index));
1752 Merged.merge(B);
1753 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1754}
1755
1756AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1757 ArrayRef<unsigned> ArgNos,
1758 Attribute A) const {
1759 assert(llvm::is_sorted(ArgNos));
1760
1761 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1762 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1763 if (MaxIndex >= AttrSets.size())
1764 AttrSets.resize(MaxIndex + 1);
1765
1766 for (unsigned ArgNo : ArgNos) {
1767 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1768 AttrBuilder B(C, AttrSets[Index]);
1769 B.addAttribute(A);
1770 AttrSets[Index] = AttributeSet::get(C, B);
1771 }
1772
1773 return getImpl(C, AttrSets);
1774}
1775
1776AttributeList
1777AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1778 Attribute::AttrKind Kind) const {
1780 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1781 if (Attrs == NewAttrs)
1782 return *this;
1783 return setAttributesAtIndex(C, Index, NewAttrs);
1784}
1785
1786AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1787 unsigned Index,
1788 StringRef Kind) const {
1790 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1791 if (Attrs == NewAttrs)
1792 return *this;
1793 return setAttributesAtIndex(C, Index, NewAttrs);
1794}
1795
1796AttributeList AttributeList::removeAttributesAtIndex(
1797 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1799 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1800 // If nothing was removed, return the original list.
1801 if (Attrs == NewAttrs)
1802 return *this;
1803 return setAttributesAtIndex(C, Index, NewAttrs);
1804}
1805
1806AttributeList
1807AttributeList::removeAttributesAtIndex(LLVMContext &C,
1808 unsigned WithoutIndex) const {
1809 if (!pImpl)
1810 return {};
1811 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1812 return *this;
1813 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1814}
1815
1816AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1817 uint64_t Bytes) const {
1818 AttrBuilder B(C);
1819 B.addDereferenceableAttr(Bytes);
1820 return addRetAttributes(C, B);
1821}
1822
1823AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1824 unsigned Index,
1825 uint64_t Bytes) const {
1826 AttrBuilder B(C);
1827 B.addDereferenceableAttr(Bytes);
1828 return addParamAttributes(C, Index, B);
1829}
1830
1831AttributeList
1832AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1833 uint64_t Bytes) const {
1834 AttrBuilder B(C);
1835 B.addDereferenceableOrNullAttr(Bytes);
1836 return addParamAttributes(C, Index, B);
1837}
1838
1839AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
1840 const ConstantRange &CR) const {
1841 AttrBuilder B(C);
1842 B.addRangeAttr(CR);
1843 return addRetAttributes(C, B);
1844}
1845
1846AttributeList AttributeList::addAllocSizeParamAttr(
1847 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1848 const std::optional<unsigned> &NumElemsArg) const {
1849 AttrBuilder B(C);
1850 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1851 return addParamAttributes(C, Index, B);
1852}
1853
1854std::optional<AttributeList>
1855AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
1856 // Trivial case, the two lists are equal.
1857 if (*this == Other)
1858 return *this;
1859
1861 auto IndexIt =
1862 index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1863 for (unsigned Idx : IndexIt) {
1864 auto IntersectedAS =
1865 getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1866 // If any index fails to intersect, fail.
1867 if (!IntersectedAS)
1868 return std::nullopt;
1869 if (!IntersectedAS->hasAttributes())
1870 continue;
1871 IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1872 }
1873
1874 llvm::sort(IntersectedAttrs, llvm::less_first());
1875 return AttributeList::get(C, IntersectedAttrs);
1876}
1877
1878//===----------------------------------------------------------------------===//
1879// AttributeList Accessor Methods
1880//===----------------------------------------------------------------------===//
1881
1882AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1883 return getAttributes(ArgNo + FirstArgIndex);
1884}
1885
1886AttributeSet AttributeList::getRetAttrs() const {
1887 return getAttributes(ReturnIndex);
1888}
1889
1890AttributeSet AttributeList::getFnAttrs() const {
1891 return getAttributes(FunctionIndex);
1892}
1893
1894bool AttributeList::hasAttributeAtIndex(unsigned Index,
1895 Attribute::AttrKind Kind) const {
1896 return getAttributes(Index).hasAttribute(Kind);
1897}
1898
1899bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1900 return getAttributes(Index).hasAttribute(Kind);
1901}
1902
1903bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1904 return getAttributes(Index).hasAttributes();
1905}
1906
1907bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1908 return pImpl && pImpl->hasFnAttribute(Kind);
1909}
1910
1911bool AttributeList::hasFnAttr(StringRef Kind) const {
1912 return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1913}
1914
1915bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1916 unsigned *Index) const {
1917 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1918}
1919
1920Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1921 Attribute::AttrKind Kind) const {
1922 return getAttributes(Index).getAttribute(Kind);
1923}
1924
1925Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1926 StringRef Kind) const {
1927 return getAttributes(Index).getAttribute(Kind);
1928}
1929
1930MaybeAlign AttributeList::getRetAlignment() const {
1931 return getAttributes(ReturnIndex).getAlignment();
1932}
1933
1934MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1935 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1936}
1937
1938MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1939 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1940}
1941
1942Type *AttributeList::getParamByValType(unsigned Index) const {
1943 return getAttributes(Index+FirstArgIndex).getByValType();
1944}
1945
1946Type *AttributeList::getParamStructRetType(unsigned Index) const {
1947 return getAttributes(Index + FirstArgIndex).getStructRetType();
1948}
1949
1950Type *AttributeList::getParamByRefType(unsigned Index) const {
1951 return getAttributes(Index + FirstArgIndex).getByRefType();
1952}
1953
1954Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1955 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1956}
1957
1958Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1959 return getAttributes(Index + FirstArgIndex).getInAllocaType();
1960}
1961
1962Type *AttributeList::getParamElementType(unsigned Index) const {
1963 return getAttributes(Index + FirstArgIndex).getElementType();
1964}
1965
1966MaybeAlign AttributeList::getFnStackAlignment() const {
1967 return getFnAttrs().getStackAlignment();
1968}
1969
1970MaybeAlign AttributeList::getRetStackAlignment() const {
1971 return getRetAttrs().getStackAlignment();
1972}
1973
1974uint64_t AttributeList::getRetDereferenceableBytes() const {
1975 return getRetAttrs().getDereferenceableBytes();
1976}
1977
1978uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1979 return getParamAttrs(Index).getDereferenceableBytes();
1980}
1981
1982uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1983 return getRetAttrs().getDereferenceableOrNullBytes();
1984}
1985
1986uint64_t
1987AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1988 return getParamAttrs(Index).getDereferenceableOrNullBytes();
1989}
1990
1991std::optional<ConstantRange>
1992AttributeList::getParamRange(unsigned ArgNo) const {
1993 auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
1994 if (RangeAttr.isValid())
1995 return RangeAttr.getRange();
1996 return std::nullopt;
1997}
1998
1999FPClassTest AttributeList::getRetNoFPClass() const {
2000 return getRetAttrs().getNoFPClass();
2001}
2002
2003FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {
2004 return getParamAttrs(Index).getNoFPClass();
2005}
2006
2007UWTableKind AttributeList::getUWTableKind() const {
2008 return getFnAttrs().getUWTableKind();
2009}
2010
2011AllocFnKind AttributeList::getAllocKind() const {
2012 return getFnAttrs().getAllocKind();
2013}
2014
2015MemoryEffects AttributeList::getMemoryEffects() const {
2016 return getFnAttrs().getMemoryEffects();
2017}
2018
2019std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
2020 return getAttributes(Index).getAsString(InAttrGrp);
2021}
2022
2023AttributeSet AttributeList::getAttributes(unsigned Index) const {
2024 Index = attrIdxToArrayIdx(Index);
2025 if (!pImpl || Index >= getNumAttrSets())
2026 return {};
2027 return pImpl->begin()[Index];
2028}
2029
2030bool AttributeList::hasParentContext(LLVMContext &C) const {
2031 assert(!isEmpty() && "an empty attribute list has no parent context");
2033 pImpl->Profile(ID);
2034 void *Unused;
2035 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
2036}
2037
2038AttributeList::iterator AttributeList::begin() const {
2039 return pImpl ? pImpl->begin() : nullptr;
2040}
2041
2042AttributeList::iterator AttributeList::end() const {
2043 return pImpl ? pImpl->end() : nullptr;
2044}
2045
2046//===----------------------------------------------------------------------===//
2047// AttributeList Introspection Methods
2048//===----------------------------------------------------------------------===//
2049
2050unsigned AttributeList::getNumAttrSets() const {
2051 return pImpl ? pImpl->NumAttrSets : 0;
2052}
2053
2054void AttributeList::print(raw_ostream &O) const {
2055 O << "AttributeList[\n";
2056
2057 for (unsigned i : indexes()) {
2058 if (!getAttributes(i).hasAttributes())
2059 continue;
2060 O << " { ";
2061 switch (i) {
2062 case AttrIndex::ReturnIndex:
2063 O << "return";
2064 break;
2065 case AttrIndex::FunctionIndex:
2066 O << "function";
2067 break;
2068 default:
2069 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2070 }
2071 O << " => " << getAsString(i) << " }\n";
2072 }
2073
2074 O << "]\n";
2075}
2076
2077#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2078LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
2079#endif
2080
2081//===----------------------------------------------------------------------===//
2082// AttrBuilder Method Implementations
2083//===----------------------------------------------------------------------===//
2084
2085AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
2086 append_range(Attrs, AS);
2087 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2088}
2089
2090void AttrBuilder::clear() { Attrs.clear(); }
2091
2092/// Attribute comparator that only compares attribute keys. Enum attributes are
2093/// sorted before string attributes.
2095 bool operator()(Attribute A0, Attribute A1) const {
2096 bool A0IsString = A0.isStringAttribute();
2097 bool A1IsString = A1.isStringAttribute();
2098 if (A0IsString) {
2099 if (A1IsString)
2100 return A0.getKindAsString() < A1.getKindAsString();
2101 else
2102 return false;
2103 }
2104 if (A1IsString)
2105 return true;
2106 return A0.getKindAsEnum() < A1.getKindAsEnum();
2107 }
2109 if (A0.isStringAttribute())
2110 return false;
2111 return A0.getKindAsEnum() < Kind;
2112 }
2113 bool operator()(Attribute A0, StringRef Kind) const {
2114 if (A0.isStringAttribute())
2115 return A0.getKindAsString() < Kind;
2116 return true;
2117 }
2118};
2119
2120template <typename K>
2122 Attribute Attr) {
2123 auto It = lower_bound(Attrs, Kind, AttributeComparator());
2124 if (It != Attrs.end() && It->hasAttribute(Kind))
2125 std::swap(*It, Attr);
2126 else
2127 Attrs.insert(It, Attr);
2128}
2129
2130AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
2131 if (Attr.isStringAttribute())
2132 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2133 else
2134 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2135 return *this;
2136}
2137
2138AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
2139 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2140 return *this;
2141}
2142
2143AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
2144 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2145 return *this;
2146}
2147
2148AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
2149 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2150 auto It = lower_bound(Attrs, Val, AttributeComparator());
2151 if (It != Attrs.end() && It->hasAttribute(Val))
2152 Attrs.erase(It);
2153 return *this;
2154}
2155
2156AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
2157 auto It = lower_bound(Attrs, A, AttributeComparator());
2158 if (It != Attrs.end() && It->hasAttribute(A))
2159 Attrs.erase(It);
2160 return *this;
2161}
2162
2163std::optional<uint64_t>
2164AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
2165 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2166 Attribute A = getAttribute(Kind);
2167 if (A.isValid())
2168 return A.getValueAsInt();
2169 return std::nullopt;
2170}
2171
2172AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
2173 uint64_t Value) {
2174 return addAttribute(Attribute::get(Ctx, Kind, Value));
2175}
2176
2177std::optional<std::pair<unsigned, std::optional<unsigned>>>
2178AttrBuilder::getAllocSizeArgs() const {
2179 Attribute A = getAttribute(Attribute::AllocSize);
2180 if (A.isValid())
2181 return A.getAllocSizeArgs();
2182 return std::nullopt;
2183}
2184
2185AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
2186 if (!Align)
2187 return *this;
2188
2189 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2190 return addRawIntAttr(Attribute::Alignment, Align->value());
2191}
2192
2193AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
2194 // Default alignment, allow the target to define how to align it.
2195 if (!Align)
2196 return *this;
2197
2198 assert(*Align <= 0x100 && "Alignment too large.");
2199 return addRawIntAttr(Attribute::StackAlignment, Align->value());
2200}
2201
2202AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
2203 if (Bytes == 0) return *this;
2204
2205 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2206}
2207
2208AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
2209 if (Bytes == 0)
2210 return *this;
2211
2212 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2213}
2214
2215AttrBuilder &
2216AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
2217 const std::optional<unsigned> &NumElems) {
2218 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2219}
2220
2221AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
2222 // (0, 0) is our "not present" value, so we need to check for it here.
2223 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2224 return addRawIntAttr(Attribute::AllocSize, RawArgs);
2225}
2226
2227AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
2228 std::optional<unsigned> MaxValue) {
2229 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2230}
2231
2232AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
2233 // (0, 0) is not present hence ignore this case
2234 if (RawArgs == 0)
2235 return *this;
2236
2237 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2238}
2239
2240AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
2241 if (Kind == UWTableKind::None)
2242 return *this;
2243 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2244}
2245
2246AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
2247 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2248}
2249
2250AttrBuilder &AttrBuilder::addCapturesAttr(CaptureInfo CI) {
2251 return addRawIntAttr(Attribute::Captures, CI.toIntValue());
2252}
2253
2254AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
2255 if (Mask == fcNone)
2256 return *this;
2257
2258 return addRawIntAttr(Attribute::NoFPClass, Mask);
2259}
2260
2261AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
2262 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2263}
2264
2265Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
2266 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2267 Attribute A = getAttribute(Kind);
2268 return A.isValid() ? A.getValueAsType() : nullptr;
2269}
2270
2271AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
2272 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2273}
2274
2275AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
2276 return addTypeAttr(Attribute::ByVal, Ty);
2277}
2278
2279AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
2280 return addTypeAttr(Attribute::StructRet, Ty);
2281}
2282
2283AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
2284 return addTypeAttr(Attribute::ByRef, Ty);
2285}
2286
2287AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
2288 return addTypeAttr(Attribute::Preallocated, Ty);
2289}
2290
2291AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
2292 return addTypeAttr(Attribute::InAlloca, Ty);
2293}
2294
2295AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,
2296 const ConstantRange &CR) {
2297 if (CR.isFullSet())
2298 return *this;
2299
2300 return addAttribute(Attribute::get(Ctx, Kind, CR));
2301}
2302
2303AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
2304 return addConstantRangeAttr(Attribute::Range, CR);
2305}
2306
2307AttrBuilder &
2308AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
2310 return addAttribute(Attribute::get(Ctx, Kind, Val));
2311}
2312
2313AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
2314 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2315}
2316
2317AttrBuilder &AttrBuilder::addFromEquivalentMetadata(const Instruction &I) {
2318 if (I.hasMetadata(LLVMContext::MD_nonnull))
2319 addAttribute(Attribute::NonNull);
2320
2321 if (I.hasMetadata(LLVMContext::MD_noundef))
2322 addAttribute(Attribute::NoUndef);
2323
2324 if (const MDNode *Align = I.getMetadata(LLVMContext::MD_align)) {
2325 ConstantInt *CI = mdconst::extract<ConstantInt>(Align->getOperand(0));
2326 addAlignmentAttr(CI->getZExtValue());
2327 }
2328
2329 if (const MDNode *Dereferenceable =
2330 I.getMetadata(LLVMContext::MD_dereferenceable)) {
2331 ConstantInt *CI =
2332 mdconst::extract<ConstantInt>(Dereferenceable->getOperand(0));
2333 addDereferenceableAttr(CI->getZExtValue());
2334 }
2335
2336 if (const MDNode *DereferenceableOrNull =
2337 I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) {
2338 ConstantInt *CI =
2339 mdconst::extract<ConstantInt>(DereferenceableOrNull->getOperand(0));
2340 addDereferenceableAttr(CI->getZExtValue());
2341 }
2342
2343 if (const MDNode *Range = I.getMetadata(LLVMContext::MD_range))
2344 addRangeAttr(getConstantRangeFromMetadata(*Range));
2345
2346 return *this;
2347}
2348
2349AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
2350 // TODO: Could make this O(n) as we're merging two sorted lists.
2351 for (const auto &I : B.attrs())
2352 addAttribute(I);
2353
2354 return *this;
2355}
2356
2357AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
2358 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2359 return *this;
2360}
2361
2362bool AttrBuilder::overlaps(const AttributeMask &AM) const {
2363 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2364}
2365
2366Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
2367 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2368 auto It = lower_bound(Attrs, A, AttributeComparator());
2369 if (It != Attrs.end() && It->hasAttribute(A))
2370 return *It;
2371 return {};
2372}
2373
2374Attribute AttrBuilder::getAttribute(StringRef A) const {
2375 auto It = lower_bound(Attrs, A, AttributeComparator());
2376 if (It != Attrs.end() && It->hasAttribute(A))
2377 return *It;
2378 return {};
2379}
2380
2381std::optional<ConstantRange> AttrBuilder::getRange() const {
2382 const Attribute RangeAttr = getAttribute(Attribute::Range);
2383 if (RangeAttr.isValid())
2384 return RangeAttr.getRange();
2385 return std::nullopt;
2386}
2387
2388bool AttrBuilder::contains(Attribute::AttrKind A) const {
2389 return getAttribute(A).isValid();
2390}
2391
2392bool AttrBuilder::contains(StringRef A) const {
2393 return getAttribute(A).isValid();
2394}
2395
2396bool AttrBuilder::operator==(const AttrBuilder &B) const {
2397 return Attrs == B.Attrs;
2398}
2399
2400//===----------------------------------------------------------------------===//
2401// AttributeFuncs Function Defintions
2402//===----------------------------------------------------------------------===//
2403
2404/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2405/// follows the same type rules as FPMathOperator.
2406bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2408}
2409
2410/// Which attributes cannot be applied to a type.
2411AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
2412 AttributeSafetyKind ASK) {
2413 AttributeMask Incompatible;
2414
2415 if (!Ty->isIntegerTy()) {
2416 // Attributes that only apply to integers.
2417 if (ASK & ASK_SAFE_TO_DROP)
2418 Incompatible.addAttribute(Attribute::AllocAlign);
2419 if (ASK & ASK_UNSAFE_TO_DROP)
2420 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2421 }
2422
2423 if (!Ty->isIntOrIntVectorTy()) {
2424 // Attributes that only apply to integers or vector of integers.
2425 if (ASK & ASK_SAFE_TO_DROP)
2426 Incompatible.addAttribute(Attribute::Range);
2427 } else {
2428 Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2429 if (RangeAttr.isValid() &&
2430 RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2431 Incompatible.addAttribute(Attribute::Range);
2432 }
2433
2434 if (!Ty->isPointerTy()) {
2435 // Attributes that only apply to pointers.
2436 if (ASK & ASK_SAFE_TO_DROP)
2437 Incompatible.addAttribute(Attribute::NoAlias)
2438 .addAttribute(Attribute::NonNull)
2439 .addAttribute(Attribute::ReadNone)
2440 .addAttribute(Attribute::ReadOnly)
2441 .addAttribute(Attribute::Dereferenceable)
2442 .addAttribute(Attribute::DereferenceableOrNull)
2443 .addAttribute(Attribute::Writable)
2444 .addAttribute(Attribute::DeadOnUnwind)
2445 .addAttribute(Attribute::Initializes)
2446 .addAttribute(Attribute::Captures)
2447 .addAttribute(Attribute::DeadOnReturn);
2448 if (ASK & ASK_UNSAFE_TO_DROP)
2449 Incompatible.addAttribute(Attribute::Nest)
2450 .addAttribute(Attribute::SwiftError)
2451 .addAttribute(Attribute::Preallocated)
2452 .addAttribute(Attribute::InAlloca)
2453 .addAttribute(Attribute::ByVal)
2454 .addAttribute(Attribute::StructRet)
2455 .addAttribute(Attribute::ByRef)
2456 .addAttribute(Attribute::ElementType)
2457 .addAttribute(Attribute::AllocatedPointer);
2458 }
2459
2460 // Attributes that only apply to pointers or vectors of pointers.
2461 if (!Ty->isPtrOrPtrVectorTy()) {
2462 if (ASK & ASK_SAFE_TO_DROP)
2463 Incompatible.addAttribute(Attribute::Alignment);
2464 }
2465
2466 if (ASK & ASK_SAFE_TO_DROP) {
2467 if (!isNoFPClassCompatibleType(Ty))
2468 Incompatible.addAttribute(Attribute::NoFPClass);
2469 }
2470
2471 // Some attributes can apply to all "values" but there are no `void` values.
2472 if (Ty->isVoidTy()) {
2473 if (ASK & ASK_SAFE_TO_DROP)
2474 Incompatible.addAttribute(Attribute::NoUndef);
2475 }
2476
2477 return Incompatible;
2478}
2479
2480AttributeMask AttributeFuncs::getUBImplyingAttributes() {
2481 AttributeMask AM;
2482 AM.addAttribute(Attribute::NoUndef);
2483 AM.addAttribute(Attribute::Dereferenceable);
2484 AM.addAttribute(Attribute::DereferenceableOrNull);
2485 return AM;
2486}
2487
2488/// Callees with dynamic denormal modes are compatible with any caller mode.
2489static bool denormModeCompatible(DenormalMode CallerMode,
2490 DenormalMode CalleeMode) {
2491 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2492 return true;
2493
2494 // If they don't exactly match, it's OK if the mismatched component is
2495 // dynamic.
2496 if (CalleeMode.Input == CallerMode.Input &&
2497 CalleeMode.Output == DenormalMode::Dynamic)
2498 return true;
2499
2500 if (CalleeMode.Output == CallerMode.Output &&
2501 CalleeMode.Input == DenormalMode::Dynamic)
2502 return true;
2503 return false;
2504}
2505
2506static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2507 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2508 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2509
2510 if (denormModeCompatible(CallerMode, CalleeMode)) {
2511 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2512 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2513 if (CallerModeF32 == DenormalMode::getInvalid())
2514 CallerModeF32 = CallerMode;
2515 if (CalleeModeF32 == DenormalMode::getInvalid())
2516 CalleeModeF32 = CalleeMode;
2517 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2518 }
2519
2520 return false;
2521}
2522
2523static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2524 // Do not inline strictfp function into non-strictfp one. It would require
2525 // conversion of all FP operations in host function to constrained intrinsics.
2526 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2527 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2528}
2529
2530template<typename AttrClass>
2531static bool isEqual(const Function &Caller, const Function &Callee) {
2532 return Caller.getFnAttribute(AttrClass::getKind()) ==
2533 Callee.getFnAttribute(AttrClass::getKind());
2534}
2535
2536static bool isEqual(const Function &Caller, const Function &Callee,
2537 const StringRef &AttrName) {
2538 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2539}
2540
2541/// Compute the logical AND of the attributes of the caller and the
2542/// callee.
2543///
2544/// This function sets the caller's attribute to false if the callee's attribute
2545/// is false.
2546template<typename AttrClass>
2547static void setAND(Function &Caller, const Function &Callee) {
2548 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2549 !AttrClass::isSet(Callee, AttrClass::getKind()))
2550 AttrClass::set(Caller, AttrClass::getKind(), false);
2551}
2552
2553/// Compute the logical OR of the attributes of the caller and the
2554/// callee.
2555///
2556/// This function sets the caller's attribute to true if the callee's attribute
2557/// is true.
2558template<typename AttrClass>
2559static void setOR(Function &Caller, const Function &Callee) {
2560 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2561 AttrClass::isSet(Callee, AttrClass::getKind()))
2562 AttrClass::set(Caller, AttrClass::getKind(), true);
2563}
2564
2565/// If the inlined function had a higher stack protection level than the
2566/// calling function, then bump up the caller's stack protection level.
2567static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2568 // If the calling function has *no* stack protection level (e.g. it was built
2569 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2570 // change it as that could change the program's semantics.
2571 if (!Caller.hasStackProtectorFnAttr())
2572 return;
2573
2574 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2575 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2576 // clutter to the IR.
2577 AttributeMask OldSSPAttr;
2578 OldSSPAttr.addAttribute(Attribute::StackProtect)
2579 .addAttribute(Attribute::StackProtectStrong)
2580 .addAttribute(Attribute::StackProtectReq);
2581
2582 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2583 Caller.removeFnAttrs(OldSSPAttr);
2584 Caller.addFnAttr(Attribute::StackProtectReq);
2585 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2586 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2587 Caller.removeFnAttrs(OldSSPAttr);
2588 Caller.addFnAttr(Attribute::StackProtectStrong);
2589 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2590 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2591 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2592 Caller.addFnAttr(Attribute::StackProtect);
2593}
2594
2595/// If the inlined function required stack probes, then ensure that
2596/// the calling function has those too.
2597static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2598 if (!Caller.hasFnAttribute("probe-stack") &&
2599 Callee.hasFnAttribute("probe-stack")) {
2600 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2601 }
2602}
2603
2604/// If the inlined function defines the size of guard region
2605/// on the stack, then ensure that the calling function defines a guard region
2606/// that is no larger.
2607static void
2609 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2610 if (CalleeAttr.isValid()) {
2611 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2612 if (CallerAttr.isValid()) {
2613 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2614 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2615 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2616
2617 if (CallerStackProbeSize > CalleeStackProbeSize) {
2618 Caller.addFnAttr(CalleeAttr);
2619 }
2620 } else {
2621 Caller.addFnAttr(CalleeAttr);
2622 }
2623 }
2624}
2625
2626/// If the inlined function defines a min legal vector width, then ensure
2627/// the calling function has the same or larger min legal vector width. If the
2628/// caller has the attribute, but the callee doesn't, we need to remove the
2629/// attribute from the caller since we can't make any guarantees about the
2630/// caller's requirements.
2631/// This function is called after the inlining decision has been made so we have
2632/// to merge the attribute this way. Heuristics that would use
2633/// min-legal-vector-width to determine inline compatibility would need to be
2634/// handled as part of inline cost analysis.
2635static void
2637 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2638 if (CallerAttr.isValid()) {
2639 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2640 if (CalleeAttr.isValid()) {
2641 uint64_t CallerVectorWidth, CalleeVectorWidth;
2642 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2643 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2644 if (CallerVectorWidth < CalleeVectorWidth)
2645 Caller.addFnAttr(CalleeAttr);
2646 } else {
2647 // If the callee doesn't have the attribute then we don't know anything
2648 // and must drop the attribute from the caller.
2649 Caller.removeFnAttr("min-legal-vector-width");
2650 }
2651 }
2652}
2653
2654/// If the inlined function has null_pointer_is_valid attribute,
2655/// set this attribute in the caller post inlining.
2656static void
2658 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2659 Caller.addFnAttr(Attribute::NullPointerIsValid);
2660 }
2661}
2662
2663struct EnumAttr {
2664 static bool isSet(const Function &Fn,
2665 Attribute::AttrKind Kind) {
2666 return Fn.hasFnAttribute(Kind);
2667 }
2668
2669 static void set(Function &Fn,
2670 Attribute::AttrKind Kind, bool Val) {
2671 if (Val)
2672 Fn.addFnAttr(Kind);
2673 else
2674 Fn.removeFnAttr(Kind);
2675 }
2676};
2677
2679 static bool isSet(const Function &Fn,
2680 StringRef Kind) {
2681 auto A = Fn.getFnAttribute(Kind);
2682 return A.getValueAsString() == "true";
2683 }
2684
2685 static void set(Function &Fn,
2686 StringRef Kind, bool Val) {
2687 Fn.addFnAttr(Kind, Val ? "true" : "false");
2688 }
2689};
2690
2691#define GET_ATTR_NAMES
2692#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2693 struct ENUM_NAME##Attr : EnumAttr { \
2694 static enum Attribute::AttrKind getKind() { \
2695 return llvm::Attribute::ENUM_NAME; \
2696 } \
2697 };
2698#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2699 struct ENUM_NAME##Attr : StrBoolAttr { \
2700 static StringRef getKind() { return #DISPLAY_NAME; } \
2701 };
2702#include "llvm/IR/Attributes.inc"
2703
2704#define GET_ATTR_COMPAT_FUNC
2705#include "llvm/IR/Attributes.inc"
2706
2707bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2708 const Function &Callee) {
2709 return hasCompatibleFnAttrs(Caller, Callee);
2710}
2711
2712bool AttributeFuncs::areOutlineCompatible(const Function &A,
2713 const Function &B) {
2714 return hasCompatibleFnAttrs(A, B);
2715}
2716
2717void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2718 const Function &Callee) {
2719 mergeFnAttrs(Caller, Callee);
2720}
2721
2722void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2723 const Function &ToMerge) {
2724
2725 // We merge functions so that they meet the most general case.
2726 // For example, if the NoNansFPMathAttr is set in one function, but not in
2727 // the other, in the merged function we can say that the NoNansFPMathAttr
2728 // is not set.
2729 // However if we have the SpeculativeLoadHardeningAttr set true in one
2730 // function, but not the other, we make sure that the function retains
2731 // that aspect in the merged function.
2732 mergeFnAttrs(Base, ToMerge);
2733}
2734
2735void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2736 uint64_t Width) {
2737 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2738 if (Attr.isValid()) {
2739 uint64_t OldWidth;
2740 Attr.getValueAsString().getAsInteger(0, OldWidth);
2741 if (Width > OldWidth)
2742 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2743 }
2744}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines various helper methods and classes used by LLVMContextImpl for creating and managin...
static void addAttributeImpl(SmallVectorImpl< Attribute > &Attrs, K Kind, Attribute Attr)
static void setAND(Function &Caller, const Function &Callee)
Compute the logical AND of the attributes of the caller and the callee.
static void adjustCallerStackProbes(Function &Caller, const Function &Callee)
If the inlined function required stack probes, then ensure that the calling function has those too.
static std::pair< unsigned, std::optional< unsigned > > unpackVScaleRangeArgs(uint64_t Value)
static void adjustMinLegalVectorWidth(Function &Caller, const Function &Callee)
If the inlined function defines a min legal vector width, then ensure the calling function has the sa...
AttributeProperty
@ RetAttr
@ IntersectPreserve
@ IntersectMin
@ IntersectCustom
@ ParamAttr
@ FnAttr
@ IntersectPropertyMask
@ IntersectAnd
static void adjustCallerStackProbeSize(Function &Caller, const Function &Callee)
If the inlined function defines the size of guard region on the stack, then ensure that the calling f...
static void adjustCallerSSPLevel(Function &Caller, const Function &Callee)
If the inlined function had a higher stack protection level than the calling function,...
static bool checkStrictFP(const Function &Caller, const Function &Callee)
static uint64_t packAllocSizeArgs(unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
static uint64_t packVScaleRangeArgs(unsigned MinValue, std::optional< unsigned > MaxValue)
static bool hasIntersectProperty(Attribute::AttrKind Kind, AttributeProperty Prop)
static unsigned attrIdxToArrayIdx(unsigned Index)
Map from AttributeList index to the internal array index.
static bool denormModeCompatible(DenormalMode CallerMode, DenormalMode CalleeMode)
Callees with dynamic denormal modes are compatible with any caller mode.
static void adjustNullPointerValidAttr(Function &Caller, const Function &Callee)
If the inlined function has null_pointer_is_valid attribute, set this attribute in the caller post in...
static const unsigned AllocSizeNumElemsNotPresent
static std::pair< unsigned, std::optional< unsigned > > unpackAllocSizeArgs(uint64_t Num)
static bool checkDenormMode(const Function &Caller, const Function &Callee)
static unsigned getAttributeProperties(Attribute::AttrKind Kind)
static void setOR(Function &Caller, const Function &Callee)
Compute the logical OR of the attributes of the caller and the callee.
static bool hasAttributeProperty(Attribute::AttrKind Kind, AttributeProperty Prop)
static const char * getModRefStr(ModRefInfo MR)
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:638
This file defines a hash set that can be used to remove duplication of nodes in a graph.
#define I(x, y, z)
Definition MD5.cpp:57
Load MIR Sample Profile
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
LLVM_ABI void Profile(FoldingSetNodeID &id) const
Used to insert APInt objects, or objects that contain APInt objects, into FoldingSets.
Definition APInt.cpp:156
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & back() const
back - Get the last element.
Definition ArrayRef.h:151
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:219
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
iterator begin() const
Definition ArrayRef.h:130
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:137
This class represents a single, uniqued attribute.
int cmp(const AttributeImpl &AI, bool KindOnly) const
Used to sort attributes.
bool isConstantRangeAttribute() const
bool hasAttribute(Attribute::AttrKind A) const
Type * getValueAsType() const
Attribute::AttrKind getKindAsEnum() const
bool operator<(const AttributeImpl &AI) const
Used when sorting the attributes.
uint64_t getValueAsInt() const
bool isIntAttribute() const
bool isTypeAttribute() const
AttributeImpl(AttrEntryKind KindID)
bool getValueAsBool() const
StringRef getKindAsString() const
StringRef getValueAsString() const
bool isEnumAttribute() const
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
bool isConstantRangeListAttribute() const
bool isStringAttribute() const
const ConstantRange & getValueAsConstantRange() const
This class represents a set of attributes that apply to the function, return type,...
bool hasAttrSomewhere(Attribute::AttrKind Kind, unsigned *Index=nullptr) const
Return true if the specified attribute is set for at least one parameter or for the return value.
iterator begin() const
void Profile(FoldingSetNodeID &ID) const
AttributeListImpl(ArrayRef< AttributeSet > Sets)
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
This class represents a group of attributes that apply to one element: function, return type,...
MaybeAlign getStackAlignment() const
uint64_t getDereferenceableOrNullBytes() const
std::optional< unsigned > getVScaleRangeMax() const
bool hasAttribute(Attribute::AttrKind Kind) const
Type * getAttributeType(Attribute::AttrKind Kind) const
AllocFnKind getAllocKind() const
CaptureInfo getCaptureInfo() const
unsigned getVScaleRangeMin() const
MaybeAlign getAlignment() const
MemoryEffects getMemoryEffects() const
iterator begin() const
UWTableKind getUWTableKind() const
std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
iterator end() const
const Attribute * iterator
uint64_t getDereferenceableBytes() const
std::string getAsString(bool InAttrGrp) const
static AttributeSetNode * get(LLVMContext &C, const AttrBuilder &B)
FPClassTest getNoFPClass() const
Attribute getAttribute(Attribute::AttrKind Kind) const
This class holds the attributes for a particular argument, parameter, function, or return value.
Definition Attributes.h:361
LLVM_ABI AllocFnKind getAllocKind() const
bool hasAttributes() const
Return true if attributes exists in this set.
Definition Attributes.h:431
const Attribute * iterator
Definition Attributes.h:469
LLVM_ABI AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Remove the specified attribute from this set.
LLVM_ABI Type * getInAllocaType() const
LLVM_ABI Type * getByValType() const
LLVM_ABI AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
LLVM_ABI std::optional< AttributeSet > intersectWith(LLVMContext &C, AttributeSet Other) const
Try to intersect this AttributeSet with Other.
LLVM_ABI Type * getStructRetType() const
LLVM_ABI std::string getAsString(bool InAttrGrp=false) const
LLVM_ABI unsigned getVScaleRangeMin() const
LLVM_ABI std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
LLVM_ABI UWTableKind getUWTableKind() const
LLVM_ABI bool hasParentContext(LLVMContext &C) const
Return true if this attribute set belongs to the LLVMContext.
LLVM_ABI iterator begin() const
LLVM_ABI iterator end() const
LLVM_ABI AttributeSet removeAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const
Remove the specified attributes from this set.
LLVM_ABI std::optional< unsigned > getVScaleRangeMax() const
LLVM_ABI MaybeAlign getStackAlignment() const
LLVM_ABI Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
LLVM_ABI Type * getPreallocatedType() const
LLVM_ABI uint64_t getDereferenceableBytes() const
LLVM_ABI MaybeAlign getAlignment() const
LLVM_ABI FPClassTest getNoFPClass() const
LLVM_ABI Type * getElementType() const
LLVM_ABI Type * getByRefType() const
LLVM_ABI CaptureInfo getCaptureInfo() const
AttributeSet()=default
AttributeSet is a trivially copyable value type.
static LLVM_ABI AttributeSet get(LLVMContext &C, const AttrBuilder &B)
LLVM_ABI uint64_t getDereferenceableOrNullBytes() const
LLVM_ABI unsigned getNumAttributes() const
Return the number of attributes in this set.
LLVM_ABI AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:69
LLVM_ABI bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
static LLVM_ABI Attribute getWithStructRetType(LLVMContext &Context, Type *Ty)
static LLVM_ABI Attribute::AttrKind getAttrKindFromName(StringRef AttrName)
LLVM_ABI bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
static LLVM_ABI Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment)
LLVM_ABI const ConstantRange & getRange() const
Returns the value of the range attribute.
static LLVM_ABI bool intersectWithCustom(AttrKind Kind)
LLVM_ABI bool isIntAttribute() const
Return true if the attribute is an integer attribute.
static LLVM_ABI Attribute getWithByRefType(LLVMContext &Context, Type *Ty)
LLVM_ABI std::optional< unsigned > getVScaleRangeMax() const
Returns the maximum value for the vscale_range attribute or std::nullopt when unknown.
LLVM_ABI uint64_t getValueAsInt() const
Return the attribute's value as an integer.
LLVM_ABI unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
LLVM_ABI AllocFnKind getAllocKind() const
LLVM_ABI bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
static LLVM_ABI Attribute getWithAllocKind(LLVMContext &Context, AllocFnKind Kind)
LLVM_ABI StringRef getKindAsString() const
Return the attribute's kind as a string.
static LLVM_ABI Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty)
static LLVM_ABI bool intersectWithMin(AttrKind Kind)
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI bool canUseAsRetAttr(AttrKind Kind)
static bool isTypeAttrKind(AttrKind Kind)
Definition Attributes.h:107
LLVM_ABI std::string getAsString(bool InAttrGrp=false) const
The Attribute is converted to a string of equivalent mnemonic.
LLVM_ABI uint64_t getDereferenceableOrNullBytes() const
Returns the number of dereferenceable_or_null bytes from the dereferenceable_or_null attribute.
static LLVM_ABI Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
LLVM_ABI std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
static LLVM_ABI Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind)
LLVM_ABI FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
static LLVM_ABI Attribute getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
Attribute()=default
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
LLVM_ABI ArrayRef< ConstantRange > getInitializes() const
Returns the value of the initializes attribute.
LLVM_ABI const ConstantRange & getValueAsConstantRange() const
Return the attribute's value as a ConstantRange.
LLVM_ABI uint64_t getDereferenceableBytes() const
Returns the number of dereferenceable bytes from the dereferenceable attribute.
static LLVM_ABI Attribute getWithVScaleRangeArgs(LLVMContext &Context, unsigned MinValue, unsigned MaxValue)
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
LLVM_ABI void Profile(FoldingSetNodeID &ID) const
LLVM_ABI UWTableKind getUWTableKind() const
static LLVM_ABI Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, uint64_t Bytes)
LLVM_ABI ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
static LLVM_ABI bool isExistingAttribute(StringRef Name)
Return true if the provided string matches the IR name of an attribute.
bool hasKindAsEnum() const
Returns true if the attribute's kind can be represented as an enum (Enum, Integer,...
Definition Attributes.h:233
static LLVM_ABI StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind)
static LLVM_ABI bool canUseAsFnAttr(AttrKind Kind)
static LLVM_ABI bool intersectWithAnd(AttrKind Kind)
static LLVM_ABI Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition Attributes.h:88
@ None
No attributes have been set.
Definition Attributes.h:90
@ EndAttrKinds
Sentinel value useful for loops.
Definition Attributes.h:93
static bool isConstantRangeAttrKind(AttrKind Kind)
Definition Attributes.h:110
LLVM_ABI bool hasParentContext(LLVMContext &C) const
Return true if this attribute belongs to the LLVMContext.
LLVM_ABI bool isTypeAttribute() const
Return true if the attribute is a type attribute.
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
static LLVM_ABI Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty)
static bool isIntAttrKind(AttrKind Kind)
Definition Attributes.h:104
static bool isConstantRangeListAttrKind(AttrKind Kind)
Definition Attributes.h:113
LLVM_ABI bool isConstantRangeListAttribute() const
Return true if the attribute is a ConstantRangeList attribute.
static LLVM_ABI Attribute getWithByValType(LLVMContext &Context, Type *Ty)
LLVM_ABI bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
static bool isEnumAttrKind(AttrKind Kind)
Definition Attributes.h:101
static LLVM_ABI Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
static LLVM_ABI bool canUseAsParamAttr(AttrKind Kind)
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:223
LLVM_ABI MaybeAlign getStackAlignment() const
Returns the stack alignment field of an attribute as a byte alignment value.
LLVM_ABI MaybeAlign getAlignment() const
Returns the alignment field of an attribute as a byte alignment value.
LLVM_ABI CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
static LLVM_ABI bool intersectMustPreserve(AttrKind Kind)
LLVM_ABI int cmpKind(Attribute A) const
Used to sort attribute by kind.
LLVM_ABI bool operator<(Attribute A) const
Less-than operator. Useful for sorting the attributes list.
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM_ABI Type * getValueAsType() const
Return the attribute's value as a Type.
Represents which components of the pointer may be captured in which location.
Definition ModRef.h:359
static CaptureInfo createFromIntValue(uint32_t Data)
Definition ModRef.h:430
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
Definition ModRef.h:375
uint32_t toIntValue() const
Convert CaptureInfo into an encoded integer value (used by captures attribute).
Definition ModRef.h:437
This is the shared class of boolean and integer constants.
Definition Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:163
static size_t totalSizeToAlloc(ArrayRef< ConstantRange > Val)
This class represents a list of constant ranges.
ArrayRef< ConstantRange > rangesRef() const
LLVM_ABI void print(raw_ostream &OS) const
Print out the ranges to a stream.
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI ConstantRange unionWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the union of this range with another range.
uint32_t getBitWidth() const
Get the bit width of this ConstantRange.
A set of classes that contain the value of the attribute object.
static bool isSupportedFloatingPointType(Type *Ty)
Returns true if Ty is a supported floating-point type for phi, select, or call FPMathOperators.
Definition Operator.h:344
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:330
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition Function.cpp:640
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:765
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition Function.cpp:688
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:730
FoldingSet< AttributeSetNode > AttrsSetNodes
FoldingSet< AttributeListImpl > AttrsLists
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
Metadata node.
Definition Metadata.h:1078
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:193
static MemoryEffectsBase createFromIntValue(uint32_t Data)
Definition ModRef.h:182
uint32_t toIntValue() const
Convert MemoryEffectsBase into an encoded integer value (used by memory attribute).
Definition ModRef.h:188
static MemoryEffectsBase unknown()
Definition ModRef.h:120
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static size_t totalSizeToAlloc(StringRef Kind, StringRef Val)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:472
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:225
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:143
int compare(StringRef RHS) const
compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...
Definition StringRef.h:179
A switch()-like statement whose cases are string literals.
static constexpr std::enable_if_t< std::is_same_v< Foo< TrailingTys... >, Foo< Tys... > >, size_t > totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType< TrailingTys, size_t >::type... Counts)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
LLVM Value Representation.
Definition Value.h:75
static constexpr uint64_t MaximumAlignment
Definition Value.h:830
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
This class provides various memory handling functions that manipulate MemoryBlock instances.
Definition Memory.h:54
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:667
iterator end() const
Definition BasicBlock.h:89
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1725
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1655
AllocFnKind
Definition Attributes.h:51
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2136
std::string utostr(uint64_t X, bool isNeg=false)
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:301
LLVM_ABI void printEscapedString(StringRef Name, raw_ostream &Out)
Print each character of the specified string, escaping it if it is not printable or if it is an escap...
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1732
UWTableKind
Definition CodeGen.h:154
@ None
No unwind table requested.
Definition CodeGen.h:155
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1622
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
Definition STLExtras.h:1920
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
Definition ModRef.h:28
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
@ ModRef
The access may reference and may modify the value stored in memory.
Definition ModRef.h:36
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
@ NoModRef
The access neither references nor modifies the value stored in memory.
Definition ModRef.h:30
@ ErrnoMem
Errno memory.
Definition ModRef.h:66
@ ArgMem
Access to memory via argument pointers.
Definition ModRef.h:62
@ TargetMem0
Represents target specific state.
Definition ModRef.h:70
@ Other
Any other memory.
Definition ModRef.h:68
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ InaccessibleMem
Memory that is inaccessible via LLVM IR.
Definition ModRef.h:64
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:1994
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1835
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2120
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
Attribute comparator that only compares attribute keys.
bool operator()(Attribute A0, StringRef Kind) const
bool operator()(Attribute A0, Attribute A1) const
bool operator()(Attribute A0, Attribute::AttrKind Kind) const
static void set(Function &Fn, Attribute::AttrKind Kind, bool Val)
static bool isSet(const Function &Fn, Attribute::AttrKind Kind)
static bool isSet(const Function &Fn, StringRef Kind)
static void set(Function &Fn, StringRef Kind, bool Val)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Represent subnormal handling kind for floating point instruction inputs and outputs.
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getInvalid()
DenormalModeKind Output
Denormal flushing mode for floating point instruction results in the default floating point environme...
static constexpr DenormalMode getDynamic()
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:130
Function object to check whether the first component of a container supported by std::get (like std::...
Definition STLExtras.h:1425