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