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