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