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");
659 }
660 OS << getModRefStr(MR);
661 }
662 OS << ")";
663 OS.flush();
664 return Result;
665 }
666
667 if (hasAttribute(Attribute::Captures)) {
668 std::string Result;
669 raw_string_ostream OS(Result);
670 OS << getCaptureInfo();
671 return Result;
672 }
673
674 if (hasAttribute(Attribute::NoFPClass)) {
675 std::string Result = "nofpclass";
676 raw_string_ostream OS(Result);
677 OS << getNoFPClass();
678 return Result;
679 }
680
681 if (hasAttribute(Attribute::Range)) {
682 std::string Result;
683 raw_string_ostream OS(Result);
685 OS << "range(";
686 OS << "i" << CR.getBitWidth() << " ";
687 OS << CR.getLower() << ", " << CR.getUpper();
688 OS << ")";
689 OS.flush();
690 return Result;
691 }
692
693 if (hasAttribute(Attribute::Initializes)) {
694 std::string Result;
695 raw_string_ostream OS(Result);
697 OS << "initializes(";
698 CRL.print(OS);
699 OS << ")";
700 OS.flush();
701 return Result;
702 }
703
704 // Convert target-dependent attributes to strings of the form:
705 //
706 // "kind"
707 // "kind" = "value"
708 //
709 if (isStringAttribute()) {
710 std::string Result;
711 {
712 raw_string_ostream OS(Result);
713 OS << '"' << getKindAsString() << '"';
714
715 // Since some attribute strings contain special characters that cannot be
716 // printable, those have to be escaped to make the attribute value
717 // printable as is. e.g. "\01__gnu_mcount_nc"
718 const auto &AttrVal = pImpl->getValueAsString();
719 if (!AttrVal.empty()) {
720 OS << "=\"";
721 printEscapedString(AttrVal, OS);
722 OS << "\"";
723 }
724 }
725 return Result;
726 }
727
728 llvm_unreachable("Unknown attribute");
729}
730
732 assert(isValid() && "invalid Attribute doesn't refer to any context");
734 pImpl->Profile(ID);
735 void *Unused;
736 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
737}
738
739int Attribute::cmpKind(Attribute A) const {
740 if (!pImpl && !A.pImpl)
741 return 0;
742 if (!pImpl)
743 return 1;
744 if (!A.pImpl)
745 return -1;
746 return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
747}
748
749bool Attribute::operator<(Attribute A) const {
750 if (!pImpl && !A.pImpl) return false;
751 if (!pImpl) return true;
752 if (!A.pImpl) return false;
753 return *pImpl < *A.pImpl;
754}
755
757 ID.AddPointer(pImpl);
758}
759
761 FnAttr = (1 << 0),
762 ParamAttr = (1 << 1),
763 RetAttr = (1 << 2),
765 IntersectAnd = (1 << 3),
766 IntersectMin = (2 << 3),
767 IntersectCustom = (3 << 3),
769};
770
771#define GET_ATTR_PROP_TABLE
772#include "llvm/IR/Attributes.inc"
773
775 unsigned Index = Kind - 1;
776 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
777 return AttrPropTable[Index];
778}
779
781 AttributeProperty Prop) {
782 return getAttributeProperties(Kind) & Prop;
783}
784
788
792
796
798 AttributeProperty Prop) {
803 "Unknown intersect property");
804 return (getAttributeProperties(Kind) &
806}
807
820
821//===----------------------------------------------------------------------===//
822// AttributeImpl Definition
823//===----------------------------------------------------------------------===//
824
826 if (isStringAttribute()) return false;
827 return getKindAsEnum() == A;
828}
829
831 if (!isStringAttribute()) return false;
832 return getKindAsString() == Kind;
833}
834
840
843 return static_cast<const IntAttributeImpl *>(this)->getValue();
844}
845
847 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
848 return getValueAsString() == "true";
849}
850
853 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
854}
855
858 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
859}
860
863 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
864}
865
868 return static_cast<const ConstantRangeAttributeImpl *>(this)
869 ->getConstantRangeValue();
870}
871
874 return static_cast<const ConstantRangeListAttributeImpl *>(this)
875 ->getConstantRangeListValue();
876}
877
878int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
879 if (this == &AI)
880 return 0;
881
882 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
883 // relative to their enum value) and then strings.
884 if (!isStringAttribute()) {
885 if (AI.isStringAttribute())
886 return -1;
887
888 if (getKindAsEnum() != AI.getKindAsEnum())
889 return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
890 else if (KindOnly)
891 return 0;
892
893 assert(!AI.isEnumAttribute() && "Non-unique attribute");
894 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
895 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
897 "Unclear how to compare range list");
898 // TODO: Is this actually needed?
899 assert(AI.isIntAttribute() && "Only possibility left");
900 if (getValueAsInt() < AI.getValueAsInt())
901 return -1;
902 return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
903 }
904 if (!AI.isStringAttribute())
905 return 1;
906 if (KindOnly)
908 if (getKindAsString() == AI.getKindAsString())
911}
912
914 return cmp(AI, /*KindOnly=*/false) < 0;
915}
916
917//===----------------------------------------------------------------------===//
918// AttributeSet Definition
919//===----------------------------------------------------------------------===//
920
921AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
923}
924
928
930 Attribute::AttrKind Kind) const {
931 if (hasAttribute(Kind)) return *this;
932 AttrBuilder B(C);
933 B.addAttribute(Kind);
935}
936
938 StringRef Value) const {
939 AttrBuilder B(C);
940 B.addAttribute(Kind, Value);
942}
943
945 const AttributeSet AS) const {
946 if (!hasAttributes())
947 return AS;
948
949 if (!AS.hasAttributes())
950 return *this;
951
952 AttrBuilder B(C, *this);
953 B.merge(AttrBuilder(C, AS));
954 return get(C, B);
955}
956
958 const AttrBuilder &B) const {
959 if (!hasAttributes())
960 return get(C, B);
961
962 if (!B.hasAttributes())
963 return *this;
964
965 AttrBuilder Merged(C, *this);
966 Merged.merge(B);
967 return get(C, Merged);
968}
969
971 Attribute::AttrKind Kind) const {
972 if (!hasAttribute(Kind)) return *this;
973 AttrBuilder B(C, *this);
974 B.removeAttribute(Kind);
975 return get(C, B);
976}
977
979 StringRef Kind) const {
980 if (!hasAttribute(Kind)) return *this;
981 AttrBuilder B(C, *this);
982 B.removeAttribute(Kind);
983 return get(C, B);
984}
985
987 const AttributeMask &Attrs) const {
988 AttrBuilder B(C, *this);
989 // If there is nothing to remove, directly return the original set.
990 if (!B.overlaps(Attrs))
991 return *this;
992
993 B.remove(Attrs);
994 return get(C, B);
995}
996
997std::optional<AttributeSet>
999 if (*this == Other)
1000 return *this;
1001
1002 AttrBuilder Intersected(C);
1003 // Iterate over both attr sets at once.
1004 auto ItBegin0 = begin();
1005 auto ItEnd0 = end();
1006 auto ItBegin1 = Other.begin();
1007 auto ItEnd1 = Other.end();
1008
1009 while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
1010 // Loop through all attributes in both this and Other in sorted order. If
1011 // the attribute is only present in one of the sets, it will be set in
1012 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
1013 Attribute Attr0, Attr1;
1014 if (ItBegin1 == ItEnd1)
1015 Attr0 = *ItBegin0++;
1016 else if (ItBegin0 == ItEnd0)
1017 Attr0 = *ItBegin1++;
1018 else {
1019 int Cmp = ItBegin0->cmpKind(*ItBegin1);
1020 if (Cmp == 0) {
1021 Attr0 = *ItBegin0++;
1022 Attr1 = *ItBegin1++;
1023 } else if (Cmp < 0)
1024 Attr0 = *ItBegin0++;
1025 else
1026 Attr0 = *ItBegin1++;
1027 }
1028 assert(Attr0.isValid() && "Iteration should always yield a valid attr");
1029
1030 auto IntersectEq = [&]() {
1031 if (!Attr1.isValid())
1032 return false;
1033 if (Attr0 != Attr1)
1034 return false;
1035 Intersected.addAttribute(Attr0);
1036 return true;
1037 };
1038
1039 // Non-enum assume we must preserve. Handle early so we can unconditionally
1040 // use Kind below.
1041 if (!Attr0.hasKindAsEnum()) {
1042 if (!IntersectEq())
1043 return std::nullopt;
1044 continue;
1045 }
1046
1047 Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1048 // If we don't have both attributes, then fail if the attribute is
1049 // must-preserve or drop it otherwise.
1050 if (!Attr1.isValid()) {
1052 return std::nullopt;
1053 continue;
1054 }
1055
1056 // We have both attributes so apply the intersection rule.
1057 assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1058 "Iterator picked up two different attributes in the same iteration");
1059
1060 // Attribute we can intersect with "and"
1061 if (Attribute::intersectWithAnd(Kind)) {
1063 "Invalid attr type of intersectAnd");
1064 Intersected.addAttribute(Kind);
1065 continue;
1066 }
1067
1068 // Attribute we can intersect with "min"
1069 if (Attribute::intersectWithMin(Kind)) {
1071 "Invalid attr type of intersectMin");
1072 uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1073 Intersected.addRawIntAttr(Kind, NewVal);
1074 continue;
1075 }
1076 // Attribute we can intersect but need a custom rule for.
1078 switch (Kind) {
1079 case Attribute::Alignment:
1080 // If `byval` is present, alignment become must-preserve. This is
1081 // handled below if we have `byval`.
1082 Intersected.addAlignmentAttr(
1083 std::min(Attr0.getAlignment().valueOrOne(),
1084 Attr1.getAlignment().valueOrOne()));
1085 break;
1086 case Attribute::Memory:
1087 Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1088 Attr1.getMemoryEffects());
1089 break;
1090 case Attribute::Captures:
1091 Intersected.addCapturesAttr(Attr0.getCaptureInfo() |
1092 Attr1.getCaptureInfo());
1093 break;
1094 case Attribute::NoFPClass:
1095 Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1096 Attr1.getNoFPClass());
1097 break;
1098 case Attribute::Range: {
1099 ConstantRange Range0 = Attr0.getRange();
1100 ConstantRange Range1 = Attr1.getRange();
1101 ConstantRange NewRange = Range0.unionWith(Range1);
1102 if (!NewRange.isFullSet())
1103 Intersected.addRangeAttr(NewRange);
1104 } break;
1105 default:
1106 llvm_unreachable("Unknown attribute with custom intersection rule");
1107 }
1108 continue;
1109 }
1110
1111 // Attributes with no intersection rule. Only intersect if they are equal.
1112 // Otherwise fail.
1113 if (!IntersectEq())
1114 return std::nullopt;
1115
1116 // Special handling of `byval`. `byval` essentially turns align attr into
1117 // must-preserve
1118 if (Kind == Attribute::ByVal &&
1119 getAttribute(Attribute::Alignment) !=
1120 Other.getAttribute(Attribute::Alignment))
1121 return std::nullopt;
1122 }
1123
1124 return get(C, Intersected);
1125}
1126
1128 return SetNode ? SetNode->getNumAttributes() : 0;
1129}
1130
1132 return SetNode ? SetNode->hasAttribute(Kind) : false;
1133}
1134
1136 return SetNode ? SetNode->hasAttribute(Kind) : false;
1137}
1138
1140 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1141}
1142
1144 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1145}
1146
1148 return SetNode ? SetNode->getAlignment() : std::nullopt;
1149}
1150
1152 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
1153}
1154
1156 return SetNode ? SetNode->getDereferenceableBytes() : 0;
1157}
1158
1160 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
1161}
1162
1164 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
1165}
1166
1168 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
1169}
1170
1172 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
1173}
1174
1176 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
1177}
1178
1180 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
1181}
1182
1184 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
1185}
1186
1187std::optional<std::pair<unsigned, std::optional<unsigned>>>
1189 if (SetNode)
1190 return SetNode->getAllocSizeArgs();
1191 return std::nullopt;
1192}
1193
1195 return SetNode ? SetNode->getVScaleRangeMin() : 1;
1196}
1197
1198std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1199 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
1200}
1201
1203 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
1204}
1205
1207 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
1208}
1209
1211 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
1212}
1213
1215 return SetNode ? SetNode->getCaptureInfo() : CaptureInfo::all();
1216}
1217
1219 return SetNode ? SetNode->getNoFPClass() : fcNone;
1220}
1221
1222std::string AttributeSet::getAsString(bool InAttrGrp) const {
1223 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
1224}
1225
1227 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1229 SetNode->Profile(ID);
1230 void *Unused;
1231 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1232}
1233
1235 return SetNode ? SetNode->begin() : nullptr;
1236}
1237
1239 return SetNode ? SetNode->end() : nullptr;
1240}
1241
1242#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1244 dbgs() << "AS =\n";
1245 dbgs() << " { ";
1246 dbgs() << getAsString(true) << " }\n";
1247}
1248#endif
1249
1250//===----------------------------------------------------------------------===//
1251// AttributeSetNode Definition
1252//===----------------------------------------------------------------------===//
1253
1254AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1255 : NumAttrs(Attrs.size()) {
1256 // There's memory after the node where we can store the entries in.
1257 llvm::copy(Attrs, getTrailingObjects());
1258
1259 for (const auto &I : *this) {
1260 if (I.isStringAttribute())
1261 StringAttrs.insert({ I.getKindAsString(), I });
1262 else
1263 AvailableAttrs.addAttribute(I.getKindAsEnum());
1264 }
1265}
1266
1268 ArrayRef<Attribute> Attrs) {
1269 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1270 llvm::sort(SortedAttrs);
1271 return getSorted(C, SortedAttrs);
1272}
1273
1274AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1275 ArrayRef<Attribute> SortedAttrs) {
1276 if (SortedAttrs.empty())
1277 return nullptr;
1278
1279 // Build a key to look up the existing attributes.
1280 LLVMContextImpl *pImpl = C.pImpl;
1282
1283 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1284 for (const auto &Attr : SortedAttrs)
1285 Attr.Profile(ID);
1286
1287 void *InsertPoint;
1288 AttributeSetNode *PA =
1289 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1290
1291 // If we didn't find any existing attributes of the same shape then create a
1292 // new one and insert it.
1293 if (!PA) {
1294 // Coallocate entries after the AttributeSetNode itself.
1295 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1296 PA = new (Mem) AttributeSetNode(SortedAttrs);
1297 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1298 }
1299
1300 // Return the AttributeSetNode that we found or created.
1301 return PA;
1302}
1303
1304AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
1305 return getSorted(C, B.attrs());
1306}
1307
1309 return StringAttrs.count(Kind);
1310}
1311
1312std::optional<Attribute>
1313AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1314 // Do a quick presence check.
1315 if (!hasAttribute(Kind))
1316 return std::nullopt;
1317
1318 // Attributes in a set are sorted by enum value, followed by string
1319 // attributes. Binary search the one we want.
1320 const Attribute *I =
1321 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1322 [](Attribute A, Attribute::AttrKind Kind) {
1323 return A.getKindAsEnum() < Kind;
1324 });
1325 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1326 return *I;
1327}
1328
1330 if (auto A = findEnumAttribute(Kind))
1331 return *A;
1332 return {};
1333}
1334
1336 return StringAttrs.lookup(Kind);
1337}
1338
1340 if (auto A = findEnumAttribute(Attribute::Alignment))
1341 return A->getAlignment();
1342 return std::nullopt;
1343}
1344
1346 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1347 return A->getStackAlignment();
1348 return std::nullopt;
1349}
1350
1352 if (auto A = findEnumAttribute(Kind))
1353 return A->getValueAsType();
1354 return nullptr;
1355}
1356
1358 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1359 return A->getDereferenceableBytes();
1360 return 0;
1361}
1362
1364 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1365 return A->getDereferenceableOrNullBytes();
1366 return 0;
1367}
1368
1369std::optional<std::pair<unsigned, std::optional<unsigned>>>
1371 if (auto A = findEnumAttribute(Attribute::AllocSize))
1372 return A->getAllocSizeArgs();
1373 return std::nullopt;
1374}
1375
1377 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1378 return A->getVScaleRangeMin();
1379 return 1;
1380}
1381
1382std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1383 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1384 return A->getVScaleRangeMax();
1385 return std::nullopt;
1386}
1387
1389 if (auto A = findEnumAttribute(Attribute::UWTable))
1390 return A->getUWTableKind();
1391 return UWTableKind::None;
1392}
1393
1395 if (auto A = findEnumAttribute(Attribute::AllocKind))
1396 return A->getAllocKind();
1397 return AllocFnKind::Unknown;
1398}
1399
1401 if (auto A = findEnumAttribute(Attribute::Memory))
1402 return A->getMemoryEffects();
1403 return MemoryEffects::unknown();
1404}
1405
1407 if (auto A = findEnumAttribute(Attribute::Captures))
1408 return A->getCaptureInfo();
1409 return CaptureInfo::all();
1410}
1411
1413 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1414 return A->getNoFPClass();
1415 return fcNone;
1416}
1417
1418std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1419 std::string Str;
1420 for (iterator I = begin(), E = end(); I != E; ++I) {
1421 if (I != begin())
1422 Str += ' ';
1423 Str += I->getAsString(InAttrGrp);
1424 }
1425 return Str;
1426}
1427
1428//===----------------------------------------------------------------------===//
1429// AttributeListImpl Definition
1430//===----------------------------------------------------------------------===//
1431
1432/// Map from AttributeList index to the internal array index. Adding one happens
1433/// to work, because -1 wraps around to 0.
1434static unsigned attrIdxToArrayIdx(unsigned Index) {
1435 return Index + 1;
1436}
1437
1439 : NumAttrSets(Sets.size()) {
1440 assert(!Sets.empty() && "pointless AttributeListImpl");
1441
1442 // There's memory after the node where we can store the entries in.
1444
1445 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1446 // summary bitsets.
1447 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1448 if (!I.isStringAttribute())
1449 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1450
1451 for (const auto &Set : Sets)
1452 for (const auto &I : Set)
1453 if (!I.isStringAttribute())
1454 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1455}
1456
1460
1463 for (const auto &Set : Sets)
1464 ID.AddPointer(Set.SetNode);
1465}
1466
1468 unsigned *Index) const {
1469 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1470 return false;
1471
1472 if (Index) {
1473 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1474 if (begin()[I].hasAttribute(Kind)) {
1475 *Index = I - 1;
1476 break;
1477 }
1478 }
1479 }
1480
1481 return true;
1482}
1483
1484
1485#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1487 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1488}
1489#endif
1490
1491//===----------------------------------------------------------------------===//
1492// AttributeList Construction and Mutation Methods
1493//===----------------------------------------------------------------------===//
1494
1495AttributeList AttributeList::getImpl(LLVMContext &C,
1496 ArrayRef<AttributeSet> AttrSets) {
1497 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1498
1499 LLVMContextImpl *pImpl = C.pImpl;
1501 AttributeListImpl::Profile(ID, AttrSets);
1502
1503 void *InsertPoint;
1504 AttributeListImpl *PA =
1505 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1506
1507 // If we didn't find any existing attributes of the same shape then
1508 // create a new one and insert it.
1509 if (!PA) {
1510 // Coallocate entries after the AttributeListImpl itself.
1511 void *Mem = pImpl->Alloc.Allocate(
1513 alignof(AttributeListImpl));
1514 PA = new (Mem) AttributeListImpl(AttrSets);
1515 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1516 }
1517
1518 // Return the AttributesList that we found or created.
1519 return AttributeList(PA);
1520}
1521
1522AttributeList
1523AttributeList::get(LLVMContext &C,
1524 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1525 // If there are no attributes then return a null AttributesList pointer.
1526 if (Attrs.empty())
1527 return {};
1528
1530 "Misordered Attributes list!");
1531 assert(llvm::all_of(Attrs,
1532 [](const std::pair<unsigned, Attribute> &Pair) {
1533 return Pair.second.isValid();
1534 }) &&
1535 "Pointless attribute!");
1536
1537 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1538 // list.
1540 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1541 E = Attrs.end(); I != E; ) {
1542 unsigned Index = I->first;
1544 while (I != E && I->first == Index) {
1545 AttrVec.push_back(I->second);
1546 ++I;
1547 }
1548
1549 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1550 }
1551
1552 return get(C, AttrPairVec);
1553}
1554
1555AttributeList
1556AttributeList::get(LLVMContext &C,
1557 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1558 // If there are no attributes then return a null AttributesList pointer.
1559 if (Attrs.empty())
1560 return {};
1561
1563 "Misordered Attributes list!");
1564 assert(llvm::none_of(Attrs,
1565 [](const std::pair<unsigned, AttributeSet> &Pair) {
1566 return !Pair.second.hasAttributes();
1567 }) &&
1568 "Pointless attribute!");
1569
1570 unsigned MaxIndex = Attrs.back().first;
1571 // If the MaxIndex is FunctionIndex and there are other indices in front
1572 // of it, we need to use the largest of those to get the right size.
1573 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1574 MaxIndex = Attrs[Attrs.size() - 2].first;
1575
1576 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1577 for (const auto &Pair : Attrs)
1578 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1579
1580 return getImpl(C, AttrVec);
1581}
1582
1583AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1584 AttributeSet RetAttrs,
1585 ArrayRef<AttributeSet> ArgAttrs) {
1586 // Scan from the end to find the last argument with attributes. Most
1587 // arguments don't have attributes, so it's nice if we can have fewer unique
1588 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1589 unsigned NumSets = 0;
1590 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1591 if (ArgAttrs[I - 1].hasAttributes()) {
1592 NumSets = I + 2;
1593 break;
1594 }
1595 }
1596 if (NumSets == 0) {
1597 // Check function and return attributes if we didn't have argument
1598 // attributes.
1599 if (RetAttrs.hasAttributes())
1600 NumSets = 2;
1601 else if (FnAttrs.hasAttributes())
1602 NumSets = 1;
1603 }
1604
1605 // If all attribute sets were empty, we can use the empty attribute list.
1606 if (NumSets == 0)
1607 return {};
1608
1610 AttrSets.reserve(NumSets);
1611 // If we have any attributes, we always have function attributes.
1612 AttrSets.push_back(FnAttrs);
1613 if (NumSets > 1)
1614 AttrSets.push_back(RetAttrs);
1615 if (NumSets > 2) {
1616 // Drop the empty argument attribute sets at the end.
1617 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1618 llvm::append_range(AttrSets, ArgAttrs);
1619 }
1620
1621 return getImpl(C, AttrSets);
1622}
1623
1624AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1625 AttributeSet Attrs) {
1626 if (!Attrs.hasAttributes())
1627 return {};
1628 Index = attrIdxToArrayIdx(Index);
1629 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1630 AttrSets[Index] = Attrs;
1631 return getImpl(C, AttrSets);
1632}
1633
1634AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1635 const AttrBuilder &B) {
1636 return get(C, Index, AttributeSet::get(C, B));
1637}
1638
1639AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1642 for (const auto K : Kinds)
1643 Attrs.emplace_back(Index, Attribute::get(C, K));
1644 return get(C, Attrs);
1645}
1646
1647AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1649 ArrayRef<uint64_t> Values) {
1650 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1652 auto VI = Values.begin();
1653 for (const auto K : Kinds)
1654 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1655 return get(C, Attrs);
1656}
1657
1658AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1659 ArrayRef<StringRef> Kinds) {
1661 for (const auto &K : Kinds)
1662 Attrs.emplace_back(Index, Attribute::get(C, K));
1663 return get(C, Attrs);
1664}
1665
1666AttributeList AttributeList::get(LLVMContext &C,
1668 if (Attrs.empty())
1669 return {};
1670 if (Attrs.size() == 1)
1671 return Attrs[0];
1672
1673 unsigned MaxSize = 0;
1674 for (const auto &List : Attrs)
1675 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1676
1677 // If every list was empty, there is no point in merging the lists.
1678 if (MaxSize == 0)
1679 return {};
1680
1681 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1682 for (unsigned I = 0; I < MaxSize; ++I) {
1683 AttrBuilder CurBuilder(C);
1684 for (const auto &List : Attrs)
1685 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1686 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1687 }
1688
1689 return getImpl(C, NewAttrSets);
1690}
1691
1692AttributeList
1693AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1694 Attribute::AttrKind Kind) const {
1696 if (Attrs.hasAttribute(Kind))
1697 return *this;
1698 // TODO: Insert at correct position and avoid sort.
1699 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1700 NewAttrs.push_back(Attribute::get(C, Kind));
1701 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1702}
1703
1704AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1705 StringRef Kind,
1706 StringRef Value) const {
1707 AttrBuilder B(C);
1708 B.addAttribute(Kind, Value);
1709 return addAttributesAtIndex(C, Index, B);
1710}
1711
1712AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1713 Attribute A) const {
1714 AttrBuilder B(C);
1715 B.addAttribute(A);
1716 return addAttributesAtIndex(C, Index, B);
1717}
1718
1719AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1720 unsigned Index,
1721 AttributeSet Attrs) const {
1722 Index = attrIdxToArrayIdx(Index);
1723 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1724 if (Index >= AttrSets.size())
1725 AttrSets.resize(Index + 1);
1726 AttrSets[Index] = Attrs;
1727
1728 // Remove trailing empty attribute sets.
1729 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1730 AttrSets.pop_back();
1731 if (AttrSets.empty())
1732 return {};
1733 return AttributeList::getImpl(C, AttrSets);
1734}
1735
1736AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1737 unsigned Index,
1738 const AttrBuilder &B) const {
1739 if (!B.hasAttributes())
1740 return *this;
1741
1742 if (!pImpl)
1743 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1744
1745 AttrBuilder Merged(C, getAttributes(Index));
1746 Merged.merge(B);
1747 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1748}
1749
1750AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1751 ArrayRef<unsigned> ArgNos,
1752 Attribute A) const {
1753 assert(llvm::is_sorted(ArgNos));
1754
1755 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1756 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1757 if (MaxIndex >= AttrSets.size())
1758 AttrSets.resize(MaxIndex + 1);
1759
1760 for (unsigned ArgNo : ArgNos) {
1761 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1762 AttrBuilder B(C, AttrSets[Index]);
1763 B.addAttribute(A);
1764 AttrSets[Index] = AttributeSet::get(C, B);
1765 }
1766
1767 return getImpl(C, AttrSets);
1768}
1769
1770AttributeList
1771AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1772 Attribute::AttrKind Kind) const {
1774 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1775 if (Attrs == NewAttrs)
1776 return *this;
1777 return setAttributesAtIndex(C, Index, NewAttrs);
1778}
1779
1780AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1781 unsigned Index,
1782 StringRef Kind) const {
1784 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1785 if (Attrs == NewAttrs)
1786 return *this;
1787 return setAttributesAtIndex(C, Index, NewAttrs);
1788}
1789
1790AttributeList AttributeList::removeAttributesAtIndex(
1791 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1793 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1794 // If nothing was removed, return the original list.
1795 if (Attrs == NewAttrs)
1796 return *this;
1797 return setAttributesAtIndex(C, Index, NewAttrs);
1798}
1799
1800AttributeList
1801AttributeList::removeAttributesAtIndex(LLVMContext &C,
1802 unsigned WithoutIndex) const {
1803 if (!pImpl)
1804 return {};
1805 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1806 return *this;
1807 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1808}
1809
1810AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1811 uint64_t Bytes) const {
1812 AttrBuilder B(C);
1813 B.addDereferenceableAttr(Bytes);
1814 return addRetAttributes(C, B);
1815}
1816
1817AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1818 unsigned Index,
1819 uint64_t Bytes) const {
1820 AttrBuilder B(C);
1821 B.addDereferenceableAttr(Bytes);
1822 return addParamAttributes(C, Index, B);
1823}
1824
1825AttributeList
1826AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1827 uint64_t Bytes) const {
1828 AttrBuilder B(C);
1829 B.addDereferenceableOrNullAttr(Bytes);
1830 return addParamAttributes(C, Index, B);
1831}
1832
1833AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
1834 const ConstantRange &CR) const {
1835 AttrBuilder B(C);
1836 B.addRangeAttr(CR);
1837 return addRetAttributes(C, B);
1838}
1839
1840AttributeList AttributeList::addAllocSizeParamAttr(
1841 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1842 const std::optional<unsigned> &NumElemsArg) const {
1843 AttrBuilder B(C);
1844 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1845 return addParamAttributes(C, Index, B);
1846}
1847
1848std::optional<AttributeList>
1849AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
1850 // Trivial case, the two lists are equal.
1851 if (*this == Other)
1852 return *this;
1853
1855 auto IndexIt =
1856 index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1857 for (unsigned Idx : IndexIt) {
1858 auto IntersectedAS =
1859 getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1860 // If any index fails to intersect, fail.
1861 if (!IntersectedAS)
1862 return std::nullopt;
1863 if (!IntersectedAS->hasAttributes())
1864 continue;
1865 IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1866 }
1867
1868 llvm::sort(IntersectedAttrs, llvm::less_first());
1869 return AttributeList::get(C, IntersectedAttrs);
1870}
1871
1872//===----------------------------------------------------------------------===//
1873// AttributeList Accessor Methods
1874//===----------------------------------------------------------------------===//
1875
1876AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1877 return getAttributes(ArgNo + FirstArgIndex);
1878}
1879
1880AttributeSet AttributeList::getRetAttrs() const {
1881 return getAttributes(ReturnIndex);
1882}
1883
1884AttributeSet AttributeList::getFnAttrs() const {
1885 return getAttributes(FunctionIndex);
1886}
1887
1888bool AttributeList::hasAttributeAtIndex(unsigned Index,
1889 Attribute::AttrKind Kind) const {
1890 return getAttributes(Index).hasAttribute(Kind);
1891}
1892
1893bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1894 return getAttributes(Index).hasAttribute(Kind);
1895}
1896
1897bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1898 return getAttributes(Index).hasAttributes();
1899}
1900
1901bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1902 return pImpl && pImpl->hasFnAttribute(Kind);
1903}
1904
1905bool AttributeList::hasFnAttr(StringRef Kind) const {
1906 return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1907}
1908
1909bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1910 unsigned *Index) const {
1911 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1912}
1913
1914Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1915 Attribute::AttrKind Kind) const {
1916 return getAttributes(Index).getAttribute(Kind);
1917}
1918
1919Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1920 StringRef Kind) const {
1921 return getAttributes(Index).getAttribute(Kind);
1922}
1923
1924MaybeAlign AttributeList::getRetAlignment() const {
1925 return getAttributes(ReturnIndex).getAlignment();
1926}
1927
1928MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1929 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1930}
1931
1932MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1933 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1934}
1935
1936Type *AttributeList::getParamByValType(unsigned Index) const {
1937 return getAttributes(Index+FirstArgIndex).getByValType();
1938}
1939
1940Type *AttributeList::getParamStructRetType(unsigned Index) const {
1941 return getAttributes(Index + FirstArgIndex).getStructRetType();
1942}
1943
1944Type *AttributeList::getParamByRefType(unsigned Index) const {
1945 return getAttributes(Index + FirstArgIndex).getByRefType();
1946}
1947
1948Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1949 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1950}
1951
1952Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1953 return getAttributes(Index + FirstArgIndex).getInAllocaType();
1954}
1955
1956Type *AttributeList::getParamElementType(unsigned Index) const {
1957 return getAttributes(Index + FirstArgIndex).getElementType();
1958}
1959
1960MaybeAlign AttributeList::getFnStackAlignment() const {
1961 return getFnAttrs().getStackAlignment();
1962}
1963
1964MaybeAlign AttributeList::getRetStackAlignment() const {
1965 return getRetAttrs().getStackAlignment();
1966}
1967
1968uint64_t AttributeList::getRetDereferenceableBytes() const {
1969 return getRetAttrs().getDereferenceableBytes();
1970}
1971
1972uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1973 return getParamAttrs(Index).getDereferenceableBytes();
1974}
1975
1976uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1977 return getRetAttrs().getDereferenceableOrNullBytes();
1978}
1979
1980uint64_t
1981AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1982 return getParamAttrs(Index).getDereferenceableOrNullBytes();
1983}
1984
1985std::optional<ConstantRange>
1986AttributeList::getParamRange(unsigned ArgNo) const {
1987 auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
1988 if (RangeAttr.isValid())
1989 return RangeAttr.getRange();
1990 return std::nullopt;
1991}
1992
1993FPClassTest AttributeList::getRetNoFPClass() const {
1994 return getRetAttrs().getNoFPClass();
1995}
1996
1997FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {
1998 return getParamAttrs(Index).getNoFPClass();
1999}
2000
2001UWTableKind AttributeList::getUWTableKind() const {
2002 return getFnAttrs().getUWTableKind();
2003}
2004
2005AllocFnKind AttributeList::getAllocKind() const {
2006 return getFnAttrs().getAllocKind();
2007}
2008
2009MemoryEffects AttributeList::getMemoryEffects() const {
2010 return getFnAttrs().getMemoryEffects();
2011}
2012
2013std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
2014 return getAttributes(Index).getAsString(InAttrGrp);
2015}
2016
2017AttributeSet AttributeList::getAttributes(unsigned Index) const {
2018 Index = attrIdxToArrayIdx(Index);
2019 if (!pImpl || Index >= getNumAttrSets())
2020 return {};
2021 return pImpl->begin()[Index];
2022}
2023
2024bool AttributeList::hasParentContext(LLVMContext &C) const {
2025 assert(!isEmpty() && "an empty attribute list has no parent context");
2027 pImpl->Profile(ID);
2028 void *Unused;
2029 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
2030}
2031
2032AttributeList::iterator AttributeList::begin() const {
2033 return pImpl ? pImpl->begin() : nullptr;
2034}
2035
2036AttributeList::iterator AttributeList::end() const {
2037 return pImpl ? pImpl->end() : nullptr;
2038}
2039
2040//===----------------------------------------------------------------------===//
2041// AttributeList Introspection Methods
2042//===----------------------------------------------------------------------===//
2043
2044unsigned AttributeList::getNumAttrSets() const {
2045 return pImpl ? pImpl->NumAttrSets : 0;
2046}
2047
2048void AttributeList::print(raw_ostream &O) const {
2049 O << "AttributeList[\n";
2050
2051 for (unsigned i : indexes()) {
2052 if (!getAttributes(i).hasAttributes())
2053 continue;
2054 O << " { ";
2055 switch (i) {
2056 case AttrIndex::ReturnIndex:
2057 O << "return";
2058 break;
2059 case AttrIndex::FunctionIndex:
2060 O << "function";
2061 break;
2062 default:
2063 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2064 }
2065 O << " => " << getAsString(i) << " }\n";
2066 }
2067
2068 O << "]\n";
2069}
2070
2071#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2072LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
2073#endif
2074
2075//===----------------------------------------------------------------------===//
2076// AttrBuilder Method Implementations
2077//===----------------------------------------------------------------------===//
2078
2079AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
2080 append_range(Attrs, AS);
2081 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2082}
2083
2084void AttrBuilder::clear() { Attrs.clear(); }
2085
2086/// Attribute comparator that only compares attribute keys. Enum attributes are
2087/// sorted before string attributes.
2089 bool operator()(Attribute A0, Attribute A1) const {
2090 bool A0IsString = A0.isStringAttribute();
2091 bool A1IsString = A1.isStringAttribute();
2092 if (A0IsString) {
2093 if (A1IsString)
2094 return A0.getKindAsString() < A1.getKindAsString();
2095 else
2096 return false;
2097 }
2098 if (A1IsString)
2099 return true;
2100 return A0.getKindAsEnum() < A1.getKindAsEnum();
2101 }
2103 if (A0.isStringAttribute())
2104 return false;
2105 return A0.getKindAsEnum() < Kind;
2106 }
2107 bool operator()(Attribute A0, StringRef Kind) const {
2108 if (A0.isStringAttribute())
2109 return A0.getKindAsString() < Kind;
2110 return true;
2111 }
2112};
2113
2114template <typename K>
2116 Attribute Attr) {
2117 auto It = lower_bound(Attrs, Kind, AttributeComparator());
2118 if (It != Attrs.end() && It->hasAttribute(Kind))
2119 std::swap(*It, Attr);
2120 else
2121 Attrs.insert(It, Attr);
2122}
2123
2124AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
2125 if (Attr.isStringAttribute())
2126 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2127 else
2128 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2129 return *this;
2130}
2131
2132AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
2133 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2134 return *this;
2135}
2136
2137AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
2138 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2139 return *this;
2140}
2141
2142AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
2143 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2144 auto It = lower_bound(Attrs, Val, AttributeComparator());
2145 if (It != Attrs.end() && It->hasAttribute(Val))
2146 Attrs.erase(It);
2147 return *this;
2148}
2149
2150AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
2151 auto It = lower_bound(Attrs, A, AttributeComparator());
2152 if (It != Attrs.end() && It->hasAttribute(A))
2153 Attrs.erase(It);
2154 return *this;
2155}
2156
2157std::optional<uint64_t>
2158AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
2159 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2160 Attribute A = getAttribute(Kind);
2161 if (A.isValid())
2162 return A.getValueAsInt();
2163 return std::nullopt;
2164}
2165
2166AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
2167 uint64_t Value) {
2168 return addAttribute(Attribute::get(Ctx, Kind, Value));
2169}
2170
2171std::optional<std::pair<unsigned, std::optional<unsigned>>>
2172AttrBuilder::getAllocSizeArgs() const {
2173 Attribute A = getAttribute(Attribute::AllocSize);
2174 if (A.isValid())
2175 return A.getAllocSizeArgs();
2176 return std::nullopt;
2177}
2178
2179AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
2180 if (!Align)
2181 return *this;
2182
2183 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2184 return addRawIntAttr(Attribute::Alignment, Align->value());
2185}
2186
2187AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
2188 // Default alignment, allow the target to define how to align it.
2189 if (!Align)
2190 return *this;
2191
2192 assert(*Align <= 0x100 && "Alignment too large.");
2193 return addRawIntAttr(Attribute::StackAlignment, Align->value());
2194}
2195
2196AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
2197 if (Bytes == 0) return *this;
2198
2199 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2200}
2201
2202AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
2203 if (Bytes == 0)
2204 return *this;
2205
2206 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2207}
2208
2209AttrBuilder &
2210AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
2211 const std::optional<unsigned> &NumElems) {
2212 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2213}
2214
2215AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
2216 // (0, 0) is our "not present" value, so we need to check for it here.
2217 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2218 return addRawIntAttr(Attribute::AllocSize, RawArgs);
2219}
2220
2221AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
2222 std::optional<unsigned> MaxValue) {
2223 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2224}
2225
2226AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
2227 // (0, 0) is not present hence ignore this case
2228 if (RawArgs == 0)
2229 return *this;
2230
2231 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2232}
2233
2234AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
2235 if (Kind == UWTableKind::None)
2236 return *this;
2237 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2238}
2239
2240AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
2241 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2242}
2243
2244AttrBuilder &AttrBuilder::addCapturesAttr(CaptureInfo CI) {
2245 return addRawIntAttr(Attribute::Captures, CI.toIntValue());
2246}
2247
2248AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
2249 if (Mask == fcNone)
2250 return *this;
2251
2252 return addRawIntAttr(Attribute::NoFPClass, Mask);
2253}
2254
2255AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
2256 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2257}
2258
2259Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
2260 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2261 Attribute A = getAttribute(Kind);
2262 return A.isValid() ? A.getValueAsType() : nullptr;
2263}
2264
2265AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
2266 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2267}
2268
2269AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
2270 return addTypeAttr(Attribute::ByVal, Ty);
2271}
2272
2273AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
2274 return addTypeAttr(Attribute::StructRet, Ty);
2275}
2276
2277AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
2278 return addTypeAttr(Attribute::ByRef, Ty);
2279}
2280
2281AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
2282 return addTypeAttr(Attribute::Preallocated, Ty);
2283}
2284
2285AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
2286 return addTypeAttr(Attribute::InAlloca, Ty);
2287}
2288
2289AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,
2290 const ConstantRange &CR) {
2291 if (CR.isFullSet())
2292 return *this;
2293
2294 return addAttribute(Attribute::get(Ctx, Kind, CR));
2295}
2296
2297AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
2298 return addConstantRangeAttr(Attribute::Range, CR);
2299}
2300
2301AttrBuilder &
2302AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
2304 return addAttribute(Attribute::get(Ctx, Kind, Val));
2305}
2306
2307AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
2308 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2309}
2310
2311AttrBuilder &AttrBuilder::addFromEquivalentMetadata(const Instruction &I) {
2312 if (I.hasMetadata(LLVMContext::MD_nonnull))
2313 addAttribute(Attribute::NonNull);
2314
2315 if (I.hasMetadata(LLVMContext::MD_noundef))
2316 addAttribute(Attribute::NoUndef);
2317
2318 if (const MDNode *Align = I.getMetadata(LLVMContext::MD_align)) {
2319 ConstantInt *CI = mdconst::extract<ConstantInt>(Align->getOperand(0));
2320 addAlignmentAttr(CI->getZExtValue());
2321 }
2322
2323 if (const MDNode *Dereferenceable =
2324 I.getMetadata(LLVMContext::MD_dereferenceable)) {
2325 ConstantInt *CI =
2326 mdconst::extract<ConstantInt>(Dereferenceable->getOperand(0));
2327 addDereferenceableAttr(CI->getZExtValue());
2328 }
2329
2330 if (const MDNode *DereferenceableOrNull =
2331 I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) {
2332 ConstantInt *CI =
2333 mdconst::extract<ConstantInt>(DereferenceableOrNull->getOperand(0));
2334 addDereferenceableAttr(CI->getZExtValue());
2335 }
2336
2337 if (const MDNode *Range = I.getMetadata(LLVMContext::MD_range))
2338 addRangeAttr(getConstantRangeFromMetadata(*Range));
2339
2340 return *this;
2341}
2342
2343AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
2344 // TODO: Could make this O(n) as we're merging two sorted lists.
2345 for (const auto &I : B.attrs())
2346 addAttribute(I);
2347
2348 return *this;
2349}
2350
2351AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
2352 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2353 return *this;
2354}
2355
2356bool AttrBuilder::overlaps(const AttributeMask &AM) const {
2357 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2358}
2359
2360Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
2361 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2362 auto It = lower_bound(Attrs, A, AttributeComparator());
2363 if (It != Attrs.end() && It->hasAttribute(A))
2364 return *It;
2365 return {};
2366}
2367
2368Attribute AttrBuilder::getAttribute(StringRef A) const {
2369 auto It = lower_bound(Attrs, A, AttributeComparator());
2370 if (It != Attrs.end() && It->hasAttribute(A))
2371 return *It;
2372 return {};
2373}
2374
2375std::optional<ConstantRange> AttrBuilder::getRange() const {
2376 const Attribute RangeAttr = getAttribute(Attribute::Range);
2377 if (RangeAttr.isValid())
2378 return RangeAttr.getRange();
2379 return std::nullopt;
2380}
2381
2382bool AttrBuilder::contains(Attribute::AttrKind A) const {
2383 return getAttribute(A).isValid();
2384}
2385
2386bool AttrBuilder::contains(StringRef A) const {
2387 return getAttribute(A).isValid();
2388}
2389
2390bool AttrBuilder::operator==(const AttrBuilder &B) const {
2391 return Attrs == B.Attrs;
2392}
2393
2394//===----------------------------------------------------------------------===//
2395// AttributeFuncs Function Defintions
2396//===----------------------------------------------------------------------===//
2397
2398/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2399/// follows the same type rules as FPMathOperator.
2400bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2402}
2403
2404/// Which attributes cannot be applied to a type.
2405AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
2406 AttributeSafetyKind ASK) {
2407 AttributeMask Incompatible;
2408
2409 if (!Ty->isIntegerTy()) {
2410 // Attributes that only apply to integers.
2411 if (ASK & ASK_SAFE_TO_DROP)
2412 Incompatible.addAttribute(Attribute::AllocAlign);
2413 if (ASK & ASK_UNSAFE_TO_DROP)
2414 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2415 }
2416
2417 if (!Ty->isIntOrIntVectorTy()) {
2418 // Attributes that only apply to integers or vector of integers.
2419 if (ASK & ASK_SAFE_TO_DROP)
2420 Incompatible.addAttribute(Attribute::Range);
2421 } else {
2422 Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2423 if (RangeAttr.isValid() &&
2424 RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2425 Incompatible.addAttribute(Attribute::Range);
2426 }
2427
2428 if (!Ty->isPointerTy()) {
2429 // Attributes that only apply to pointers.
2430 if (ASK & ASK_SAFE_TO_DROP)
2431 Incompatible.addAttribute(Attribute::NoAlias)
2432 .addAttribute(Attribute::NonNull)
2433 .addAttribute(Attribute::ReadNone)
2434 .addAttribute(Attribute::ReadOnly)
2435 .addAttribute(Attribute::Dereferenceable)
2436 .addAttribute(Attribute::DereferenceableOrNull)
2437 .addAttribute(Attribute::Writable)
2438 .addAttribute(Attribute::DeadOnUnwind)
2439 .addAttribute(Attribute::Initializes)
2440 .addAttribute(Attribute::Captures)
2441 .addAttribute(Attribute::DeadOnReturn);
2442 if (ASK & ASK_UNSAFE_TO_DROP)
2443 Incompatible.addAttribute(Attribute::Nest)
2444 .addAttribute(Attribute::SwiftError)
2445 .addAttribute(Attribute::Preallocated)
2446 .addAttribute(Attribute::InAlloca)
2447 .addAttribute(Attribute::ByVal)
2448 .addAttribute(Attribute::StructRet)
2449 .addAttribute(Attribute::ByRef)
2450 .addAttribute(Attribute::ElementType)
2451 .addAttribute(Attribute::AllocatedPointer);
2452 }
2453
2454 // Attributes that only apply to pointers or vectors of pointers.
2455 if (!Ty->isPtrOrPtrVectorTy()) {
2456 if (ASK & ASK_SAFE_TO_DROP)
2457 Incompatible.addAttribute(Attribute::Alignment);
2458 }
2459
2460 if (ASK & ASK_SAFE_TO_DROP) {
2461 if (!isNoFPClassCompatibleType(Ty))
2462 Incompatible.addAttribute(Attribute::NoFPClass);
2463 }
2464
2465 // Some attributes can apply to all "values" but there are no `void` values.
2466 if (Ty->isVoidTy()) {
2467 if (ASK & ASK_SAFE_TO_DROP)
2468 Incompatible.addAttribute(Attribute::NoUndef);
2469 }
2470
2471 return Incompatible;
2472}
2473
2474AttributeMask AttributeFuncs::getUBImplyingAttributes() {
2475 AttributeMask AM;
2476 AM.addAttribute(Attribute::NoUndef);
2477 AM.addAttribute(Attribute::Dereferenceable);
2478 AM.addAttribute(Attribute::DereferenceableOrNull);
2479 return AM;
2480}
2481
2482/// Callees with dynamic denormal modes are compatible with any caller mode.
2483static bool denormModeCompatible(DenormalMode CallerMode,
2484 DenormalMode CalleeMode) {
2485 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2486 return true;
2487
2488 // If they don't exactly match, it's OK if the mismatched component is
2489 // dynamic.
2490 if (CalleeMode.Input == CallerMode.Input &&
2491 CalleeMode.Output == DenormalMode::Dynamic)
2492 return true;
2493
2494 if (CalleeMode.Output == CallerMode.Output &&
2495 CalleeMode.Input == DenormalMode::Dynamic)
2496 return true;
2497 return false;
2498}
2499
2500static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2501 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2502 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2503
2504 if (denormModeCompatible(CallerMode, CalleeMode)) {
2505 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2506 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2507 if (CallerModeF32 == DenormalMode::getInvalid())
2508 CallerModeF32 = CallerMode;
2509 if (CalleeModeF32 == DenormalMode::getInvalid())
2510 CalleeModeF32 = CalleeMode;
2511 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2512 }
2513
2514 return false;
2515}
2516
2517static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2518 // Do not inline strictfp function into non-strictfp one. It would require
2519 // conversion of all FP operations in host function to constrained intrinsics.
2520 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2521 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2522}
2523
2524template<typename AttrClass>
2525static bool isEqual(const Function &Caller, const Function &Callee) {
2526 return Caller.getFnAttribute(AttrClass::getKind()) ==
2527 Callee.getFnAttribute(AttrClass::getKind());
2528}
2529
2530static bool isEqual(const Function &Caller, const Function &Callee,
2531 const StringRef &AttrName) {
2532 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2533}
2534
2535/// Compute the logical AND of the attributes of the caller and the
2536/// callee.
2537///
2538/// This function sets the caller's attribute to false if the callee's attribute
2539/// is false.
2540template<typename AttrClass>
2541static void setAND(Function &Caller, const Function &Callee) {
2542 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2543 !AttrClass::isSet(Callee, AttrClass::getKind()))
2544 AttrClass::set(Caller, AttrClass::getKind(), false);
2545}
2546
2547/// Compute the logical OR of the attributes of the caller and the
2548/// callee.
2549///
2550/// This function sets the caller's attribute to true if the callee's attribute
2551/// is true.
2552template<typename AttrClass>
2553static void setOR(Function &Caller, const Function &Callee) {
2554 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2555 AttrClass::isSet(Callee, AttrClass::getKind()))
2556 AttrClass::set(Caller, AttrClass::getKind(), true);
2557}
2558
2559/// If the inlined function had a higher stack protection level than the
2560/// calling function, then bump up the caller's stack protection level.
2561static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2562 // If the calling function has *no* stack protection level (e.g. it was built
2563 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2564 // change it as that could change the program's semantics.
2565 if (!Caller.hasStackProtectorFnAttr())
2566 return;
2567
2568 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2569 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2570 // clutter to the IR.
2571 AttributeMask OldSSPAttr;
2572 OldSSPAttr.addAttribute(Attribute::StackProtect)
2573 .addAttribute(Attribute::StackProtectStrong)
2574 .addAttribute(Attribute::StackProtectReq);
2575
2576 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2577 Caller.removeFnAttrs(OldSSPAttr);
2578 Caller.addFnAttr(Attribute::StackProtectReq);
2579 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2580 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2581 Caller.removeFnAttrs(OldSSPAttr);
2582 Caller.addFnAttr(Attribute::StackProtectStrong);
2583 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2584 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2585 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2586 Caller.addFnAttr(Attribute::StackProtect);
2587}
2588
2589/// If the inlined function required stack probes, then ensure that
2590/// the calling function has those too.
2591static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2592 if (!Caller.hasFnAttribute("probe-stack") &&
2593 Callee.hasFnAttribute("probe-stack")) {
2594 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2595 }
2596}
2597
2598/// If the inlined function defines the size of guard region
2599/// on the stack, then ensure that the calling function defines a guard region
2600/// that is no larger.
2601static void
2603 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2604 if (CalleeAttr.isValid()) {
2605 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2606 if (CallerAttr.isValid()) {
2607 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2608 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2609 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2610
2611 if (CallerStackProbeSize > CalleeStackProbeSize) {
2612 Caller.addFnAttr(CalleeAttr);
2613 }
2614 } else {
2615 Caller.addFnAttr(CalleeAttr);
2616 }
2617 }
2618}
2619
2620/// If the inlined function defines a min legal vector width, then ensure
2621/// the calling function has the same or larger min legal vector width. If the
2622/// caller has the attribute, but the callee doesn't, we need to remove the
2623/// attribute from the caller since we can't make any guarantees about the
2624/// caller's requirements.
2625/// This function is called after the inlining decision has been made so we have
2626/// to merge the attribute this way. Heuristics that would use
2627/// min-legal-vector-width to determine inline compatibility would need to be
2628/// handled as part of inline cost analysis.
2629static void
2631 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2632 if (CallerAttr.isValid()) {
2633 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2634 if (CalleeAttr.isValid()) {
2635 uint64_t CallerVectorWidth, CalleeVectorWidth;
2636 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2637 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2638 if (CallerVectorWidth < CalleeVectorWidth)
2639 Caller.addFnAttr(CalleeAttr);
2640 } else {
2641 // If the callee doesn't have the attribute then we don't know anything
2642 // and must drop the attribute from the caller.
2643 Caller.removeFnAttr("min-legal-vector-width");
2644 }
2645 }
2646}
2647
2648/// If the inlined function has null_pointer_is_valid attribute,
2649/// set this attribute in the caller post inlining.
2650static void
2652 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2653 Caller.addFnAttr(Attribute::NullPointerIsValid);
2654 }
2655}
2656
2657struct EnumAttr {
2658 static bool isSet(const Function &Fn,
2659 Attribute::AttrKind Kind) {
2660 return Fn.hasFnAttribute(Kind);
2661 }
2662
2663 static void set(Function &Fn,
2664 Attribute::AttrKind Kind, bool Val) {
2665 if (Val)
2666 Fn.addFnAttr(Kind);
2667 else
2668 Fn.removeFnAttr(Kind);
2669 }
2670};
2671
2673 static bool isSet(const Function &Fn,
2674 StringRef Kind) {
2675 auto A = Fn.getFnAttribute(Kind);
2676 return A.getValueAsString() == "true";
2677 }
2678
2679 static void set(Function &Fn,
2680 StringRef Kind, bool Val) {
2681 Fn.addFnAttr(Kind, Val ? "true" : "false");
2682 }
2683};
2684
2685#define GET_ATTR_NAMES
2686#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2687 struct ENUM_NAME##Attr : EnumAttr { \
2688 static enum Attribute::AttrKind getKind() { \
2689 return llvm::Attribute::ENUM_NAME; \
2690 } \
2691 };
2692#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2693 struct ENUM_NAME##Attr : StrBoolAttr { \
2694 static StringRef getKind() { return #DISPLAY_NAME; } \
2695 };
2696#include "llvm/IR/Attributes.inc"
2697
2698#define GET_ATTR_COMPAT_FUNC
2699#include "llvm/IR/Attributes.inc"
2700
2701bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2702 const Function &Callee) {
2703 return hasCompatibleFnAttrs(Caller, Callee);
2704}
2705
2706bool AttributeFuncs::areOutlineCompatible(const Function &A,
2707 const Function &B) {
2708 return hasCompatibleFnAttrs(A, B);
2709}
2710
2711void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2712 const Function &Callee) {
2713 mergeFnAttrs(Caller, Callee);
2714}
2715
2716void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2717 const Function &ToMerge) {
2718
2719 // We merge functions so that they meet the most general case.
2720 // For example, if the NoNansFPMathAttr is set in one function, but not in
2721 // the other, in the merged function we can say that the NoNansFPMathAttr
2722 // is not set.
2723 // However if we have the SpeculativeLoadHardeningAttr set true in one
2724 // function, but not the other, we make sure that the function retains
2725 // that aspect in the merged function.
2726 mergeFnAttrs(Base, ToMerge);
2727}
2728
2729void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2730 uint64_t Width) {
2731 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2732 if (Attr.isValid()) {
2733 uint64_t OldWidth;
2734 Attr.getValueAsString().getAsInteger(0, OldWidth);
2735 if (Width > OldWidth)
2736 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2737 }
2738}
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:58
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:41
const T & back() const
back - Get the last element.
Definition ArrayRef.h:156
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:224
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
iterator begin() const
Definition ArrayRef.h:135
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:142
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.
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
Definition Allocator.h:149
Represents which components of the pointer may be captured in which location.
Definition ModRef.h:354
static CaptureInfo createFromIntValue(uint32_t Data)
Definition ModRef.h:425
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
Definition ModRef.h:370
uint32_t toIntValue() const
Convert CaptureInfo into an encoded integer value (used by captures attribute).
Definition ModRef.h:432
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:637
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:762
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition Function.cpp:685
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:727
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:1077
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:188
static MemoryEffectsBase createFromIntValue(uint32_t Data)
Definition ModRef.h:177
uint32_t toIntValue() const
Convert MemoryEffectsBase into an encoded integer value (used by memory attribute).
Definition ModRef.h:183
static MemoryEffectsBase unknown()
Definition ModRef.h:115
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:480
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:233
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:151
int compare(StringRef RHS) const
compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...
Definition StringRef.h:187
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:666
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:1727
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:1685
AllocFnKind
Definition Attributes.h:51
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2138
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:296
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:1734
UWTableKind
Definition CodeGen.h:148
@ None
No unwind table requested.
Definition CodeGen.h:149
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
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:1741
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:1922
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
@ Other
Any other memory.
Definition ModRef.h:68
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:71
@ 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:1996
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1837
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:2122
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:853
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
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:85
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:117
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:141
Function object to check whether the first component of a container supported by std::get (like std::...
Definition STLExtras.h:1455