LLVM 24.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;
102 if (!IsIntAttr) {
103 assert(Val == 0 && "Value must be zero for enum attributes");
104 EnumAttributeImpl *&PA = pImpl->EnumAttrs[Kind - Attribute::FirstEnumAttr];
105 if (!PA)
106 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
107 return Attribute(PA);
108 }
109
111 IntAttributeImpl *PA = pImpl->IntAttrs.lookup({Kind, Val}, Token);
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 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
116 pImpl->IntAttrs.insert(PA, Token);
117 }
118
119 // Return the Attribute that we found or created.
120 return Attribute(PA);
121}
122
123Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
124 LLVMContextImpl *pImpl = Context.pImpl;
126 StringAttributeImpl *PA = pImpl->StringAttrs.lookup({Kind, Val}, Token);
127 if (!PA) {
128 // If we didn't find any existing attributes of the same shape then create a
129 // new one and insert it.
130 void *Mem =
131 pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
132 alignof(StringAttributeImpl));
133 PA = new (Mem) StringAttributeImpl(Kind, Val);
134 pImpl->StringAttrs.insert(PA, Token);
135 }
136
137 // Return the Attribute that we found or created.
138 return Attribute(PA);
139}
140
142 Type *Ty) {
143 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
144 LLVMContextImpl *pImpl = Context.pImpl;
146 TypeAttributeImpl *PA = pImpl->TypeAttrs.lookup({Kind, Ty}, Token);
147 if (!PA) {
148 // If we didn't find any existing attributes of the same shape then create a
149 // new one and insert it.
150 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
151 pImpl->TypeAttrs.insert(PA, Token);
152 }
153
154 // Return the Attribute that we found or created.
155 return Attribute(PA);
156}
157
159 const ConstantRange &CR) {
161 "Not a ConstantRange attribute");
162 assert(!CR.isFullSet() && "ConstantRange attribute must not be full");
163 LLVMContextImpl *pImpl = Context.pImpl;
165 ID.AddInteger(Kind);
166 CR.getLower().Profile(ID);
167 CR.getUpper().Profile(ID);
168
170 AttributeImpl *PA = pImpl->AttrsSet.lookup(ID, Token);
171
172 if (!PA) {
173 // If we didn't find any existing attributes of the same shape then create a
174 // new one and insert it.
175 PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
177 pImpl->AttrsSet.insert(PA, Token);
178 }
179
180 // Return the Attribute that we found or created.
181 return Attribute(PA);
182}
183
187 "Not a ConstantRangeList attribute");
188 LLVMContextImpl *pImpl = Context.pImpl;
190 ID.AddInteger(Kind);
191 ID.AddInteger(Val.size());
192 for (auto &CR : Val) {
193 CR.getLower().Profile(ID);
194 CR.getUpper().Profile(ID);
195 }
196
198 AttributeImpl *PA = pImpl->AttrsSet.lookup(ID, Token);
199
200 if (!PA) {
201 // If we didn't find any existing attributes of the same shape then create a
202 // new one and insert it.
203 // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
204 // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
205 // allocation and record the allocated pointer in
206 // `ConstantRangeListAttributes`. LLVMContext destructor will call the
207 // destructor of the allocated pointer explicitly.
208 void *Mem = pImpl->Alloc.Allocate(
211 PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
212 pImpl->AttrsSet.insert(PA, Token);
213 pImpl->ConstantRangeListAttributes.push_back(
214 reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
215 }
216
217 // Return the Attribute that we found or created.
218 return Attribute(PA);
219}
220
222 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
223 return get(Context, Alignment, A.value());
224}
225
227 assert(A <= 0x100 && "Alignment too large.");
228 return get(Context, StackAlignment, A.value());
229}
230
232 uint64_t Bytes) {
233 assert(Bytes && "Bytes must be non-zero.");
234 return get(Context, Dereferenceable, Bytes);
235}
236
238 uint64_t Bytes) {
239 assert(Bytes && "Bytes must be non-zero.");
240 return get(Context, DereferenceableOrNull, Bytes);
241}
242
244 return get(Context, ByVal, Ty);
245}
246
248 return get(Context, StructRet, Ty);
249}
250
252 return get(Context, ByRef, Ty);
253}
254
256 return get(Context, Preallocated, Ty);
257}
258
260 return get(Context, InAlloca, Ty);
261}
262
264 UWTableKind Kind) {
265 return get(Context, UWTable, uint64_t(Kind));
266}
267
269 MemoryEffects ME) {
270 return get(Context, Memory, ME.toIntValue());
271}
272
274 FPClassTest ClassMask) {
275 return get(Context, NoFPClass, ClassMask);
276}
277
279 DeadOnReturnInfo DI) {
280 return get(Context, DeadOnReturn, DI.toIntValue());
281}
282
284 return get(Context, Captures, CI.toIntValue());
285}
286
288Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
289 const std::optional<unsigned> &NumElemsArg) {
290 assert(!(ElemSizeArg == 0 && NumElemsArg == 0) &&
291 "Invalid allocsize arguments -- given allocsize(0, 0)");
292 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
293}
294
296 return get(Context, AllocKind, static_cast<uint64_t>(Kind));
297}
298
300 unsigned MinValue,
301 unsigned MaxValue) {
302 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
303}
304
306 return StringSwitch<Attribute::AttrKind>(AttrName)
307#define GET_ATTR_NAMES
308#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
309 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
310#include "llvm/IR/Attributes.inc"
312}
313
315 switch (AttrKind) {
316#define GET_ATTR_NAMES
317#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
318 case Attribute::ENUM_NAME: \
319 return #DISPLAY_NAME;
320#include "llvm/IR/Attributes.inc"
321 case Attribute::None:
322 return "none";
323 default:
324 llvm_unreachable("invalid Kind");
325 }
326}
327
328//===----------------------------------------------------------------------===//
329// Attribute Accessor Methods
330//===----------------------------------------------------------------------===//
331
333 return pImpl && pImpl->isEnumAttribute();
334}
335
337 return pImpl && pImpl->isIntAttribute();
338}
339
341 return pImpl && pImpl->isStringAttribute();
342}
343
345 return pImpl && pImpl->isTypeAttribute();
346}
347
349 return pImpl && pImpl->isConstantRangeAttribute();
350}
351
353 return pImpl && pImpl->isConstantRangeListAttribute();
354}
355
357 if (!pImpl) return None;
359 "Invalid attribute type to get the kind as an enum!");
360 return pImpl->getKindAsEnum();
361}
362
363uint64_t Attribute::getValueAsInt() const {
364 if (!pImpl) return 0;
366 "Expected the attribute to be an integer attribute!");
367 return pImpl->getValueAsInt();
368}
369
371 if (!pImpl) return false;
373 "Expected the attribute to be a string attribute!");
374 return pImpl->getValueAsBool();
375}
376
378 if (!pImpl) return {};
380 "Invalid attribute type to get the kind as a string!");
381 return pImpl->getKindAsString();
382}
383
385 if (!pImpl) return {};
387 "Invalid attribute type to get the value as a string!");
388 return pImpl->getValueAsString();
389}
390
392 if (!pImpl) return {};
394 "Invalid attribute type to get the value as a type!");
395 return pImpl->getValueAsType();
396}
397
400 "Invalid attribute type to get the value as a ConstantRange!");
401 return pImpl->getValueAsConstantRange();
402}
403
406 "Invalid attribute type to get the value as a ConstantRangeList!");
407 return pImpl->getValueAsConstantRangeList();
408}
409
411 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
412}
413
415 if (!isStringAttribute()) return false;
416 return pImpl && pImpl->hasAttribute(Kind);
417}
418
420 assert(hasAttribute(Attribute::Alignment) &&
421 "Trying to get alignment from non-alignment attribute!");
422 return MaybeAlign(pImpl->getValueAsInt());
423}
424
426 assert(hasAttribute(Attribute::StackAlignment) &&
427 "Trying to get alignment from non-alignment attribute!");
428 return MaybeAlign(pImpl->getValueAsInt());
429}
430
432 assert(hasAttribute(Attribute::Dereferenceable) &&
433 "Trying to get dereferenceable bytes from "
434 "non-dereferenceable attribute!");
435 return pImpl->getValueAsInt();
436}
437
439 assert(hasAttribute(Attribute::DeadOnReturn) &&
440 "Trying to get dead_on_return bytes from"
441 "a parameter without such an attribute!");
442 return DeadOnReturnInfo::createFromIntValue(pImpl->getValueAsInt());
443}
444
446 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
447 "Trying to get dereferenceable bytes from "
448 "non-dereferenceable attribute!");
449 return pImpl->getValueAsInt();
450}
451
452std::pair<unsigned, std::optional<unsigned>>
454 assert(hasAttribute(Attribute::AllocSize) &&
455 "Trying to get allocsize args from non-allocsize attribute");
456 return unpackAllocSizeArgs(pImpl->getValueAsInt());
457}
458
460 assert(hasAttribute(Attribute::VScaleRange) &&
461 "Trying to get vscale args from non-vscale attribute");
462 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
463}
464
465std::optional<unsigned> Attribute::getVScaleRangeMax() const {
466 assert(hasAttribute(Attribute::VScaleRange) &&
467 "Trying to get vscale args from non-vscale attribute");
468 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
469}
470
472 assert(hasAttribute(Attribute::UWTable) &&
473 "Trying to get unwind table kind from non-uwtable attribute");
474 return UWTableKind(pImpl->getValueAsInt());
475}
476
478 assert(hasAttribute(Attribute::AllocKind) &&
479 "Trying to get allockind value from non-allockind attribute");
480 return AllocFnKind(pImpl->getValueAsInt());
481}
482
484 assert(hasAttribute(Attribute::Memory) &&
485 "Can only call getMemoryEffects() on memory attribute");
486 return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
487}
488
490 assert(hasAttribute(Attribute::Captures) &&
491 "Can only call getCaptureInfo() on captures attribute");
492 return CaptureInfo::createFromIntValue(pImpl->getValueAsInt());
493}
494
496 return DenormalFPEnv::createFromIntValue(pImpl->getValueAsInt());
497}
498
500 assert(hasAttribute(Attribute::NoFPClass) &&
501 "Can only call getNoFPClass() on nofpclass attribute");
502 return static_cast<FPClassTest>(pImpl->getValueAsInt());
503}
504
506 assert(hasAttribute(Attribute::Range) &&
507 "Trying to get range args from non-range attribute");
508 return pImpl->getValueAsConstantRange();
509}
510
512 assert(hasAttribute(Attribute::Initializes) &&
513 "Trying to get initializes attr from non-ConstantRangeList attribute");
514 return pImpl->getValueAsConstantRangeList();
515}
516
517static const char *getModRefStr(ModRefInfo MR) {
518 switch (MR) {
520 return "none";
521 case ModRefInfo::Ref:
522 return "read";
523 case ModRefInfo::Mod:
524 return "write";
526 return "readwrite";
527 }
528 llvm_unreachable("Invalid ModRefInfo");
529}
530
531std::string Attribute::getAsString(bool InAttrGrp) const {
532 if (!pImpl) return {};
533
534 if (isEnumAttribute())
536
537 if (isTypeAttribute()) {
538 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
539 Result += '(';
540 raw_string_ostream OS(Result);
541 getValueAsType()->print(OS, false, true);
542 Result += ')';
543 return Result;
544 }
545
546 // FIXME: These should be output like this:
547 //
548 // align=4
549 // alignstack=8
550 //
551 if (hasAttribute(Attribute::Alignment))
552 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
553 : "align " + Twine(getValueAsInt()))
554 .str();
555
556 auto AttrWithBytesToString = [&](const char *Name) {
557 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
558 : Name + ("(" + Twine(getValueAsInt())) + ")")
559 .str();
560 };
561
562 if (hasAttribute(Attribute::StackAlignment))
563 return AttrWithBytesToString("alignstack");
564
565 if (hasAttribute(Attribute::Dereferenceable))
566 return AttrWithBytesToString("dereferenceable");
567
568 if (hasAttribute(Attribute::DereferenceableOrNull))
569 return AttrWithBytesToString("dereferenceable_or_null");
570
571 if (hasAttribute(Attribute::DeadOnReturn)) {
572 uint64_t DeadBytes = getValueAsInt();
573 if (DeadBytes == std::numeric_limits<uint64_t>::max())
574 return "dead_on_return";
575 return AttrWithBytesToString("dead_on_return");
576 }
577
578 if (hasAttribute(Attribute::AllocSize)) {
579 unsigned ElemSize;
580 std::optional<unsigned> NumElems;
581 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
582
583 return (NumElems
584 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
585 : "allocsize(" + Twine(ElemSize) + ")")
586 .str();
587 }
588
589 if (hasAttribute(Attribute::VScaleRange)) {
590 unsigned MinValue = getVScaleRangeMin();
591 std::optional<unsigned> MaxValue = getVScaleRangeMax();
592 return ("vscale_range(" + Twine(MinValue) + "," +
593 Twine(MaxValue.value_or(0)) + ")")
594 .str();
595 }
596
597 if (hasAttribute(Attribute::UWTable)) {
599 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
600 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
601 }
602
603 if (hasAttribute(Attribute::AllocKind)) {
604 AllocFnKind Kind = getAllocKind();
607 parts.push_back("alloc");
609 parts.push_back("realloc");
611 parts.push_back("free");
613 parts.push_back("uninitialized");
615 parts.push_back("zeroed");
617 parts.push_back("aligned");
618 return ("allockind(\"" +
619 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
620 .str();
621 }
622
623 if (hasAttribute(Attribute::Memory)) {
624 std::string Result;
625 raw_string_ostream OS(Result);
626 bool First = true;
627 OS << "memory(";
628
630
631 // Print access kind for "other" as the default access kind. This way it
632 // will apply to any new location kinds that get split out of "other".
634 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
635 First = false;
636 OS << getModRefStr(OtherMR);
637 }
638
639 bool TargetPrintedForAll = false;
640 for (auto Loc : MemoryEffects::locations()) {
641 ModRefInfo MR = ME.getModRef(Loc);
642 if (MR == OtherMR)
643 continue;
644
645 if (!First && !TargetPrintedForAll)
646 OS << ", ";
647 First = false;
648
649 // isTargetMemLocSameForAll is fine for target location < 3
650 // If more targets are added it should do something like:
651 // memory(target_mem:read, target_mem3:none, target_mem5:write).
653 if (!TargetPrintedForAll) {
654 OS << "target_mem: ";
655 OS << getModRefStr(MR);
656 TargetPrintedForAll = true;
657 }
658 // Only works when target memories are last to be listed in Location.
659 continue;
660 }
661
662 switch (Loc) {
664 OS << "argmem: ";
665 break;
667 OS << "inaccessiblemem: ";
668 break;
670 OS << "errnomem: ";
671 break;
673 llvm_unreachable("This is represented as the default access kind");
675 OS << "target_mem0: ";
676 break;
678 OS << "target_mem1: ";
679 break;
680 }
681 OS << getModRefStr(MR);
682 }
683 OS << ")";
684 return Result;
685 }
686
687 if (hasAttribute(Attribute::Captures)) {
688 std::string Result;
690 return Result;
691 }
692
693 if (hasAttribute(Attribute::DenormalFPEnv)) {
694 std::string Result = "denormal_fpenv(";
695 raw_string_ostream OS(Result);
696
697 struct DenormalFPEnv FPEnv = getDenormalFPEnv();
698 FPEnv.print(OS, /*OmitIfSame=*/true);
699
700 OS << ')';
701 return Result;
702 }
703
704 if (hasAttribute(Attribute::NoFPClass)) {
705 std::string Result = "nofpclass";
706 raw_string_ostream(Result) << getNoFPClass();
707 return Result;
708 }
709
710 if (hasAttribute(Attribute::Range)) {
711 std::string Result;
712 raw_string_ostream OS(Result);
714 OS << "range(";
715 OS << "i" << CR.getBitWidth() << " ";
716 OS << CR.getLower() << ", " << CR.getUpper();
717 OS << ")";
718 return Result;
719 }
720
721 if (hasAttribute(Attribute::Initializes)) {
722 std::string Result;
723 raw_string_ostream OS(Result);
725 OS << "initializes(";
726 CRL.print(OS);
727 OS << ")";
728 return Result;
729 }
730
731 // Convert target-dependent attributes to strings of the form:
732 //
733 // "kind"
734 // "kind" = "value"
735 //
736 if (isStringAttribute()) {
737 std::string Result;
738 {
739 raw_string_ostream OS(Result);
740 OS << '"' << getKindAsString() << '"';
741
742 // Since some attribute strings contain special characters that cannot be
743 // printable, those have to be escaped to make the attribute value
744 // printable as is. e.g. "\01__gnu_mcount_nc"
745 const auto &AttrVal = pImpl->getValueAsString();
746 if (!AttrVal.empty()) {
747 OS << "=\"";
748 printEscapedString(AttrVal, OS);
749 OS << "\"";
750 }
751 }
752 return Result;
753 }
754
755 llvm_unreachable("Unknown attribute");
756}
757
759 assert(isValid() && "invalid Attribute doesn't refer to any context");
760 LLVMContextImpl *pI = C.pImpl;
762 if (pImpl->isEnumAttribute())
763 return pI->EnumAttrs[pImpl->getKindAsEnum() - FirstEnumAttr] == pImpl;
764 if (pImpl->isIntAttribute())
765 return pI->IntAttrs.lookup({pImpl->getKindAsEnum(), pImpl->getValueAsInt()},
766 Token) == pImpl;
767 if (pImpl->isStringAttribute())
768 return pI->StringAttrs.lookup(
769 {pImpl->getKindAsString(), pImpl->getValueAsString()}, Token) ==
770 pImpl;
771 if (pImpl->isTypeAttribute())
772 return pI->TypeAttrs.lookup(
773 {pImpl->getKindAsEnum(), pImpl->getValueAsType()}, Token) ==
774 pImpl;
776 pImpl->Profile(ID);
777 return pI->AttrsSet.lookup(ID, Token) == pImpl;
778}
779
780int Attribute::cmpKind(Attribute A) const {
781 if (!pImpl && !A.pImpl)
782 return 0;
783 if (!pImpl)
784 return 1;
785 if (!A.pImpl)
786 return -1;
787 return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
788}
789
790bool Attribute::operator<(Attribute A) const {
791 if (!pImpl && !A.pImpl) return false;
792 if (!pImpl) return true;
793 if (!A.pImpl) return false;
794 return *pImpl < *A.pImpl;
795}
796
798 FnAttr = (1 << 0),
799 ParamAttr = (1 << 1),
800 RetAttr = (1 << 2),
802 IntersectAnd = (1 << 3),
803 IntersectMin = (2 << 3),
804 IntersectCustom = (3 << 3),
806 ABIAttr = (1 << 5),
807};
808
809#define GET_ATTR_PROP_TABLE
810#include "llvm/IR/Attributes.inc"
811
813 unsigned Index = Kind - 1;
814 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
815 return AttrPropTable[Index];
816}
817
819 AttributeProperty Prop) {
820 return getAttributeProperties(Kind) & Prop;
821}
822
826
830
834
838
840 AttributeProperty Prop) {
845 "Unknown intersect property");
846 return (getAttributeProperties(Kind) &
848}
849
862
863//===----------------------------------------------------------------------===//
864// AttributeImpl Definition
865//===----------------------------------------------------------------------===//
866
868 if (isStringAttribute()) return false;
869 return getKindAsEnum() == A;
870}
871
873 if (!isStringAttribute()) return false;
874 return getKindAsString() == Kind;
875}
876
882
885 return static_cast<const IntAttributeImpl *>(this)->getValue();
886}
887
889 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
890 return getValueAsString() == "true";
891}
892
895 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
896}
897
900 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
901}
902
905 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
906}
907
910 return static_cast<const ConstantRangeAttributeImpl *>(this)
911 ->getConstantRangeValue();
912}
913
916 return static_cast<const ConstantRangeListAttributeImpl *>(this)
917 ->getConstantRangeListValue();
918}
919
920int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
921 if (this == &AI)
922 return 0;
923
924 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
925 // relative to their enum value) and then strings.
926 if (!isStringAttribute()) {
927 if (AI.isStringAttribute())
928 return -1;
929
930 if (getKindAsEnum() != AI.getKindAsEnum())
931 return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
932 else if (KindOnly)
933 return 0;
934
935 assert(!AI.isEnumAttribute() && "Non-unique attribute");
936 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
937 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
939 "Unclear how to compare range list");
940 // TODO: Is this actually needed?
941 assert(AI.isIntAttribute() && "Only possibility left");
942 if (getValueAsInt() < AI.getValueAsInt())
943 return -1;
944 return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
945 }
946 if (!AI.isStringAttribute())
947 return 1;
948 if (KindOnly)
950 if (getKindAsString() == AI.getKindAsString())
953}
954
956 return cmp(AI, /*KindOnly=*/false) < 0;
957}
958
959//===----------------------------------------------------------------------===//
960// AttributeSet Definition
961//===----------------------------------------------------------------------===//
962
963AttributeSet::AttributeSet(AttributeSetNode *ASN) : SetNode(ASN) {}
964
965AttributeSetNode *AttributeSet::getNode() const {
966 return static_cast<AttributeSetNode *>(SetNode);
967}
968
969AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
971}
972
976
978 Attribute::AttrKind Kind) const {
979 if (hasAttribute(Kind)) return *this;
980 AttrBuilder B(C);
981 B.addAttribute(Kind);
983}
984
986 StringRef Value) const {
987 AttrBuilder B(C);
988 B.addAttribute(Kind, Value);
990}
991
993 const AttributeSet AS) const {
994 if (!hasAttributes())
995 return AS;
996
997 if (!AS.hasAttributes())
998 return *this;
999
1000 AttrBuilder B(C, *this);
1001 B.merge(AttrBuilder(C, AS));
1002 return get(C, B);
1003}
1004
1006 const AttrBuilder &B) const {
1007 if (!hasAttributes())
1008 return get(C, B);
1009
1010 if (!B.hasAttributes())
1011 return *this;
1012
1013 AttrBuilder Merged(C, *this);
1014 Merged.merge(B);
1015 return get(C, Merged);
1016}
1017
1019 Attribute::AttrKind Kind) const {
1020 if (!hasAttribute(Kind)) return *this;
1021 AttrBuilder B(C, *this);
1022 B.removeAttribute(Kind);
1023 return get(C, B);
1024}
1025
1027 StringRef Kind) const {
1028 if (!hasAttribute(Kind)) return *this;
1029 AttrBuilder B(C, *this);
1030 B.removeAttribute(Kind);
1031 return get(C, B);
1032}
1033
1035 const AttributeMask &Attrs) const {
1036 AttrBuilder B(C, *this);
1037 // If there is nothing to remove, directly return the original set.
1038 if (!B.overlaps(Attrs))
1039 return *this;
1040
1041 B.remove(Attrs);
1042 return get(C, B);
1043}
1044
1045std::optional<AttributeSet>
1047 if (*this == Other)
1048 return *this;
1049
1050 AttrBuilder Intersected(C);
1051 // Iterate over both attr sets at once.
1052 auto ItBegin0 = begin();
1053 auto ItEnd0 = end();
1054 auto ItBegin1 = Other.begin();
1055 auto ItEnd1 = Other.end();
1056
1057 while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
1058 // Loop through all attributes in both this and Other in sorted order. If
1059 // the attribute is only present in one of the sets, it will be set in
1060 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
1061 Attribute Attr0, Attr1;
1062 if (ItBegin1 == ItEnd1)
1063 Attr0 = *ItBegin0++;
1064 else if (ItBegin0 == ItEnd0)
1065 Attr0 = *ItBegin1++;
1066 else {
1067 int Cmp = ItBegin0->cmpKind(*ItBegin1);
1068 if (Cmp == 0) {
1069 Attr0 = *ItBegin0++;
1070 Attr1 = *ItBegin1++;
1071 } else if (Cmp < 0)
1072 Attr0 = *ItBegin0++;
1073 else
1074 Attr0 = *ItBegin1++;
1075 }
1076 assert(Attr0.isValid() && "Iteration should always yield a valid attr");
1077
1078 auto IntersectEq = [&]() {
1079 if (!Attr1.isValid())
1080 return false;
1081 if (Attr0 != Attr1)
1082 return false;
1083 Intersected.addAttribute(Attr0);
1084 return true;
1085 };
1086
1087 // Non-enum assume we must preserve. Handle early so we can unconditionally
1088 // use Kind below.
1089 if (!Attr0.hasKindAsEnum()) {
1090 if (!IntersectEq())
1091 return std::nullopt;
1092 continue;
1093 }
1094
1095 Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1096 // If we don't have both attributes, then fail if the attribute is
1097 // must-preserve or drop it otherwise.
1098 if (!Attr1.isValid()) {
1100 return std::nullopt;
1101 continue;
1102 }
1103
1104 // We have both attributes so apply the intersection rule.
1105 assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1106 "Iterator picked up two different attributes in the same iteration");
1107
1108 // Attribute we can intersect with "and"
1109 if (Attribute::intersectWithAnd(Kind)) {
1111 "Invalid attr type of intersectAnd");
1112 Intersected.addAttribute(Kind);
1113 continue;
1114 }
1115
1116 // Attribute we can intersect with "min"
1117 if (Attribute::intersectWithMin(Kind)) {
1119 "Invalid attr type of intersectMin");
1120 uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1121 Intersected.addRawIntAttr(Kind, NewVal);
1122 continue;
1123 }
1124 // Attribute we can intersect but need a custom rule for.
1126 switch (Kind) {
1127 case Attribute::Alignment:
1128 // If `byval` is present, alignment become must-preserve. This is
1129 // handled below if we have `byval`.
1130 Intersected.addAlignmentAttr(
1131 std::min(Attr0.getAlignment().valueOrOne(),
1132 Attr1.getAlignment().valueOrOne()));
1133 break;
1134 case Attribute::Memory:
1135 Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1136 Attr1.getMemoryEffects());
1137 break;
1138 case Attribute::Captures:
1139 Intersected.addCapturesAttr(Attr0.getCaptureInfo() |
1140 Attr1.getCaptureInfo());
1141 break;
1142 case Attribute::NoFPClass:
1143 Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1144 Attr1.getNoFPClass());
1145 break;
1146 case Attribute::Range: {
1147 ConstantRange Range0 = Attr0.getRange();
1148 ConstantRange Range1 = Attr1.getRange();
1149 ConstantRange NewRange = Range0.unionWith(Range1);
1150 if (!NewRange.isFullSet())
1151 Intersected.addRangeAttr(NewRange);
1152 } break;
1153 default:
1154 llvm_unreachable("Unknown attribute with custom intersection rule");
1155 }
1156 continue;
1157 }
1158
1159 // Attributes with no intersection rule. Only intersect if they are equal.
1160 // Otherwise fail.
1161 if (!IntersectEq())
1162 return std::nullopt;
1163
1164 // Special handling of `byval`. `byval` essentially turns align attr into
1165 // must-preserve
1166 if (Kind == Attribute::ByVal &&
1167 getAttribute(Attribute::Alignment) !=
1168 Other.getAttribute(Attribute::Alignment))
1169 return std::nullopt;
1170 }
1171
1172 return get(C, Intersected);
1173}
1174
1176 return SetNode ? getNode()->getNumAttributes() : 0;
1177}
1178
1179
1181 return SetNode ? getNode()->hasAttribute(Kind) : false;
1182}
1183
1185 return SetNode ? getNode()->getAttribute(Kind) : Attribute();
1186}
1187
1189 return SetNode ? getNode()->getAttribute(Kind) : Attribute();
1190}
1191
1193 return SetNode ? getNode()->getAlignment() : std::nullopt;
1194}
1195
1197 return SetNode ? getNode()->getStackAlignment() : std::nullopt;
1198}
1199
1201 return SetNode ? getNode()->getDereferenceableBytes() : 0;
1202}
1203
1205 return SetNode ? getNode()->getDeadOnReturnInfo() : DeadOnReturnInfo(0);
1206}
1207
1209 return SetNode ? getNode()->getDereferenceableOrNullBytes() : 0;
1210}
1211
1213 return SetNode ? getNode()->getAttributeType(Attribute::ByRef) : nullptr;
1214}
1215
1217 return SetNode ? getNode()->getAttributeType(Attribute::ByVal) : nullptr;
1218}
1219
1221 return SetNode ? getNode()->getAttributeType(Attribute::StructRet) : nullptr;
1222}
1223
1225 return SetNode ? getNode()->getAttributeType(Attribute::Preallocated)
1226 : nullptr;
1227}
1228
1230 return SetNode ? getNode()->getAttributeType(Attribute::InAlloca) : nullptr;
1231}
1232
1234 return SetNode ? getNode()->getAttributeType(Attribute::ElementType)
1235 : nullptr;
1236}
1237
1238std::optional<std::pair<unsigned, std::optional<unsigned>>>
1240 if (SetNode)
1241 return getNode()->getAllocSizeArgs();
1242 return std::nullopt;
1243}
1244
1246 return SetNode ? getNode()->getVScaleRangeMin() : 1;
1247}
1248
1249std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1250 return SetNode ? getNode()->getVScaleRangeMax() : std::nullopt;
1251}
1252
1254 return SetNode ? getNode()->getUWTableKind() : UWTableKind::None;
1255}
1256
1258 return SetNode ? getNode()->getAllocKind() : AllocFnKind::Unknown;
1259}
1260
1262 return SetNode ? getNode()->getMemoryEffects() : MemoryEffects::unknown();
1263}
1264
1266 return SetNode ? getNode()->getCaptureInfo() : CaptureInfo::all();
1267}
1268
1270 return SetNode ? getNode()->getNoFPClass() : fcNone;
1271}
1272
1273std::string AttributeSet::getAsString(bool InAttrGrp) const {
1274 return SetNode ? getNode()->getAsString(InAttrGrp) : "";
1275}
1276
1278 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1280 return C.pImpl->AttrsSetNodes.lookup(getNode()->getKey(), Token) == SetNode;
1281}
1282
1284 return SetNode ? getNode()->begin() : nullptr;
1285}
1286
1288 return SetNode ? getNode()->end() : nullptr;
1289}
1290
1291#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1293 dbgs() << "AS =\n";
1294 dbgs() << " { ";
1295 dbgs() << getAsString(true) << " }\n";
1296}
1297#endif
1298
1299//===----------------------------------------------------------------------===//
1300// AttributeSetNode Definition
1301//===----------------------------------------------------------------------===//
1302
1303AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1304 : NumAttrs(Attrs.size()) {
1305 // There's memory after the node where we can store the entries in.
1306 llvm::copy(Attrs, getTrailingObjects());
1307
1308 for (const auto &I : *this) {
1309 if (I.isStringAttribute())
1310 StringAttrs.insert({ I.getKindAsString(), I });
1311 else
1312 AvailableAttrs.addAttribute(I.getKindAsEnum());
1313 }
1314}
1315
1317 ArrayRef<Attribute> Attrs) {
1318 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1319 llvm::sort(SortedAttrs);
1320 return getSorted(C, SortedAttrs);
1321}
1322
1323/// Attribute comparator that only compares attribute keys. Enum attributes are
1324/// sorted before string attributes.
1326 bool operator()(Attribute A0, Attribute A1) const {
1327 bool A0IsString = A0.isStringAttribute();
1328 bool A1IsString = A1.isStringAttribute();
1329 if (A0IsString) {
1330 if (A1IsString)
1331 return A0.getKindAsString() < A1.getKindAsString();
1332 else
1333 return false;
1334 }
1335 if (A1IsString)
1336 return true;
1337 return A0.getKindAsEnum() < A1.getKindAsEnum();
1338 }
1340 if (A0.isStringAttribute())
1341 return false;
1342 return A0.getKindAsEnum() < Kind;
1343 }
1344 bool operator()(Attribute A0, StringRef Kind) const {
1345 if (A0.isStringAttribute())
1346 return A0.getKindAsString() < Kind;
1347 return true;
1348 }
1349};
1350
1351#ifndef NDEBUG
1352/// Return true if \p Attrs is known sorted with no duplicate entries.
1354 return adjacent_find(Attrs, [](Attribute A0, Attribute A1) {
1355 return !AttributeComparator()(A0, A1);
1356 }) == Attrs.end();
1357}
1358#endif
1359
1361 ArrayRef<Attribute> SortedAttrs) {
1362 if (SortedAttrs.empty())
1363 return nullptr;
1364
1365 assert(isSortedAndUnique(SortedAttrs) &&
1366 "expected sorted and unique attributes!");
1367
1369 AttributeSetNode *PA = C.pImpl->AttrsSetNodes.lookup(SortedAttrs, Token);
1370
1371 // If we didn't find any existing attributes of the same shape then create a
1372 // new one and insert it.
1373 if (!PA) {
1374 // Coallocate entries after the AttributeSetNode itself.
1375 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1376 PA = new (Mem) AttributeSetNode(SortedAttrs);
1377 C.pImpl->AttrsSetNodes.insert(PA, Token);
1378 }
1379
1380 // Return the AttributeSetNode that we found or created.
1381 return PA;
1382}
1383
1384AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
1385 return getSorted(C, B.attrs());
1386}
1387
1389 return StringAttrs.count(Kind);
1390}
1391
1392std::optional<Attribute>
1393AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1394 // Do a quick presence check.
1395 if (!hasAttribute(Kind))
1396 return std::nullopt;
1397
1398 // Attributes in a set are sorted by enum value, followed by string
1399 // attributes. Binary search the one we want.
1400 const Attribute *I =
1401 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1402 [](Attribute A, Attribute::AttrKind Kind) {
1403 return A.getKindAsEnum() < Kind;
1404 });
1405 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1406 return *I;
1407}
1408
1410 if (auto A = findEnumAttribute(Kind))
1411 return *A;
1412 return {};
1413}
1414
1416 return StringAttrs.lookup(Kind);
1417}
1418
1420 if (auto A = findEnumAttribute(Attribute::Alignment))
1421 return A->getAlignment();
1422 return std::nullopt;
1423}
1424
1426 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1427 return A->getStackAlignment();
1428 return std::nullopt;
1429}
1430
1432 if (auto A = findEnumAttribute(Kind))
1433 return A->getValueAsType();
1434 return nullptr;
1435}
1436
1438 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1439 return A->getDereferenceableBytes();
1440 return 0;
1441}
1442
1444 if (auto A = findEnumAttribute(Attribute::DeadOnReturn))
1445 return A->getDeadOnReturnInfo();
1446 return 0;
1447}
1448
1450 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1451 return A->getDereferenceableOrNullBytes();
1452 return 0;
1453}
1454
1455std::optional<std::pair<unsigned, std::optional<unsigned>>>
1457 if (auto A = findEnumAttribute(Attribute::AllocSize))
1458 return A->getAllocSizeArgs();
1459 return std::nullopt;
1460}
1461
1463 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1464 return A->getVScaleRangeMin();
1465 return 1;
1466}
1467
1468std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1469 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1470 return A->getVScaleRangeMax();
1471 return std::nullopt;
1472}
1473
1475 if (auto A = findEnumAttribute(Attribute::UWTable))
1476 return A->getUWTableKind();
1477 return UWTableKind::None;
1478}
1479
1481 if (auto A = findEnumAttribute(Attribute::AllocKind))
1482 return A->getAllocKind();
1483 return AllocFnKind::Unknown;
1484}
1485
1487 if (auto A = findEnumAttribute(Attribute::Memory))
1488 return A->getMemoryEffects();
1489 return MemoryEffects::unknown();
1490}
1491
1493 if (auto A = findEnumAttribute(Attribute::Captures))
1494 return A->getCaptureInfo();
1495 return CaptureInfo::all();
1496}
1497
1499 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1500 return A->getNoFPClass();
1501 return fcNone;
1502}
1503
1504std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1505 std::string Str;
1506 for (iterator I = begin(), E = end(); I != E; ++I) {
1507 if (I != begin())
1508 Str += ' ';
1509 Str += I->getAsString(InAttrGrp);
1510 }
1511 return Str;
1512}
1513
1514//===----------------------------------------------------------------------===//
1515// AttributeListImpl Definition
1516//===----------------------------------------------------------------------===//
1517
1518/// Map from AttributeList index to the internal array index. Adding one happens
1519/// to work, because -1 wraps around to 0.
1520static unsigned attrIdxToArrayIdx(unsigned Index) {
1521 return Index + 1;
1522}
1523
1525 : NumAttrSets(Sets.size()) {
1526 assert(!Sets.empty() && "pointless AttributeListImpl");
1527
1528 // There's memory after the node where we can store the entries in.
1530
1531 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1532 // summary bitsets.
1533 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1534 if (!I.isStringAttribute())
1535 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1536
1537 for (const auto &Set : Sets)
1538 for (const auto &I : Set)
1539 if (!I.isStringAttribute())
1540 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1541}
1542
1544 unsigned *Index) const {
1545 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1546 return false;
1547
1548 if (Index) {
1549 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1550 if (begin()[I].hasAttribute(Kind)) {
1551 *Index = I - 1;
1552 break;
1553 }
1554 }
1555 }
1556
1557 return true;
1558}
1559
1560
1561#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1563 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1564}
1565#endif
1566
1567//===----------------------------------------------------------------------===//
1568// AttributeList Construction and Mutation Methods
1569//===----------------------------------------------------------------------===//
1570
1571AttributeList::AttributeList(AttributeListImpl *LI) : pImpl(LI) {}
1572
1573AttributeListImpl *AttributeList::getListImpl() const {
1574 return static_cast<AttributeListImpl *>(pImpl);
1575}
1576
1577AttributeList AttributeList::getImpl(LLVMContext &C,
1578 ArrayRef<AttributeSet> AttrSets) {
1579 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1580
1581 LLVMContextImpl *pImpl = C.pImpl;
1583 AttributeListImpl *PA = pImpl->AttrsLists.lookup(AttrSets, Token);
1584
1585 // If we didn't find any existing attributes of the same shape then
1586 // create a new one and insert it.
1587 if (!PA) {
1588 // Coallocate entries after the AttributeListImpl itself.
1589 void *Mem = pImpl->Alloc.Allocate(
1591 alignof(AttributeListImpl));
1592 PA = new (Mem) AttributeListImpl(AttrSets);
1593 pImpl->AttrsLists.insert(PA, Token);
1594 }
1595
1596 // Return the AttributesList that we found or created.
1597 return AttributeList(PA);
1598}
1599
1600AttributeList
1601AttributeList::get(LLVMContext &C,
1602 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1603 // If there are no attributes then return a null AttributesList pointer.
1604 if (Attrs.empty())
1605 return {};
1606
1608 "Misordered Attributes list!");
1609 assert(llvm::all_of(Attrs,
1610 [](const std::pair<unsigned, Attribute> &Pair) {
1611 return Pair.second.isValid();
1612 }) &&
1613 "Pointless attribute!");
1614
1615 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1616 // list.
1618 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1619 E = Attrs.end(); I != E; ) {
1620 unsigned Index = I->first;
1622 while (I != E && I->first == Index) {
1623 AttrVec.push_back(I->second);
1624 ++I;
1625 }
1626
1627 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1628 }
1629
1630 return get(C, AttrPairVec);
1631}
1632
1633AttributeList
1634AttributeList::get(LLVMContext &C,
1635 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1636 // If there are no attributes then return a null AttributesList pointer.
1637 if (Attrs.empty())
1638 return {};
1639
1641 "Misordered Attributes list!");
1642 assert(llvm::none_of(Attrs,
1643 [](const std::pair<unsigned, AttributeSet> &Pair) {
1644 return !Pair.second.hasAttributes();
1645 }) &&
1646 "Pointless attribute!");
1647
1648 unsigned MaxIndex = Attrs.back().first;
1649 // If the MaxIndex is FunctionIndex and there are other indices in front
1650 // of it, we need to use the largest of those to get the right size.
1651 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1652 MaxIndex = Attrs[Attrs.size() - 2].first;
1653
1654 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1655 for (const auto &Pair : Attrs)
1656 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1657
1658 return getImpl(C, AttrVec);
1659}
1660
1661AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1662 AttributeSet RetAttrs,
1663 ArrayRef<AttributeSet> ArgAttrs) {
1664 // Scan from the end to find the last argument with attributes. Most
1665 // arguments don't have attributes, so it's nice if we can have fewer unique
1666 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1667 unsigned NumSets = 0;
1668 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1669 if (ArgAttrs[I - 1].hasAttributes()) {
1670 NumSets = I + 2;
1671 break;
1672 }
1673 }
1674 if (NumSets == 0) {
1675 // Check function and return attributes if we didn't have argument
1676 // attributes.
1677 if (RetAttrs.hasAttributes())
1678 NumSets = 2;
1679 else if (FnAttrs.hasAttributes())
1680 NumSets = 1;
1681 }
1682
1683 // If all attribute sets were empty, we can use the empty attribute list.
1684 if (NumSets == 0)
1685 return {};
1686
1688 AttrSets.reserve(NumSets);
1689 // If we have any attributes, we always have function attributes.
1690 AttrSets.push_back(FnAttrs);
1691 if (NumSets > 1)
1692 AttrSets.push_back(RetAttrs);
1693 if (NumSets > 2) {
1694 // Drop the empty argument attribute sets at the end.
1695 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1696 llvm::append_range(AttrSets, ArgAttrs);
1697 }
1698
1699 return getImpl(C, AttrSets);
1700}
1701
1702AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1703 AttributeSet Attrs) {
1704 if (!Attrs.hasAttributes())
1705 return {};
1706 Index = attrIdxToArrayIdx(Index);
1707 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1708 AttrSets[Index] = Attrs;
1709 return getImpl(C, AttrSets);
1710}
1711
1712AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1713 const AttrBuilder &B) {
1714 return get(C, Index, AttributeSet::get(C, B));
1715}
1716
1717AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1720 for (const auto K : Kinds)
1721 Attrs.emplace_back(Index, Attribute::get(C, K));
1722 return get(C, Attrs);
1723}
1724
1725AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1728 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1730 auto VI = Values.begin();
1731 for (const auto K : Kinds)
1732 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1733 return get(C, Attrs);
1734}
1735
1736AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1737 ArrayRef<StringRef> Kinds) {
1739 for (const auto &K : Kinds)
1740 Attrs.emplace_back(Index, Attribute::get(C, K));
1741 return get(C, Attrs);
1742}
1743
1744AttributeList AttributeList::get(LLVMContext &C,
1746 if (Attrs.empty())
1747 return {};
1748 if (Attrs.size() == 1)
1749 return Attrs[0];
1750
1751 unsigned MaxSize = 0;
1752 for (const auto &List : Attrs)
1753 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1754
1755 // If every list was empty, there is no point in merging the lists.
1756 if (MaxSize == 0)
1757 return {};
1758
1759 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1760 for (unsigned I = 0; I < MaxSize; ++I) {
1761 AttrBuilder CurBuilder(C);
1762 for (const auto &List : Attrs)
1763 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1764 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1765 }
1766
1767 return getImpl(C, NewAttrSets);
1768}
1769
1770AttributeList
1771AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1772 Attribute::AttrKind Kind) const {
1774 if (Attrs.hasAttribute(Kind))
1775 return *this;
1776 // TODO: Insert at correct position and avoid sort.
1777 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1778 NewAttrs.push_back(Attribute::get(C, Kind));
1779 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1780}
1781
1782AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1783 StringRef Kind,
1784 StringRef Value) const {
1785 AttrBuilder B(C);
1786 B.addAttribute(Kind, Value);
1787 return addAttributesAtIndex(C, Index, B);
1788}
1789
1790AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1791 Attribute A) const {
1792 AttrBuilder B(C);
1793 B.addAttribute(A);
1794 return addAttributesAtIndex(C, Index, B);
1795}
1796
1797AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1798 unsigned Index,
1799 AttributeSet Attrs) const {
1800 Index = attrIdxToArrayIdx(Index);
1801 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1802 if (Index >= AttrSets.size())
1803 AttrSets.resize(Index + 1);
1804 AttrSets[Index] = Attrs;
1805
1806 // Remove trailing empty attribute sets.
1807 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1808 AttrSets.pop_back();
1809 if (AttrSets.empty())
1810 return {};
1811 return AttributeList::getImpl(C, AttrSets);
1812}
1813
1814AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1815 unsigned Index,
1816 const AttrBuilder &B) const {
1817 if (!B.hasAttributes())
1818 return *this;
1819
1820 if (!pImpl)
1821 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1822
1823 AttrBuilder Merged(C, getAttributes(Index));
1824 Merged.merge(B);
1825 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1826}
1827
1828AttributeList
1829AttributeList::addSortedAttributesAtIndex(LLVMContext &C, unsigned Index,
1830 ArrayRef<Attribute> Attrs) const {
1831 if (Attrs.empty())
1832 return *this;
1833 return setAttributesAtIndex(
1834 C, Index, getAttributes(Index).addSortedAttributes(C, Attrs));
1835}
1836
1837AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1838 ArrayRef<unsigned> ArgNos,
1839 Attribute A) const {
1840 assert(llvm::is_sorted(ArgNos));
1841
1842 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1843 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1844 if (MaxIndex >= AttrSets.size())
1845 AttrSets.resize(MaxIndex + 1);
1846
1847 for (unsigned ArgNo : ArgNos) {
1848 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1849 AttrBuilder B(C, AttrSets[Index]);
1850 B.addAttribute(A);
1851 AttrSets[Index] = AttributeSet::get(C, B);
1852 }
1853
1854 return getImpl(C, AttrSets);
1855}
1856
1857AttributeList
1858AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1859 Attribute::AttrKind Kind) const {
1861 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1862 if (Attrs == NewAttrs)
1863 return *this;
1864 return setAttributesAtIndex(C, Index, NewAttrs);
1865}
1866
1867AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1868 unsigned Index,
1869 StringRef Kind) const {
1871 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1872 if (Attrs == NewAttrs)
1873 return *this;
1874 return setAttributesAtIndex(C, Index, NewAttrs);
1875}
1876
1877AttributeList AttributeList::removeAttributesAtIndex(
1878 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1880 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1881 // If nothing was removed, return the original list.
1882 if (Attrs == NewAttrs)
1883 return *this;
1884 return setAttributesAtIndex(C, Index, NewAttrs);
1885}
1886
1887AttributeList
1888AttributeList::removeAttributesAtIndex(LLVMContext &C,
1889 unsigned WithoutIndex) const {
1890 if (!pImpl)
1891 return {};
1892 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1893 return *this;
1894 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1895}
1896
1897AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1898 uint64_t Bytes) const {
1899 AttrBuilder B(C);
1900 B.addDereferenceableAttr(Bytes);
1901 return addRetAttributes(C, B);
1902}
1903
1904AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1905 unsigned Index,
1906 uint64_t Bytes) const {
1907 AttrBuilder B(C);
1908 B.addDereferenceableAttr(Bytes);
1909 return addParamAttributes(C, Index, B);
1910}
1911
1912AttributeList
1913AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1914 uint64_t Bytes) const {
1915 AttrBuilder B(C);
1916 B.addDereferenceableOrNullAttr(Bytes);
1917 return addParamAttributes(C, Index, B);
1918}
1919
1920AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
1921 const ConstantRange &CR) const {
1922 AttrBuilder B(C);
1923 B.addRangeAttr(CR);
1924 return addRetAttributes(C, B);
1925}
1926
1927AttributeList AttributeList::addAllocSizeParamAttr(
1928 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1929 const std::optional<unsigned> &NumElemsArg) const {
1930 AttrBuilder B(C);
1931 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1932 return addParamAttributes(C, Index, B);
1933}
1934
1935std::optional<AttributeList>
1936AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
1937 // Trivial case, the two lists are equal.
1938 if (*this == Other)
1939 return *this;
1940
1942 auto IndexIt =
1943 index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1944 for (unsigned Idx : IndexIt) {
1945 auto IntersectedAS =
1946 getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1947 // If any index fails to intersect, fail.
1948 if (!IntersectedAS)
1949 return std::nullopt;
1950 if (!IntersectedAS->hasAttributes())
1951 continue;
1952 IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1953 }
1954
1955 llvm::sort(IntersectedAttrs, llvm::less_first());
1956 return AttributeList::get(C, IntersectedAttrs);
1957}
1958
1959//===----------------------------------------------------------------------===//
1960// AttributeList Accessor Methods
1961//===----------------------------------------------------------------------===//
1962
1963AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1964 return getAttributes(ArgNo + FirstArgIndex);
1965}
1966
1967AttributeSet AttributeList::getRetAttrs() const {
1968 return getAttributes(ReturnIndex);
1969}
1970
1971AttributeSet AttributeList::getFnAttrs() const {
1972 return getAttributes(FunctionIndex);
1973}
1974
1975bool AttributeList::hasAttributeAtIndex(unsigned Index,
1976 Attribute::AttrKind Kind) const {
1977 return getAttributes(Index).hasAttribute(Kind);
1978}
1979
1980bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1981 return getAttributes(Index).hasAttribute(Kind);
1982}
1983
1984bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1985 return getAttributes(Index).hasAttributes();
1986}
1987
1988
1989bool AttributeList::hasFnAttr(StringRef Kind) const {
1990 return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1991}
1992
1993bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1994 unsigned *Index) const {
1995 return pImpl && getListImpl()->hasAttrSomewhere(Attr, Index);
1996}
1997
1998Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1999 Attribute::AttrKind Kind) const {
2000 return getAttributes(Index).getAttribute(Kind);
2001}
2002
2003Attribute AttributeList::getAttributeAtIndex(unsigned Index,
2004 StringRef Kind) const {
2005 return getAttributes(Index).getAttribute(Kind);
2006}
2007
2008MaybeAlign AttributeList::getRetAlignment() const {
2009 return getAttributes(ReturnIndex).getAlignment();
2010}
2011
2012MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
2013 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
2014}
2015
2016MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
2017 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
2018}
2019
2020Type *AttributeList::getParamByValType(unsigned Index) const {
2021 return getAttributes(Index+FirstArgIndex).getByValType();
2022}
2023
2024Type *AttributeList::getParamStructRetType(unsigned Index) const {
2025 return getAttributes(Index + FirstArgIndex).getStructRetType();
2026}
2027
2028Type *AttributeList::getParamByRefType(unsigned Index) const {
2029 return getAttributes(Index + FirstArgIndex).getByRefType();
2030}
2031
2032Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
2033 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
2034}
2035
2036Type *AttributeList::getParamInAllocaType(unsigned Index) const {
2037 return getAttributes(Index + FirstArgIndex).getInAllocaType();
2038}
2039
2040Type *AttributeList::getParamElementType(unsigned Index) const {
2041 return getAttributes(Index + FirstArgIndex).getElementType();
2042}
2043
2044MaybeAlign AttributeList::getFnStackAlignment() const {
2045 return getFnAttrs().getStackAlignment();
2046}
2047
2048MaybeAlign AttributeList::getRetStackAlignment() const {
2049 return getRetAttrs().getStackAlignment();
2050}
2051
2052uint64_t AttributeList::getRetDereferenceableBytes() const {
2053 return getRetAttrs().getDereferenceableBytes();
2054}
2055
2056uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
2057 return getParamAttrs(Index).getDereferenceableBytes();
2058}
2059
2060uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
2061 return getRetAttrs().getDereferenceableOrNullBytes();
2062}
2063
2064DeadOnReturnInfo AttributeList::getDeadOnReturnInfo(unsigned Index) const {
2065 return getParamAttrs(Index).getDeadOnReturnInfo();
2066}
2067
2069AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
2070 return getParamAttrs(Index).getDereferenceableOrNullBytes();
2071}
2072
2073std::optional<ConstantRange>
2074AttributeList::getParamRange(unsigned ArgNo) const {
2075 auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
2076 if (RangeAttr.isValid())
2077 return RangeAttr.getRange();
2078 return std::nullopt;
2079}
2080
2081FPClassTest AttributeList::getRetNoFPClass() const {
2082 return getRetAttrs().getNoFPClass();
2083}
2084
2085FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {
2086 return getParamAttrs(Index).getNoFPClass();
2087}
2088
2089UWTableKind AttributeList::getUWTableKind() const {
2090 return getFnAttrs().getUWTableKind();
2091}
2092
2093AllocFnKind AttributeList::getAllocKind() const {
2094 return getFnAttrs().getAllocKind();
2095}
2096
2097MemoryEffects AttributeList::getMemoryEffects() const {
2098 return getFnAttrs().getMemoryEffects();
2099}
2100
2101std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
2102 return getAttributes(Index).getAsString(InAttrGrp);
2103}
2104
2105AttributeSet AttributeList::getAttributes(unsigned Index) const {
2106 Index = attrIdxToArrayIdx(Index);
2107 if (!pImpl || Index >= getNumAttrSets())
2108 return {};
2109 return getListImpl()->begin()[Index];
2110}
2111
2112bool AttributeList::hasParentContext(LLVMContext &C) const {
2113 assert(!isEmpty() && "an empty attribute list has no parent context");
2115 return C.pImpl->AttrsLists.lookup(getListImpl()->getKey(), Token) == pImpl;
2116}
2117
2118AttributeList::iterator AttributeList::begin() const {
2119 return pImpl ? getListImpl()->begin() : nullptr;
2120}
2121
2122AttributeList::iterator AttributeList::end() const {
2123 return pImpl ? getListImpl()->end() : nullptr;
2124}
2125
2126//===----------------------------------------------------------------------===//
2127// AttributeList Introspection Methods
2128//===----------------------------------------------------------------------===//
2129
2130unsigned AttributeList::getNumAttrSets() const {
2131 return pImpl ? getListImpl()->NumAttrSets : 0;
2132}
2133
2134void AttributeList::print(raw_ostream &O) const {
2135 O << "AttributeList[\n";
2136
2137 for (unsigned i : indexes()) {
2138 if (!getAttributes(i).hasAttributes())
2139 continue;
2140 O << " { ";
2141 switch (i) {
2142 case AttrIndex::ReturnIndex:
2143 O << "return";
2144 break;
2145 case AttrIndex::FunctionIndex:
2146 O << "function";
2147 break;
2148 default:
2149 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2150 }
2151 O << " => " << getAsString(i) << " }\n";
2152 }
2153
2154 O << "]\n";
2155}
2156
2157#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2158LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
2159#endif
2160
2161//===----------------------------------------------------------------------===//
2162// AttrBuilder Method Implementations
2163//===----------------------------------------------------------------------===//
2164
2165AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
2166 append_range(Attrs, AS);
2167 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2168}
2169
2170void AttrBuilder::clear() { Attrs.clear(); }
2171
2172template <typename K>
2174 Attribute Attr) {
2175 auto It = lower_bound(Attrs, Kind, AttributeComparator());
2176 if (It != Attrs.end() && It->hasAttribute(Kind))
2177 std::swap(*It, Attr);
2178 else
2179 Attrs.insert(It, Attr);
2180}
2181
2182AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
2183 if (Attr.isStringAttribute())
2184 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2185 else
2186 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2187 return *this;
2188}
2189
2190AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
2191 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2192 return *this;
2193}
2194
2195AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
2196 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2197 return *this;
2198}
2199
2200AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
2201 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2202 auto It = lower_bound(Attrs, Val, AttributeComparator());
2203 if (It != Attrs.end() && It->hasAttribute(Val))
2204 Attrs.erase(It);
2205 return *this;
2206}
2207
2208AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
2209 auto It = lower_bound(Attrs, A, AttributeComparator());
2210 if (It != Attrs.end() && It->hasAttribute(A))
2211 Attrs.erase(It);
2212 return *this;
2213}
2214
2215std::optional<uint64_t>
2216AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
2217 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2218 Attribute A = getAttribute(Kind);
2219 if (A.isValid())
2220 return A.getValueAsInt();
2221 return std::nullopt;
2222}
2223
2224AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
2225 uint64_t Value) {
2226 return addAttribute(Attribute::get(Ctx, Kind, Value));
2227}
2228
2229std::optional<std::pair<unsigned, std::optional<unsigned>>>
2230AttrBuilder::getAllocSizeArgs() const {
2231 Attribute A = getAttribute(Attribute::AllocSize);
2232 if (A.isValid())
2233 return A.getAllocSizeArgs();
2234 return std::nullopt;
2235}
2236
2237AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
2238 if (!Align)
2239 return *this;
2240
2241 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2242 return addRawIntAttr(Attribute::Alignment, Align->value());
2243}
2244
2245AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
2246 // Default alignment, allow the target to define how to align it.
2247 if (!Align)
2248 return *this;
2249
2250 assert(*Align <= 0x100 && "Alignment too large.");
2251 return addRawIntAttr(Attribute::StackAlignment, Align->value());
2252}
2253
2254AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
2255 if (Bytes == 0) return *this;
2256
2257 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2258}
2259
2260AttrBuilder &AttrBuilder::addDeadOnReturnAttr(DeadOnReturnInfo Info) {
2261 if (Info.isZeroSized())
2262 return *this;
2263
2264 return addRawIntAttr(Attribute::DeadOnReturn, Info.toIntValue());
2265}
2266
2267AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
2268 if (Bytes == 0)
2269 return *this;
2270
2271 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2272}
2273
2274AttrBuilder &
2275AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
2276 const std::optional<unsigned> &NumElems) {
2277 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2278}
2279
2280AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
2281 // (0, 0) is our "not present" value, so we need to check for it here.
2282 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2283 return addRawIntAttr(Attribute::AllocSize, RawArgs);
2284}
2285
2286AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
2287 std::optional<unsigned> MaxValue) {
2288 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2289}
2290
2291AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
2292 // (0, 0) is not present hence ignore this case
2293 if (RawArgs == 0)
2294 return *this;
2295
2296 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2297}
2298
2299AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
2300 if (Kind == UWTableKind::None)
2301 return *this;
2302 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2303}
2304
2305AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
2306 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2307}
2308
2309AttrBuilder &AttrBuilder::addCapturesAttr(CaptureInfo CI) {
2310 return addRawIntAttr(Attribute::Captures, CI.toIntValue());
2311}
2312
2313AttrBuilder &AttrBuilder::addDenormalFPEnvAttr(DenormalFPEnv FPEnv) {
2314 return addRawIntAttr(Attribute::DenormalFPEnv, FPEnv.toIntValue());
2315}
2316
2317AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
2318 if (Mask == fcNone)
2319 return *this;
2320
2321 return addRawIntAttr(Attribute::NoFPClass, Mask);
2322}
2323
2324AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
2325 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2326}
2327
2328Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
2329 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2330 Attribute A = getAttribute(Kind);
2331 return A.isValid() ? A.getValueAsType() : nullptr;
2332}
2333
2334AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
2335 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2336}
2337
2338AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
2339 return addTypeAttr(Attribute::ByVal, Ty);
2340}
2341
2342AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
2343 return addTypeAttr(Attribute::StructRet, Ty);
2344}
2345
2346AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
2347 return addTypeAttr(Attribute::ByRef, Ty);
2348}
2349
2350AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
2351 return addTypeAttr(Attribute::Preallocated, Ty);
2352}
2353
2354AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
2355 return addTypeAttr(Attribute::InAlloca, Ty);
2356}
2357
2358AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,
2359 const ConstantRange &CR) {
2360 if (CR.isFullSet())
2361 return *this;
2362
2363 return addAttribute(Attribute::get(Ctx, Kind, CR));
2364}
2365
2366AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
2367 return addConstantRangeAttr(Attribute::Range, CR);
2368}
2369
2370AttrBuilder &
2371AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
2373 return addAttribute(Attribute::get(Ctx, Kind, Val));
2374}
2375
2376AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
2377 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2378}
2379
2380AttrBuilder &AttrBuilder::addFromEquivalentMetadata(const Instruction &I) {
2381 if (I.hasMetadata(LLVMContext::MD_nonnull))
2382 addAttribute(Attribute::NonNull);
2383
2384 if (I.hasMetadata(LLVMContext::MD_noundef))
2385 addAttribute(Attribute::NoUndef);
2386
2387 if (const MDNode *Align = I.getMetadata(LLVMContext::MD_align)) {
2388 ConstantInt *CI = mdconst::extract<ConstantInt>(Align->getOperand(0));
2389 addAlignmentAttr(CI->getZExtValue());
2390 }
2391
2392 if (const MDNode *Dereferenceable =
2393 I.getMetadata(LLVMContext::MD_dereferenceable)) {
2394 ConstantInt *CI =
2395 mdconst::extract<ConstantInt>(Dereferenceable->getOperand(0));
2396 addDereferenceableAttr(CI->getZExtValue());
2397 }
2398
2399 if (const MDNode *DereferenceableOrNull =
2400 I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) {
2401 ConstantInt *CI =
2402 mdconst::extract<ConstantInt>(DereferenceableOrNull->getOperand(0));
2403 addDereferenceableAttr(CI->getZExtValue());
2404 }
2405
2406 if (const MDNode *Range = I.getMetadata(LLVMContext::MD_range))
2407 addRangeAttr(getConstantRangeFromMetadata(*Range));
2408
2409 if (const MDNode *NoFPClass = I.getMetadata(LLVMContext::MD_nofpclass)) {
2410 ConstantInt *CI = mdconst::extract<ConstantInt>(NoFPClass->getOperand(0));
2411 addNoFPClassAttr(static_cast<FPClassTest>(CI->getZExtValue()));
2412 }
2413
2414 return *this;
2415}
2416
2417/// Merge \p B into \p A, both sorted by kind, into \p Merged. An attribute
2418/// in \p B replaces the attribute of the same kind in \p A.
2421 Merged.reserve(A.size() + B.size());
2423 auto *I = A.begin(), *E = A.end();
2424
2425 for (Attribute BAttr : B) {
2426 while (I != E && Less(*I, BAttr))
2427 Merged.push_back(*I++);
2428
2429 if (I != E && !Less(BAttr, *I))
2430 ++I;
2431
2432 Merged.push_back(BAttr);
2433 }
2434
2435 Merged.append(I, E);
2436}
2437
2438AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
2439 if (B.Attrs.empty())
2440 return *this;
2441
2442 if (Attrs.empty()) {
2443 Attrs = B.Attrs;
2444 return *this;
2445 }
2446
2447 // Both lists are already sorted by kind.
2449 mergeSortedAttrs(Attrs, B.Attrs, Merged);
2450 Attrs = std::move(Merged);
2451 return *this;
2452}
2453
2456 ArrayRef<Attribute> Attrs) const {
2457 if (Attrs.empty())
2458 return *this;
2459
2460 assert(isSortedAndUnique(Attrs) &&
2461 "Expected sorted attributes with distinct kinds!");
2462
2464 mergeSortedAttrs(ArrayRef(begin(), end()), Attrs, Merged);
2466}
2467
2468AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
2469 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2470 return *this;
2471}
2472
2473bool AttrBuilder::overlaps(const AttributeMask &AM) const {
2474 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2475}
2476
2477Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
2478 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2479 auto It = lower_bound(Attrs, A, AttributeComparator());
2480 if (It != Attrs.end() && It->hasAttribute(A))
2481 return *It;
2482 return {};
2483}
2484
2485Attribute AttrBuilder::getAttribute(StringRef A) const {
2486 auto It = lower_bound(Attrs, A, AttributeComparator());
2487 if (It != Attrs.end() && It->hasAttribute(A))
2488 return *It;
2489 return {};
2490}
2491
2492std::optional<ConstantRange> AttrBuilder::getRange() const {
2493 const Attribute RangeAttr = getAttribute(Attribute::Range);
2494 if (RangeAttr.isValid())
2495 return RangeAttr.getRange();
2496 return std::nullopt;
2497}
2498
2499bool AttrBuilder::contains(Attribute::AttrKind A) const {
2500 return getAttribute(A).isValid();
2501}
2502
2503bool AttrBuilder::contains(StringRef A) const {
2504 return getAttribute(A).isValid();
2505}
2506
2507bool AttrBuilder::operator==(const AttrBuilder &B) const {
2508 return Attrs == B.Attrs;
2509}
2510
2511//===----------------------------------------------------------------------===//
2512// AttributeFuncs Function Defintions
2513//===----------------------------------------------------------------------===//
2514
2515/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2516/// follows the same type rules as FPMathOperator.
2517bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2519}
2520
2521/// Which attributes cannot be applied to a type.
2522AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
2523 AttributeSafetyKind ASK) {
2524 AttributeMask Incompatible;
2525
2526 if (!Ty->isIntegerTy()) {
2527 // Attributes that only apply to integers.
2528 if (ASK & ASK_SAFE_TO_DROP)
2529 Incompatible.addAttribute(Attribute::AllocAlign);
2530 }
2531
2532 if (!Ty->isIntegerTy() && !Ty->isByteTy()) {
2533 // Attributes that only apply to integers and bytes.
2534 if (ASK & ASK_UNSAFE_TO_DROP)
2535 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2536 }
2537
2538 if (!Ty->isIntOrIntVectorTy()) {
2539 // Attributes that only apply to integers or vector of integers.
2540 if (ASK & ASK_SAFE_TO_DROP)
2541 Incompatible.addAttribute(Attribute::Range);
2542 } else {
2543 Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2544 if (RangeAttr.isValid() &&
2545 RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2546 Incompatible.addAttribute(Attribute::Range);
2547 }
2548
2549 if (!Ty->isPointerTy()) {
2550 // Attributes that only apply to pointers.
2551 if (ASK & ASK_SAFE_TO_DROP)
2552 Incompatible.addAttribute(Attribute::NoAlias)
2553 .addAttribute(Attribute::NonNull)
2554 .addAttribute(Attribute::ReadNone)
2555 .addAttribute(Attribute::ReadOnly)
2556 .addAttribute(Attribute::Dereferenceable)
2557 .addAttribute(Attribute::DereferenceableOrNull)
2558 .addAttribute(Attribute::Writable)
2559 .addAttribute(Attribute::DeadOnUnwind)
2560 .addAttribute(Attribute::Initializes)
2561 .addAttribute(Attribute::Captures)
2562 .addAttribute(Attribute::DeadOnReturn)
2563 .addAttribute(Attribute::NoFree)
2564 .addAttribute(Attribute::NoFreeObj);
2565 if (ASK & ASK_UNSAFE_TO_DROP)
2566 Incompatible.addAttribute(Attribute::Nest)
2567 .addAttribute(Attribute::SwiftError)
2568 .addAttribute(Attribute::Preallocated)
2569 .addAttribute(Attribute::InAlloca)
2570 .addAttribute(Attribute::ByVal)
2571 .addAttribute(Attribute::StructRet)
2572 .addAttribute(Attribute::ByRef)
2573 .addAttribute(Attribute::ElementType)
2574 .addAttribute(Attribute::AllocatedPointer);
2575 }
2576
2577 // Attributes that only apply to pointers or vectors of pointers.
2578 if (!Ty->isPtrOrPtrVectorTy()) {
2579 if (ASK & ASK_SAFE_TO_DROP)
2580 Incompatible.addAttribute(Attribute::Alignment);
2581 }
2582
2583 if (ASK & ASK_SAFE_TO_DROP) {
2584 if (!isNoFPClassCompatibleType(Ty))
2585 Incompatible.addAttribute(Attribute::NoFPClass);
2586 }
2587
2588 // Some attributes can apply to all "values" but there are no `void` values.
2589 if (Ty->isVoidTy()) {
2590 if (ASK & ASK_SAFE_TO_DROP)
2591 Incompatible.addAttribute(Attribute::NoUndef);
2592 }
2593
2594 return Incompatible;
2595}
2596
2597AttributeMask AttributeFuncs::getUBImplyingAttributes() {
2598 AttributeMask AM;
2599 AM.addAttribute(Attribute::NoUndef);
2600 AM.addAttribute(Attribute::Dereferenceable);
2601 AM.addAttribute(Attribute::DereferenceableOrNull);
2602 return AM;
2603}
2604
2605AttributeMask AttributeFuncs::getPoisonGeneratingAttributes() {
2606 AttributeMask AM;
2607 AM.addAttribute(Attribute::Range);
2608 AM.addAttribute(Attribute::Alignment);
2609 AM.addAttribute(Attribute::NonNull);
2610 AM.addAttribute(Attribute::NoFPClass);
2611 return AM;
2612}
2613
2614/// Callees with dynamic denormal modes are compatible with any caller mode.
2615static bool denormModeCompatible(DenormalMode CallerMode,
2616 DenormalMode CalleeMode) {
2617 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2618 return true;
2619
2620 // If they don't exactly match, it's OK if the mismatched component is
2621 // dynamic.
2622 if (CalleeMode.Input == CallerMode.Input &&
2623 CalleeMode.Output == DenormalMode::Dynamic)
2624 return true;
2625
2626 if (CalleeMode.Output == CallerMode.Output &&
2627 CalleeMode.Input == DenormalMode::Dynamic)
2628 return true;
2629 return false;
2630}
2631
2632static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2633 DenormalFPEnv CallerEnv = Caller.getDenormalFPEnv();
2634 DenormalFPEnv CalleeEnv = Callee.getDenormalFPEnv();
2635
2636 if (denormModeCompatible(CallerEnv.DefaultMode, CalleeEnv.DefaultMode)) {
2637 DenormalMode CallerModeF32 = CallerEnv.F32Mode;
2638 DenormalMode CalleeModeF32 = CalleeEnv.F32Mode;
2639 if (CallerModeF32 == DenormalMode::getInvalid())
2640 CallerModeF32 = CallerEnv.DefaultMode;
2641 if (CalleeModeF32 == DenormalMode::getInvalid())
2642 CalleeModeF32 = CalleeEnv.DefaultMode;
2643 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2644 }
2645
2646 return false;
2647}
2648
2649static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2650 // Do not inline strictfp function into non-strictfp one. It would require
2651 // conversion of all FP operations in host function to constrained intrinsics.
2652 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2653 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2654}
2655
2656template<typename AttrClass>
2657static bool isEqual(const Function &Caller, const Function &Callee) {
2658 return Caller.getFnAttribute(AttrClass::getKind()) ==
2659 Callee.getFnAttribute(AttrClass::getKind());
2660}
2661
2662static bool isEqual(const Function &Caller, const Function &Callee,
2663 const StringRef &AttrName) {
2664 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2665}
2666
2667/// Compute the logical AND of the attributes of the caller and the
2668/// callee.
2669///
2670/// This function sets the caller's attribute to false if the callee's attribute
2671/// is false.
2672template<typename AttrClass>
2673static void setAND(Function &Caller, const Function &Callee) {
2674 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2675 !AttrClass::isSet(Callee, AttrClass::getKind()))
2676 AttrClass::set(Caller, AttrClass::getKind(), false);
2677}
2678
2679/// Compute the logical OR of the attributes of the caller and the
2680/// callee.
2681///
2682/// This function sets the caller's attribute to true if the callee's attribute
2683/// is true.
2684template<typename AttrClass>
2685static void setOR(Function &Caller, const Function &Callee) {
2686 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2687 AttrClass::isSet(Callee, AttrClass::getKind()))
2688 AttrClass::set(Caller, AttrClass::getKind(), true);
2689}
2690
2691/// If the inlined function had a higher stack protection level than the
2692/// calling function, then bump up the caller's stack protection level.
2693static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2694 // If the calling function has *no* stack protection level (e.g. it was built
2695 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2696 // change it as that could change the program's semantics.
2697 if (!Caller.hasStackProtectorFnAttr())
2698 return;
2699
2700 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2701 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2702 // clutter to the IR.
2703 AttributeMask OldSSPAttr;
2704 OldSSPAttr.addAttribute(Attribute::StackProtect)
2705 .addAttribute(Attribute::StackProtectStrong)
2706 .addAttribute(Attribute::StackProtectReq);
2707
2708 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2709 Caller.removeFnAttrs(OldSSPAttr);
2710 Caller.addFnAttr(Attribute::StackProtectReq);
2711 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2712 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2713 Caller.removeFnAttrs(OldSSPAttr);
2714 Caller.addFnAttr(Attribute::StackProtectStrong);
2715 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2716 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2717 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2718 Caller.addFnAttr(Attribute::StackProtect);
2719}
2720
2721/// If the inlined function required stack probes, then ensure that
2722/// the calling function has those too.
2723static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2724 if (!Caller.hasFnAttribute("probe-stack") &&
2725 Callee.hasFnAttribute("probe-stack")) {
2726 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2727 }
2728}
2729
2730/// If the inlined function defines the size of guard region
2731/// on the stack, then ensure that the calling function defines a guard region
2732/// that is no larger.
2733static void
2735 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2736 if (CalleeAttr.isValid()) {
2737 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2738 if (CallerAttr.isValid()) {
2739 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2740 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2741 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2742
2743 if (CallerStackProbeSize > CalleeStackProbeSize) {
2744 Caller.addFnAttr(CalleeAttr);
2745 }
2746 } else {
2747 Caller.addFnAttr(CalleeAttr);
2748 }
2749 }
2750}
2751
2752/// If the inlined function defines a min legal vector width, then ensure
2753/// the calling function has the same or larger min legal vector width. If the
2754/// caller has the attribute, but the callee doesn't, we need to remove the
2755/// attribute from the caller since we can't make any guarantees about the
2756/// caller's requirements.
2757/// This function is called after the inlining decision has been made so we have
2758/// to merge the attribute this way. Heuristics that would use
2759/// min-legal-vector-width to determine inline compatibility would need to be
2760/// handled as part of inline cost analysis.
2761static void
2763 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2764 if (CallerAttr.isValid()) {
2765 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2766 if (CalleeAttr.isValid()) {
2767 uint64_t CallerVectorWidth, CalleeVectorWidth;
2768 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2769 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2770 if (CallerVectorWidth < CalleeVectorWidth)
2771 Caller.addFnAttr(CalleeAttr);
2772 } else {
2773 // If the callee doesn't have the attribute then we don't know anything
2774 // and must drop the attribute from the caller.
2775 Caller.removeFnAttr("min-legal-vector-width");
2776 }
2777 }
2778}
2779
2780/// If the inlined function has null_pointer_is_valid attribute,
2781/// set this attribute in the caller post inlining.
2782static void
2784 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2785 Caller.addFnAttr(Attribute::NullPointerIsValid);
2786 }
2787}
2788
2789struct EnumAttr {
2790 static bool isSet(const Function &Fn,
2791 Attribute::AttrKind Kind) {
2792 return Fn.hasFnAttribute(Kind);
2793 }
2794
2795 static void set(Function &Fn,
2796 Attribute::AttrKind Kind, bool Val) {
2797 if (Val)
2798 Fn.addFnAttr(Kind);
2799 else
2800 Fn.removeFnAttr(Kind);
2801 }
2802};
2803
2805 static bool isSet(const Function &Fn,
2806 StringRef Kind) {
2807 auto A = Fn.getFnAttribute(Kind);
2808 return A.getValueAsString() == "true";
2809 }
2810
2811 static void set(Function &Fn,
2812 StringRef Kind, bool Val) {
2813 Fn.addFnAttr(Kind, Val ? "true" : "false");
2814 }
2815};
2816
2817#define GET_ATTR_NAMES
2818#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2819 struct ENUM_NAME##Attr : EnumAttr { \
2820 static enum Attribute::AttrKind getKind() { \
2821 return llvm::Attribute::ENUM_NAME; \
2822 } \
2823 };
2824#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2825 struct ENUM_NAME##Attr : StrBoolAttr { \
2826 static StringRef getKind() { return #DISPLAY_NAME; } \
2827 };
2828#include "llvm/IR/Attributes.inc"
2829
2830#define GET_ATTR_COMPAT_FUNC
2831#include "llvm/IR/Attributes.inc"
2832
2833bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2834 const Function &Callee) {
2835 return hasCompatibleFnAttrs(Caller, Callee);
2836}
2837
2838bool AttributeFuncs::isStrictFPInlineCompatible(const Function &Caller,
2839 const Function &Callee) {
2840 return checkStrictFP(Caller, Callee);
2841}
2842
2843bool AttributeFuncs::areOutlineCompatible(const Function &A,
2844 const Function &B) {
2845 return hasCompatibleFnAttrs(A, B);
2846}
2847
2848void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2849 const Function &Callee) {
2850 mergeFnAttrs(Caller, Callee);
2851}
2852
2853void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2854 const Function &ToMerge) {
2855
2856 // We merge functions so that they meet the most general case.
2857 // For example, if the NoNansFPMathAttr is set in one function, but not in
2858 // the other, in the merged function we can say that the NoNansFPMathAttr
2859 // is not set.
2860 // However if we have the SpeculativeLoadHardeningAttr set true in one
2861 // function, but not the other, we make sure that the function retains
2862 // that aspect in the merged function.
2863 mergeFnAttrs(Base, ToMerge);
2864}
2865
2866void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2867 uint64_t Width) {
2868 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2869 if (Attr.isValid()) {
2870 uint64_t OldWidth;
2871 Attr.getValueAsString().getAsInteger(0, OldWidth);
2872 if (Width > OldWidth)
2873 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2874 }
2875}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
uint64_t uint64_t
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
@ ABIAttr
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 bool isSortedAndUnique(ArrayRef< Attribute > Attrs)
Return true if Attrs is known sorted with no duplicate entries.
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 void mergeSortedAttrs(ArrayRef< Attribute > A, ArrayRef< Attribute > B, SmallVectorImpl< Attribute > &Merged)
Merge B into A, both sorted by kind, into Merged.
static const char * getModRefStr(ModRefInfo MR)
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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:690
This file defines a hash set that can be used to remove duplication of nodes in a graph.
static constexpr Value * getValue(Ty &ValueOrUse)
#define I(x, y, z)
Definition MD5.cpp:57
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:152
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & back() const
Get the last element.
Definition ArrayRef.h:150
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:218
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
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
AttributeBitSet AvailableFunctionAttrs
Definition Attributes.h:433
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
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
Type * getAttributeType(Attribute::AttrKind Kind) const
AllocFnKind getAllocKind() const
CaptureInfo getCaptureInfo() const
unsigned getVScaleRangeMin() const
static AttributeSetNode * getSorted(LLVMContext &C, ArrayRef< Attribute > SortedAttrs)
MaybeAlign getAlignment() const
MemoryEffects getMemoryEffects() const
bool hasAttribute(StringRef Kind) 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:448
LLVM_ABI AllocFnKind getAllocKind() const
bool hasAttributes() const
Return true if attributes exists in this set.
Definition Attributes.h:529
const Attribute * iterator
Definition Attributes.h:570
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 std::optional< AttributeSet > intersectWith(LLVMContext &C, AttributeSet Other) const
Try to intersect this AttributeSet with Other.
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
Definition Attributes.h:532
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 addSortedAttributes(LLVMContext &C, ArrayRef< Attribute > Attrs) const
Add attributes to the attribute set, replacing attributes of the same kind.
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:107
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 bool isABIAttr(AttrKind Kind)
Whether this is an ABI attribute (for returns or arguments).
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:146
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 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.
bool hasKindAsEnum() const
Returns true if the attribute's kind can be represented as an enum (Enum, Integer,...
Definition Attributes.h:273
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)
static bool isConstantRangeAttrKind(AttrKind Kind)
Definition Attributes.h:149
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:143
static bool isConstantRangeListAttrKind(AttrKind Kind)
Definition Attributes.h:152
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:140
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:263
LLVM_ABI MaybeAlign getStackAlignment() const
Returns the stack alignment field of an attribute as a byte alignment value.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition Attributes.h:126
@ None
No attributes have been set.
Definition Attributes.h:128
@ EndAttrKinds
Sentinel value useful for loops.
Definition Attributes.h:131
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:414
static CaptureInfo createFromIntValue(uint32_t Data)
Definition ModRef.h:485
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
Definition ModRef.h:430
uint32_t toIntValue() const
Convert CaptureInfo into an encoded integer value (used by captures attribute).
Definition ModRef.h:492
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:81
uint64_t toIntValue() const
Definition Attributes.h:87
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:302
Insertion token: a failed lookup fills it in, the matching insert consumes it.
Definition FoldingSet.h:284
This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:162
void AddInteger(signed I)
Definition FoldingSet.h:190
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition Function.cpp:641
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:766
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition Function.cpp:689
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:731
UniquingSet< TypeAttributeImpl > TypeAttrs
EnumAttributeImpl * EnumAttrs[Attribute::NumEnumAttrKinds]
UniquingSet< IntAttributeImpl > IntAttrs
FoldingSet< AttributeImpl > AttrsSet
UniquingSet< StringAttributeImpl > StringAttrs
UniquingSet< AttributeListImpl > AttrsLists
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
Metadata node.
Definition Metadata.h:1081
bool isTargetMemLocSameForAll() const
Whether the target memory locations are all the same.
Definition ModRef.h:289
bool isTargetMemLoc(IRMemLocation Loc) const
Whether location is target memory location.
Definition ModRef.h:279
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:219
static MemoryEffectsBase createFromIntValue(uint32_t Data)
Definition ModRef.h:208
uint32_t toIntValue() const
Convert MemoryEffectsBase into an encoded integer value (used by memory attribute).
Definition ModRef.h:214
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 append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
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)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:490
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
int compare(StringRef RHS) const
Compare two strings; the result is negative, zero, or positive if this string is lexicographically le...
Definition StringRef.h:177
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:46
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:801
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.
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:679
iterator end() const
Definition BasicBlock.h:89
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
AllocFnKind
Definition Attributes.h:55
auto adjacent_find(R &&Range)
Provide wrappers to std::adjacent_find which finds the first pair of adjacent elements that are equal...
Definition STLExtras.h:1834
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
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:356
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:1762
UWTableKind
Definition CodeGen.h:362
@ None
No unwind table requested.
Definition CodeGen.h:363
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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:1769
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:1986
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:2068
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1901
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:2208
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:881
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:82
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:111
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:135
Function object to check whether the first component of a container supported by std::get (like std::...
Definition STLExtras.h:1455