LLVM 20.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/Type.h"
34#include "llvm/Support/ModRef.h"
36#include <algorithm>
37#include <cassert>
38#include <cstddef>
39#include <cstdint>
40#include <limits>
41#include <optional>
42#include <string>
43#include <tuple>
44#include <utility>
45
46using namespace llvm;
47
48//===----------------------------------------------------------------------===//
49// Attribute Construction Methods
50//===----------------------------------------------------------------------===//
51
52// allocsize has two integer arguments, but because they're both 32 bits, we can
53// pack them into one 64-bit value, at the cost of making said value
54// nonsensical.
55//
56// In order to do this, we need to reserve one value of the second (optional)
57// allocsize argument to signify "not present."
58static const unsigned AllocSizeNumElemsNotPresent = -1;
59
60static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
61 const std::optional<unsigned> &NumElemsArg) {
62 assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
63 "Attempting to pack a reserved value");
64
65 return uint64_t(ElemSizeArg) << 32 |
66 NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
67}
68
69static std::pair<unsigned, std::optional<unsigned>>
71 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
72 unsigned ElemSizeArg = Num >> 32;
73
74 std::optional<unsigned> NumElemsArg;
75 if (NumElems != AllocSizeNumElemsNotPresent)
76 NumElemsArg = NumElems;
77 return std::make_pair(ElemSizeArg, NumElemsArg);
78}
79
80static uint64_t packVScaleRangeArgs(unsigned MinValue,
81 std::optional<unsigned> MaxValue) {
82 return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
83}
84
85static std::pair<unsigned, std::optional<unsigned>>
87 unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
88 unsigned MinValue = Value >> 32;
89
90 return std::make_pair(MinValue,
91 MaxValue > 0 ? MaxValue : std::optional<unsigned>());
92}
93
95 uint64_t Val) {
96 bool IsIntAttr = Attribute::isIntAttrKind(Kind);
97 assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
98 "Not an enum or int attribute");
99
100 LLVMContextImpl *pImpl = Context.pImpl;
102 ID.AddInteger(Kind);
103 if (IsIntAttr)
104 ID.AddInteger(Val);
105 else
106 assert(Val == 0 && "Value must be zero for enum attributes");
107
108 void *InsertPoint;
109 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
110
111 if (!PA) {
112 // If we didn't find any existing attributes of the same shape then create a
113 // new one and insert it.
114 if (!IsIntAttr)
115 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
116 else
117 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
118 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
119 }
120
121 // Return the Attribute that we found or created.
122 return Attribute(PA);
123}
124
126 LLVMContextImpl *pImpl = Context.pImpl;
128 ID.AddString(Kind);
129 if (!Val.empty()) ID.AddString(Val);
130
131 void *InsertPoint;
132 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
133
134 if (!PA) {
135 // If we didn't find any existing attributes of the same shape then create a
136 // new one and insert it.
137 void *Mem =
139 alignof(StringAttributeImpl));
140 PA = new (Mem) StringAttributeImpl(Kind, Val);
141 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
142 }
143
144 // Return the Attribute that we found or created.
145 return Attribute(PA);
146}
147
149 Type *Ty) {
150 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
151 LLVMContextImpl *pImpl = Context.pImpl;
153 ID.AddInteger(Kind);
154 ID.AddPointer(Ty);
155
156 void *InsertPoint;
157 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
158
159 if (!PA) {
160 // If we didn't find any existing attributes of the same shape then create a
161 // new one and insert it.
162 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
163 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
164 }
165
166 // Return the Attribute that we found or created.
167 return Attribute(PA);
168}
169
171 const ConstantRange &CR) {
173 "Not a ConstantRange attribute");
174 assert(!CR.isFullSet() && "ConstantRange attribute must not be full");
175 LLVMContextImpl *pImpl = Context.pImpl;
177 ID.AddInteger(Kind);
178 CR.getLower().Profile(ID);
179 CR.getUpper().Profile(ID);
180
181 void *InsertPoint;
182 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
183
184 if (!PA) {
185 // If we didn't find any existing attributes of the same shape then create a
186 // new one and insert it.
187 PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
189 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
190 }
191
192 // Return the Attribute that we found or created.
193 return Attribute(PA);
194}
195
199 "Not a ConstantRangeList attribute");
200 LLVMContextImpl *pImpl = Context.pImpl;
202 ID.AddInteger(Kind);
203 ID.AddInteger(Val.size());
204 for (auto &CR : Val) {
205 CR.getLower().Profile(ID);
206 CR.getUpper().Profile(ID);
207 }
208
209 void *InsertPoint;
210 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
211
212 if (!PA) {
213 // If we didn't find any existing attributes of the same shape then create a
214 // new one and insert it.
215 // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
216 // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
217 // allocation and record the allocated pointer in
218 // `ConstantRangeListAttributes`. LLVMContext destructor will call the
219 // destructor of the allocated pointer explicitly.
220 void *Mem = pImpl->Alloc.Allocate(
223 PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
224 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
225 pImpl->ConstantRangeListAttributes.push_back(
226 reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
227 }
228
229 // Return the Attribute that we found or created.
230 return Attribute(PA);
231}
232
234 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
235 return get(Context, Alignment, A.value());
236}
237
239 assert(A <= 0x100 && "Alignment too large.");
240 return get(Context, StackAlignment, A.value());
241}
242
244 uint64_t Bytes) {
245 assert(Bytes && "Bytes must be non-zero.");
246 return get(Context, Dereferenceable, Bytes);
247}
248
250 uint64_t Bytes) {
251 assert(Bytes && "Bytes must be non-zero.");
252 return get(Context, DereferenceableOrNull, Bytes);
253}
254
256 return get(Context, ByVal, Ty);
257}
258
260 return get(Context, StructRet, Ty);
261}
262
264 return get(Context, ByRef, Ty);
265}
266
268 return get(Context, Preallocated, Ty);
269}
270
272 return get(Context, InAlloca, Ty);
273}
274
276 UWTableKind Kind) {
277 return get(Context, UWTable, uint64_t(Kind));
278}
279
281 MemoryEffects ME) {
282 return get(Context, Memory, ME.toIntValue());
283}
284
286 FPClassTest ClassMask) {
287 return get(Context, NoFPClass, ClassMask);
288}
289
291Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
292 const std::optional<unsigned> &NumElemsArg) {
293 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
294 "Invalid allocsize arguments -- given allocsize(0, 0)");
295 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
296}
297
299 unsigned MinValue,
300 unsigned MaxValue) {
301 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
302}
303
305 return StringSwitch<Attribute::AttrKind>(AttrName)
306#define GET_ATTR_NAMES
307#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
308 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
309#include "llvm/IR/Attributes.inc"
311}
312
314 switch (AttrKind) {
315#define GET_ATTR_NAMES
316#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
317 case Attribute::ENUM_NAME: \
318 return #DISPLAY_NAME;
319#include "llvm/IR/Attributes.inc"
320 case Attribute::None:
321 return "none";
322 default:
323 llvm_unreachable("invalid Kind");
324 }
325}
326
329#define GET_ATTR_NAMES
330#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
331#include "llvm/IR/Attributes.inc"
332 .Default(false);
333}
334
335//===----------------------------------------------------------------------===//
336// Attribute Accessor Methods
337//===----------------------------------------------------------------------===//
338
340 return pImpl && pImpl->isEnumAttribute();
341}
342
344 return pImpl && pImpl->isIntAttribute();
345}
346
348 return pImpl && pImpl->isStringAttribute();
349}
350
352 return pImpl && pImpl->isTypeAttribute();
353}
354
356 return pImpl && pImpl->isConstantRangeAttribute();
357}
358
360 return pImpl && pImpl->isConstantRangeListAttribute();
361}
362
364 if (!pImpl) return None;
367 "Invalid attribute type to get the kind as an enum!");
368 return pImpl->getKindAsEnum();
369}
370
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::DereferenceableOrNull) &&
448 "Trying to get dereferenceable bytes from "
449 "non-dereferenceable attribute!");
450 return pImpl->getValueAsInt();
451}
452
453std::pair<unsigned, std::optional<unsigned>>
455 assert(hasAttribute(Attribute::AllocSize) &&
456 "Trying to get allocsize args from non-allocsize attribute");
457 return unpackAllocSizeArgs(pImpl->getValueAsInt());
458}
459
461 assert(hasAttribute(Attribute::VScaleRange) &&
462 "Trying to get vscale args from non-vscale attribute");
463 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
464}
465
466std::optional<unsigned> Attribute::getVScaleRangeMax() const {
467 assert(hasAttribute(Attribute::VScaleRange) &&
468 "Trying to get vscale args from non-vscale attribute");
469 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
470}
471
473 assert(hasAttribute(Attribute::UWTable) &&
474 "Trying to get unwind table kind from non-uwtable attribute");
475 return UWTableKind(pImpl->getValueAsInt());
476}
477
479 assert(hasAttribute(Attribute::AllocKind) &&
480 "Trying to get allockind value from non-allockind attribute");
481 return AllocFnKind(pImpl->getValueAsInt());
482}
483
485 assert(hasAttribute(Attribute::Memory) &&
486 "Can only call getMemoryEffects() on memory attribute");
488}
489
491 assert(hasAttribute(Attribute::NoFPClass) &&
492 "Can only call getNoFPClass() on nofpclass attribute");
493 return static_cast<FPClassTest>(pImpl->getValueAsInt());
494}
495
497 assert(hasAttribute(Attribute::Range) &&
498 "Trying to get range args from non-range attribute");
499 return pImpl->getValueAsConstantRange();
500}
501
503 assert(hasAttribute(Attribute::Initializes) &&
504 "Trying to get initializes attr from non-ConstantRangeList attribute");
505 return pImpl->getValueAsConstantRangeList();
506}
507
508static const char *getModRefStr(ModRefInfo MR) {
509 switch (MR) {
511 return "none";
512 case ModRefInfo::Ref:
513 return "read";
514 case ModRefInfo::Mod:
515 return "write";
517 return "readwrite";
518 }
519 llvm_unreachable("Invalid ModRefInfo");
520}
521
522std::string Attribute::getAsString(bool InAttrGrp) const {
523 if (!pImpl) return {};
524
525 if (isEnumAttribute())
527
528 if (isTypeAttribute()) {
529 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
530 Result += '(';
531 raw_string_ostream OS(Result);
532 getValueAsType()->print(OS, false, true);
533 OS.flush();
534 Result += ')';
535 return Result;
536 }
537
538 // FIXME: These should be output like this:
539 //
540 // align=4
541 // alignstack=8
542 //
543 if (hasAttribute(Attribute::Alignment))
544 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
545 : "align " + Twine(getValueAsInt()))
546 .str();
547
548 auto AttrWithBytesToString = [&](const char *Name) {
549 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
550 : Name + ("(" + Twine(getValueAsInt())) + ")")
551 .str();
552 };
553
554 if (hasAttribute(Attribute::StackAlignment))
555 return AttrWithBytesToString("alignstack");
556
557 if (hasAttribute(Attribute::Dereferenceable))
558 return AttrWithBytesToString("dereferenceable");
559
560 if (hasAttribute(Attribute::DereferenceableOrNull))
561 return AttrWithBytesToString("dereferenceable_or_null");
562
563 if (hasAttribute(Attribute::AllocSize)) {
564 unsigned ElemSize;
565 std::optional<unsigned> NumElems;
566 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
567
568 return (NumElems
569 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
570 : "allocsize(" + Twine(ElemSize) + ")")
571 .str();
572 }
573
574 if (hasAttribute(Attribute::VScaleRange)) {
575 unsigned MinValue = getVScaleRangeMin();
576 std::optional<unsigned> MaxValue = getVScaleRangeMax();
577 return ("vscale_range(" + Twine(MinValue) + "," +
578 Twine(MaxValue.value_or(0)) + ")")
579 .str();
580 }
581
582 if (hasAttribute(Attribute::UWTable)) {
584 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
585 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
586 }
587
588 if (hasAttribute(Attribute::AllocKind)) {
589 AllocFnKind Kind = getAllocKind();
592 parts.push_back("alloc");
594 parts.push_back("realloc");
596 parts.push_back("free");
598 parts.push_back("uninitialized");
600 parts.push_back("zeroed");
602 parts.push_back("aligned");
603 return ("allockind(\"" +
604 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
605 .str();
606 }
607
608 if (hasAttribute(Attribute::Memory)) {
609 std::string Result;
610 raw_string_ostream OS(Result);
611 bool First = true;
612 OS << "memory(";
613
615
616 // Print access kind for "other" as the default access kind. This way it
617 // will apply to any new location kinds that get split out of "other".
619 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
620 First = false;
621 OS << getModRefStr(OtherMR);
622 }
623
624 for (auto Loc : MemoryEffects::locations()) {
625 ModRefInfo MR = ME.getModRef(Loc);
626 if (MR == OtherMR)
627 continue;
628
629 if (!First)
630 OS << ", ";
631 First = false;
632
633 switch (Loc) {
635 OS << "argmem: ";
636 break;
638 OS << "inaccessiblemem: ";
639 break;
641 llvm_unreachable("This is represented as the default access kind");
642 }
643 OS << getModRefStr(MR);
644 }
645 OS << ")";
646 OS.flush();
647 return Result;
648 }
649
650 if (hasAttribute(Attribute::NoFPClass)) {
651 std::string Result = "nofpclass";
652 raw_string_ostream OS(Result);
653 OS << getNoFPClass();
654 return Result;
655 }
656
657 if (hasAttribute(Attribute::Range)) {
658 std::string Result;
659 raw_string_ostream OS(Result);
661 OS << "range(";
662 OS << "i" << CR.getBitWidth() << " ";
663 OS << CR.getLower() << ", " << CR.getUpper();
664 OS << ")";
665 OS.flush();
666 return Result;
667 }
668
669 if (hasAttribute(Attribute::Initializes)) {
670 std::string Result;
671 raw_string_ostream OS(Result);
673 OS << "initializes(";
674 CRL.print(OS);
675 OS << ")";
676 OS.flush();
677 return Result;
678 }
679
680 // Convert target-dependent attributes to strings of the form:
681 //
682 // "kind"
683 // "kind" = "value"
684 //
685 if (isStringAttribute()) {
686 std::string Result;
687 {
688 raw_string_ostream OS(Result);
689 OS << '"' << getKindAsString() << '"';
690
691 // Since some attribute strings contain special characters that cannot be
692 // printable, those have to be escaped to make the attribute value
693 // printable as is. e.g. "\01__gnu_mcount_nc"
694 const auto &AttrVal = pImpl->getValueAsString();
695 if (!AttrVal.empty()) {
696 OS << "=\"";
697 printEscapedString(AttrVal, OS);
698 OS << "\"";
699 }
700 }
701 return Result;
702 }
703
704 llvm_unreachable("Unknown attribute");
705}
706
708 assert(isValid() && "invalid Attribute doesn't refer to any context");
710 pImpl->Profile(ID);
711 void *Unused;
712 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
713}
714
716 if (!pImpl && !A.pImpl) return false;
717 if (!pImpl) return true;
718 if (!A.pImpl) return false;
719 return *pImpl < *A.pImpl;
720}
721
723 ID.AddPointer(pImpl);
724}
725
727 FnAttr = (1 << 0),
728 ParamAttr = (1 << 1),
729 RetAttr = (1 << 2),
730};
731
732#define GET_ATTR_PROP_TABLE
733#include "llvm/IR/Attributes.inc"
734
736 AttributeProperty Prop) {
737 unsigned Index = Kind - 1;
738 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
739 return AttrPropTable[Index] & Prop;
740}
741
743 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
744}
745
747 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
748}
749
751 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
752}
753
754//===----------------------------------------------------------------------===//
755// AttributeImpl Definition
756//===----------------------------------------------------------------------===//
757
759 if (isStringAttribute()) return false;
760 return getKindAsEnum() == A;
761}
762
764 if (!isStringAttribute()) return false;
765 return getKindAsString() == Kind;
766}
767
771 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
772}
773
776 return static_cast<const IntAttributeImpl *>(this)->getValue();
777}
778
780 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
781 return getValueAsString() == "true";
782}
783
786 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
787}
788
791 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
792}
793
796 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
797}
798
801 return static_cast<const ConstantRangeAttributeImpl *>(this)
802 ->getConstantRangeValue();
803}
804
807 return static_cast<const ConstantRangeListAttributeImpl *>(this)
808 ->getConstantRangeListValue();
809}
810
812 if (this == &AI)
813 return false;
814
815 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
816 // relative to their enum value) and then strings.
817 if (!isStringAttribute()) {
818 if (AI.isStringAttribute())
819 return true;
820 if (getKindAsEnum() != AI.getKindAsEnum())
821 return getKindAsEnum() < AI.getKindAsEnum();
822 assert(!AI.isEnumAttribute() && "Non-unique attribute");
823 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
824 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
826 "Unclear how to compare range list");
827 // TODO: Is this actually needed?
828 assert(AI.isIntAttribute() && "Only possibility left");
829 return getValueAsInt() < AI.getValueAsInt();
830 }
831
832 if (!AI.isStringAttribute())
833 return false;
834 if (getKindAsString() == AI.getKindAsString())
835 return getValueAsString() < AI.getValueAsString();
836 return getKindAsString() < AI.getKindAsString();
837}
838
839//===----------------------------------------------------------------------===//
840// AttributeSet Definition
841//===----------------------------------------------------------------------===//
842
845}
846
848 return AttributeSet(AttributeSetNode::get(C, Attrs));
849}
850
852 Attribute::AttrKind Kind) const {
853 if (hasAttribute(Kind)) return *this;
854 AttrBuilder B(C);
855 B.addAttribute(Kind);
857}
858
860 StringRef Value) const {
861 AttrBuilder B(C);
862 B.addAttribute(Kind, Value);
864}
865
867 const AttributeSet AS) const {
868 if (!hasAttributes())
869 return AS;
870
871 if (!AS.hasAttributes())
872 return *this;
873
874 AttrBuilder B(C, *this);
875 B.merge(AttrBuilder(C, AS));
876 return get(C, B);
877}
878
880 Attribute::AttrKind Kind) const {
881 if (!hasAttribute(Kind)) return *this;
882 AttrBuilder B(C, *this);
883 B.removeAttribute(Kind);
884 return get(C, B);
885}
886
888 StringRef Kind) const {
889 if (!hasAttribute(Kind)) return *this;
890 AttrBuilder B(C, *this);
891 B.removeAttribute(Kind);
892 return get(C, B);
893}
894
896 const AttributeMask &Attrs) const {
897 AttrBuilder B(C, *this);
898 // If there is nothing to remove, directly return the original set.
899 if (!B.overlaps(Attrs))
900 return *this;
901
902 B.remove(Attrs);
903 return get(C, B);
904}
905
907 return SetNode ? SetNode->getNumAttributes() : 0;
908}
909
911 return SetNode ? SetNode->hasAttribute(Kind) : false;
912}
913
915 return SetNode ? SetNode->hasAttribute(Kind) : false;
916}
917
919 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
920}
921
923 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
924}
925
927 return SetNode ? SetNode->getAlignment() : std::nullopt;
928}
929
931 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
932}
933
935 return SetNode ? SetNode->getDereferenceableBytes() : 0;
936}
937
939 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
940}
941
943 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
944}
945
947 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
948}
949
951 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
952}
953
955 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
956}
957
959 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
960}
961
963 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
964}
965
966std::optional<std::pair<unsigned, std::optional<unsigned>>>
968 if (SetNode)
969 return SetNode->getAllocSizeArgs();
970 return std::nullopt;
971}
972
974 return SetNode ? SetNode->getVScaleRangeMin() : 1;
975}
976
977std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
978 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
979}
980
982 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
983}
984
986 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
987}
988
990 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
991}
992
994 return SetNode ? SetNode->getNoFPClass() : fcNone;
995}
996
997std::string AttributeSet::getAsString(bool InAttrGrp) const {
998 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
999}
1000
1002 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1004 SetNode->Profile(ID);
1005 void *Unused;
1006 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1007}
1008
1010 return SetNode ? SetNode->begin() : nullptr;
1011}
1012
1014 return SetNode ? SetNode->end() : nullptr;
1015}
1016
1017#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1019 dbgs() << "AS =\n";
1020 dbgs() << " { ";
1021 dbgs() << getAsString(true) << " }\n";
1022}
1023#endif
1024
1025//===----------------------------------------------------------------------===//
1026// AttributeSetNode Definition
1027//===----------------------------------------------------------------------===//
1028
1029AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1030 : NumAttrs(Attrs.size()) {
1031 // There's memory after the node where we can store the entries in.
1032 llvm::copy(Attrs, getTrailingObjects<Attribute>());
1033
1034 for (const auto &I : *this) {
1035 if (I.isStringAttribute())
1036 StringAttrs.insert({ I.getKindAsString(), I });
1037 else
1038 AvailableAttrs.addAttribute(I.getKindAsEnum());
1039 }
1040}
1041
1043 ArrayRef<Attribute> Attrs) {
1044 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1045 llvm::sort(SortedAttrs);
1046 return getSorted(C, SortedAttrs);
1047}
1048
1049AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1050 ArrayRef<Attribute> SortedAttrs) {
1051 if (SortedAttrs.empty())
1052 return nullptr;
1053
1054 // Build a key to look up the existing attributes.
1055 LLVMContextImpl *pImpl = C.pImpl;
1057
1058 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1059 for (const auto &Attr : SortedAttrs)
1060 Attr.Profile(ID);
1061
1062 void *InsertPoint;
1063 AttributeSetNode *PA =
1064 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1065
1066 // If we didn't find any existing attributes of the same shape then create a
1067 // new one and insert it.
1068 if (!PA) {
1069 // Coallocate entries after the AttributeSetNode itself.
1070 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1071 PA = new (Mem) AttributeSetNode(SortedAttrs);
1072 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1073 }
1074
1075 // Return the AttributeSetNode that we found or created.
1076 return PA;
1077}
1078
1080 return getSorted(C, B.attrs());
1081}
1082
1084 return StringAttrs.count(Kind);
1085}
1086
1087std::optional<Attribute>
1088AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1089 // Do a quick presence check.
1090 if (!hasAttribute(Kind))
1091 return std::nullopt;
1092
1093 // Attributes in a set are sorted by enum value, followed by string
1094 // attributes. Binary search the one we want.
1095 const Attribute *I =
1096 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1097 [](Attribute A, Attribute::AttrKind Kind) {
1098 return A.getKindAsEnum() < Kind;
1099 });
1100 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1101 return *I;
1102}
1103
1105 if (auto A = findEnumAttribute(Kind))
1106 return *A;
1107 return {};
1108}
1109
1111 return StringAttrs.lookup(Kind);
1112}
1113
1115 if (auto A = findEnumAttribute(Attribute::Alignment))
1116 return A->getAlignment();
1117 return std::nullopt;
1118}
1119
1121 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1122 return A->getStackAlignment();
1123 return std::nullopt;
1124}
1125
1127 if (auto A = findEnumAttribute(Kind))
1128 return A->getValueAsType();
1129 return nullptr;
1130}
1131
1133 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1134 return A->getDereferenceableBytes();
1135 return 0;
1136}
1137
1139 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1140 return A->getDereferenceableOrNullBytes();
1141 return 0;
1142}
1143
1144std::optional<std::pair<unsigned, std::optional<unsigned>>>
1146 if (auto A = findEnumAttribute(Attribute::AllocSize))
1147 return A->getAllocSizeArgs();
1148 return std::nullopt;
1149}
1150
1152 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1153 return A->getVScaleRangeMin();
1154 return 1;
1155}
1156
1157std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1158 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1159 return A->getVScaleRangeMax();
1160 return std::nullopt;
1161}
1162
1164 if (auto A = findEnumAttribute(Attribute::UWTable))
1165 return A->getUWTableKind();
1166 return UWTableKind::None;
1167}
1168
1170 if (auto A = findEnumAttribute(Attribute::AllocKind))
1171 return A->getAllocKind();
1172 return AllocFnKind::Unknown;
1173}
1174
1176 if (auto A = findEnumAttribute(Attribute::Memory))
1177 return A->getMemoryEffects();
1178 return MemoryEffects::unknown();
1179}
1180
1182 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1183 return A->getNoFPClass();
1184 return fcNone;
1185}
1186
1187std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1188 std::string Str;
1189 for (iterator I = begin(), E = end(); I != E; ++I) {
1190 if (I != begin())
1191 Str += ' ';
1192 Str += I->getAsString(InAttrGrp);
1193 }
1194 return Str;
1195}
1196
1197//===----------------------------------------------------------------------===//
1198// AttributeListImpl Definition
1199//===----------------------------------------------------------------------===//
1200
1201/// Map from AttributeList index to the internal array index. Adding one happens
1202/// to work, because -1 wraps around to 0.
1203static unsigned attrIdxToArrayIdx(unsigned Index) {
1204 return Index + 1;
1205}
1206
1208 : NumAttrSets(Sets.size()) {
1209 assert(!Sets.empty() && "pointless AttributeListImpl");
1210
1211 // There's memory after the node where we can store the entries in.
1212 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1213
1214 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1215 // summary bitsets.
1216 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1217 if (!I.isStringAttribute())
1218 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1219
1220 for (const auto &Set : Sets)
1221 for (const auto &I : Set)
1222 if (!I.isStringAttribute())
1223 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1224}
1225
1227 Profile(ID, ArrayRef(begin(), end()));
1228}
1229
1232 for (const auto &Set : Sets)
1233 ID.AddPointer(Set.SetNode);
1234}
1235
1237 unsigned *Index) const {
1238 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1239 return false;
1240
1241 if (Index) {
1242 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1243 if (begin()[I].hasAttribute(Kind)) {
1244 *Index = I - 1;
1245 break;
1246 }
1247 }
1248 }
1249
1250 return true;
1251}
1252
1253
1254#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1256 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1257}
1258#endif
1259
1260//===----------------------------------------------------------------------===//
1261// AttributeList Construction and Mutation Methods
1262//===----------------------------------------------------------------------===//
1263
1264AttributeList AttributeList::getImpl(LLVMContext &C,
1265 ArrayRef<AttributeSet> AttrSets) {
1266 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1267
1268 LLVMContextImpl *pImpl = C.pImpl;
1270 AttributeListImpl::Profile(ID, AttrSets);
1271
1272 void *InsertPoint;
1273 AttributeListImpl *PA =
1274 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1275
1276 // If we didn't find any existing attributes of the same shape then
1277 // create a new one and insert it.
1278 if (!PA) {
1279 // Coallocate entries after the AttributeListImpl itself.
1280 void *Mem = pImpl->Alloc.Allocate(
1281 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1282 alignof(AttributeListImpl));
1283 PA = new (Mem) AttributeListImpl(AttrSets);
1284 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1285 }
1286
1287 // Return the AttributesList that we found or created.
1288 return AttributeList(PA);
1289}
1290
1293 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1294 // If there are no attributes then return a null AttributesList pointer.
1295 if (Attrs.empty())
1296 return {};
1297
1299 "Misordered Attributes list!");
1300 assert(llvm::all_of(Attrs,
1301 [](const std::pair<unsigned, Attribute> &Pair) {
1302 return Pair.second.isValid();
1303 }) &&
1304 "Pointless attribute!");
1305
1306 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1307 // list.
1309 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1310 E = Attrs.end(); I != E; ) {
1311 unsigned Index = I->first;
1313 while (I != E && I->first == Index) {
1314 AttrVec.push_back(I->second);
1315 ++I;
1316 }
1317
1318 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1319 }
1320
1321 return get(C, AttrPairVec);
1322}
1323
1326 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1327 // If there are no attributes then return a null AttributesList pointer.
1328 if (Attrs.empty())
1329 return {};
1330
1332 "Misordered Attributes list!");
1333 assert(llvm::none_of(Attrs,
1334 [](const std::pair<unsigned, AttributeSet> &Pair) {
1335 return !Pair.second.hasAttributes();
1336 }) &&
1337 "Pointless attribute!");
1338
1339 unsigned MaxIndex = Attrs.back().first;
1340 // If the MaxIndex is FunctionIndex and there are other indices in front
1341 // of it, we need to use the largest of those to get the right size.
1342 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1343 MaxIndex = Attrs[Attrs.size() - 2].first;
1344
1345 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1346 for (const auto &Pair : Attrs)
1347 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1348
1349 return getImpl(C, AttrVec);
1350}
1351
1353 AttributeSet RetAttrs,
1354 ArrayRef<AttributeSet> ArgAttrs) {
1355 // Scan from the end to find the last argument with attributes. Most
1356 // arguments don't have attributes, so it's nice if we can have fewer unique
1357 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1358 unsigned NumSets = 0;
1359 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1360 if (ArgAttrs[I - 1].hasAttributes()) {
1361 NumSets = I + 2;
1362 break;
1363 }
1364 }
1365 if (NumSets == 0) {
1366 // Check function and return attributes if we didn't have argument
1367 // attributes.
1368 if (RetAttrs.hasAttributes())
1369 NumSets = 2;
1370 else if (FnAttrs.hasAttributes())
1371 NumSets = 1;
1372 }
1373
1374 // If all attribute sets were empty, we can use the empty attribute list.
1375 if (NumSets == 0)
1376 return {};
1377
1379 AttrSets.reserve(NumSets);
1380 // If we have any attributes, we always have function attributes.
1381 AttrSets.push_back(FnAttrs);
1382 if (NumSets > 1)
1383 AttrSets.push_back(RetAttrs);
1384 if (NumSets > 2) {
1385 // Drop the empty argument attribute sets at the end.
1386 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1387 llvm::append_range(AttrSets, ArgAttrs);
1388 }
1389
1390 return getImpl(C, AttrSets);
1391}
1392
1394 AttributeSet Attrs) {
1395 if (!Attrs.hasAttributes())
1396 return {};
1398 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1399 AttrSets[Index] = Attrs;
1400 return getImpl(C, AttrSets);
1401}
1402
1404 const AttrBuilder &B) {
1405 return get(C, Index, AttributeSet::get(C, B));
1406}
1407
1411 for (const auto K : Kinds)
1412 Attrs.emplace_back(Index, Attribute::get(C, K));
1413 return get(C, Attrs);
1414}
1415
1418 ArrayRef<uint64_t> Values) {
1419 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1421 auto VI = Values.begin();
1422 for (const auto K : Kinds)
1423 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1424 return get(C, Attrs);
1425}
1426
1428 ArrayRef<StringRef> Kinds) {
1430 for (const auto &K : Kinds)
1431 Attrs.emplace_back(Index, Attribute::get(C, K));
1432 return get(C, Attrs);
1433}
1434
1437 if (Attrs.empty())
1438 return {};
1439 if (Attrs.size() == 1)
1440 return Attrs[0];
1441
1442 unsigned MaxSize = 0;
1443 for (const auto &List : Attrs)
1444 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1445
1446 // If every list was empty, there is no point in merging the lists.
1447 if (MaxSize == 0)
1448 return {};
1449
1450 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1451 for (unsigned I = 0; I < MaxSize; ++I) {
1452 AttrBuilder CurBuilder(C);
1453 for (const auto &List : Attrs)
1454 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1455 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1456 }
1457
1458 return getImpl(C, NewAttrSets);
1459}
1460
1463 Attribute::AttrKind Kind) const {
1465 if (Attrs.hasAttribute(Kind))
1466 return *this;
1467 // TODO: Insert at correct position and avoid sort.
1468 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1469 NewAttrs.push_back(Attribute::get(C, Kind));
1470 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1471}
1472
1474 StringRef Kind,
1475 StringRef Value) const {
1476 AttrBuilder B(C);
1477 B.addAttribute(Kind, Value);
1478 return addAttributesAtIndex(C, Index, B);
1479}
1480
1482 Attribute A) const {
1483 AttrBuilder B(C);
1484 B.addAttribute(A);
1485 return addAttributesAtIndex(C, Index, B);
1486}
1487
1488AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1489 unsigned Index,
1490 AttributeSet Attrs) const {
1492 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1493 if (Index >= AttrSets.size())
1494 AttrSets.resize(Index + 1);
1495 AttrSets[Index] = Attrs;
1496
1497 // Remove trailing empty attribute sets.
1498 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1499 AttrSets.pop_back();
1500 if (AttrSets.empty())
1501 return {};
1502 return AttributeList::getImpl(C, AttrSets);
1503}
1504
1506 unsigned Index,
1507 const AttrBuilder &B) const {
1508 if (!B.hasAttributes())
1509 return *this;
1510
1511 if (!pImpl)
1513
1514 AttrBuilder Merged(C, getAttributes(Index));
1515 Merged.merge(B);
1516 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1517}
1518
1520 ArrayRef<unsigned> ArgNos,
1521 Attribute A) const {
1522 assert(llvm::is_sorted(ArgNos));
1523
1524 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1525 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1526 if (MaxIndex >= AttrSets.size())
1527 AttrSets.resize(MaxIndex + 1);
1528
1529 for (unsigned ArgNo : ArgNos) {
1530 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1531 AttrBuilder B(C, AttrSets[Index]);
1532 B.addAttribute(A);
1533 AttrSets[Index] = AttributeSet::get(C, B);
1534 }
1535
1536 return getImpl(C, AttrSets);
1537}
1538
1541 Attribute::AttrKind Kind) const {
1543 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1544 if (Attrs == NewAttrs)
1545 return *this;
1546 return setAttributesAtIndex(C, Index, NewAttrs);
1547}
1548
1550 unsigned Index,
1551 StringRef Kind) const {
1553 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1554 if (Attrs == NewAttrs)
1555 return *this;
1556 return setAttributesAtIndex(C, Index, NewAttrs);
1557}
1558
1560 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1562 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1563 // If nothing was removed, return the original list.
1564 if (Attrs == NewAttrs)
1565 return *this;
1566 return setAttributesAtIndex(C, Index, NewAttrs);
1567}
1568
1571 unsigned WithoutIndex) const {
1572 if (!pImpl)
1573 return {};
1574 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1575 return *this;
1576 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1577}
1578
1580 uint64_t Bytes) const {
1581 AttrBuilder B(C);
1582 B.addDereferenceableAttr(Bytes);
1583 return addRetAttributes(C, B);
1584}
1585
1587 unsigned Index,
1588 uint64_t Bytes) const {
1589 AttrBuilder B(C);
1590 B.addDereferenceableAttr(Bytes);
1591 return addParamAttributes(C, Index, B);
1592}
1593
1596 uint64_t Bytes) const {
1597 AttrBuilder B(C);
1598 B.addDereferenceableOrNullAttr(Bytes);
1599 return addParamAttributes(C, Index, B);
1600}
1601
1603 const ConstantRange &CR) const {
1604 AttrBuilder B(C);
1605 B.addRangeAttr(CR);
1606 return addRetAttributes(C, B);
1607}
1608
1610 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1611 const std::optional<unsigned> &NumElemsArg) {
1612 AttrBuilder B(C);
1613 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1614 return addParamAttributes(C, Index, B);
1615}
1616
1617//===----------------------------------------------------------------------===//
1618// AttributeList Accessor Methods
1619//===----------------------------------------------------------------------===//
1620
1622 return getAttributes(ArgNo + FirstArgIndex);
1623}
1624
1626 return getAttributes(ReturnIndex);
1627}
1628
1631}
1632
1634 Attribute::AttrKind Kind) const {
1635 return getAttributes(Index).hasAttribute(Kind);
1636}
1637
1639 return getAttributes(Index).hasAttribute(Kind);
1640}
1641
1644}
1645
1647 return pImpl && pImpl->hasFnAttribute(Kind);
1648}
1649
1652}
1653
1655 unsigned *Index) const {
1656 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1657}
1658
1660 Attribute::AttrKind Kind) const {
1661 return getAttributes(Index).getAttribute(Kind);
1662}
1663
1665 StringRef Kind) const {
1666 return getAttributes(Index).getAttribute(Kind);
1667}
1668
1671}
1672
1674 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1675}
1676
1679}
1680
1683}
1684
1687}
1688
1691}
1692
1695}
1696
1699}
1700
1703}
1704
1706 return getFnAttrs().getStackAlignment();
1707}
1708
1710 return getRetAttrs().getStackAlignment();
1711}
1712
1715}
1716
1719}
1720
1723}
1724
1728}
1729
1731 return getRetAttrs().getNoFPClass();
1732}
1733
1736}
1737
1739 return getFnAttrs().getUWTableKind();
1740}
1741
1743 return getFnAttrs().getAllocKind();
1744}
1745
1747 return getFnAttrs().getMemoryEffects();
1748}
1749
1750std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1751 return getAttributes(Index).getAsString(InAttrGrp);
1752}
1753
1756 if (!pImpl || Index >= getNumAttrSets())
1757 return {};
1758 return pImpl->begin()[Index];
1759}
1760
1762 assert(!isEmpty() && "an empty attribute list has no parent context");
1764 pImpl->Profile(ID);
1765 void *Unused;
1766 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1767}
1768
1770 return pImpl ? pImpl->begin() : nullptr;
1771}
1772
1774 return pImpl ? pImpl->end() : nullptr;
1775}
1776
1777//===----------------------------------------------------------------------===//
1778// AttributeList Introspection Methods
1779//===----------------------------------------------------------------------===//
1780
1782 return pImpl ? pImpl->NumAttrSets : 0;
1783}
1784
1786 O << "AttributeList[\n";
1787
1788 for (unsigned i : indexes()) {
1789 if (!getAttributes(i).hasAttributes())
1790 continue;
1791 O << " { ";
1792 switch (i) {
1794 O << "return";
1795 break;
1797 O << "function";
1798 break;
1799 default:
1800 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1801 }
1802 O << " => " << getAsString(i) << " }\n";
1803 }
1804
1805 O << "]\n";
1806}
1807
1808#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1810#endif
1811
1812//===----------------------------------------------------------------------===//
1813// AttrBuilder Method Implementations
1814//===----------------------------------------------------------------------===//
1815
1817 append_range(Attrs, AS);
1818 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
1819}
1820
1821void AttrBuilder::clear() { Attrs.clear(); }
1822
1823/// Attribute comparator that only compares attribute keys. Enum attributes are
1824/// sorted before string attributes.
1826 bool operator()(Attribute A0, Attribute A1) const {
1827 bool A0IsString = A0.isStringAttribute();
1828 bool A1IsString = A1.isStringAttribute();
1829 if (A0IsString) {
1830 if (A1IsString)
1831 return A0.getKindAsString() < A1.getKindAsString();
1832 else
1833 return false;
1834 }
1835 if (A1IsString)
1836 return true;
1837 return A0.getKindAsEnum() < A1.getKindAsEnum();
1838 }
1840 if (A0.isStringAttribute())
1841 return false;
1842 return A0.getKindAsEnum() < Kind;
1843 }
1844 bool operator()(Attribute A0, StringRef Kind) const {
1845 if (A0.isStringAttribute())
1846 return A0.getKindAsString() < Kind;
1847 return true;
1848 }
1849};
1850
1851template <typename K>
1853 Attribute Attr) {
1854 auto It = lower_bound(Attrs, Kind, AttributeComparator());
1855 if (It != Attrs.end() && It->hasAttribute(Kind))
1856 std::swap(*It, Attr);
1857 else
1858 Attrs.insert(It, Attr);
1859}
1860
1862 if (Attr.isStringAttribute())
1863 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1864 else
1865 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
1866 return *this;
1867}
1868
1870 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
1871 return *this;
1872}
1873
1875 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
1876 return *this;
1877}
1878
1880 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1881 auto It = lower_bound(Attrs, Val, AttributeComparator());
1882 if (It != Attrs.end() && It->hasAttribute(Val))
1883 Attrs.erase(It);
1884 return *this;
1885}
1886
1888 auto It = lower_bound(Attrs, A, AttributeComparator());
1889 if (It != Attrs.end() && It->hasAttribute(A))
1890 Attrs.erase(It);
1891 return *this;
1892}
1893
1894std::optional<uint64_t>
1896 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
1897 Attribute A = getAttribute(Kind);
1898 if (A.isValid())
1899 return A.getValueAsInt();
1900 return std::nullopt;
1901}
1902
1904 uint64_t Value) {
1905 return addAttribute(Attribute::get(Ctx, Kind, Value));
1906}
1907
1908std::optional<std::pair<unsigned, std::optional<unsigned>>>
1910 Attribute A = getAttribute(Attribute::AllocSize);
1911 if (A.isValid())
1912 return A.getAllocSizeArgs();
1913 return std::nullopt;
1914}
1915
1917 if (!Align)
1918 return *this;
1919
1920 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1921 return addRawIntAttr(Attribute::Alignment, Align->value());
1922}
1923
1925 // Default alignment, allow the target to define how to align it.
1926 if (!Align)
1927 return *this;
1928
1929 assert(*Align <= 0x100 && "Alignment too large.");
1930 return addRawIntAttr(Attribute::StackAlignment, Align->value());
1931}
1932
1934 if (Bytes == 0) return *this;
1935
1936 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
1937}
1938
1940 if (Bytes == 0)
1941 return *this;
1942
1943 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
1944}
1945
1948 const std::optional<unsigned> &NumElems) {
1949 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1950}
1951
1953 // (0, 0) is our "not present" value, so we need to check for it here.
1954 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1955 return addRawIntAttr(Attribute::AllocSize, RawArgs);
1956}
1957
1959 std::optional<unsigned> MaxValue) {
1960 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
1961}
1962
1964 // (0, 0) is not present hence ignore this case
1965 if (RawArgs == 0)
1966 return *this;
1967
1968 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1969}
1970
1972 if (Kind == UWTableKind::None)
1973 return *this;
1974 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
1975}
1976
1978 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
1979}
1980
1982 if (Mask == fcNone)
1983 return *this;
1984
1985 return addRawIntAttr(Attribute::NoFPClass, Mask);
1986}
1987
1989 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
1990}
1991
1993 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
1994 Attribute A = getAttribute(Kind);
1995 return A.isValid() ? A.getValueAsType() : nullptr;
1996}
1997
1999 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2000}
2001
2003 return addTypeAttr(Attribute::ByVal, Ty);
2004}
2005
2007 return addTypeAttr(Attribute::StructRet, Ty);
2008}
2009
2011 return addTypeAttr(Attribute::ByRef, Ty);
2012}
2013
2015 return addTypeAttr(Attribute::Preallocated, Ty);
2016}
2017
2019 return addTypeAttr(Attribute::InAlloca, Ty);
2020}
2021
2023 const ConstantRange &CR) {
2024 if (CR.isFullSet())
2025 return *this;
2026
2027 return addAttribute(Attribute::get(Ctx, Kind, CR));
2028}
2029
2031 return addConstantRangeAttr(Attribute::Range, CR);
2032}
2033
2037 return addAttribute(Attribute::get(Ctx, Kind, Val));
2038}
2039
2041 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2042}
2043
2045 // TODO: Could make this O(n) as we're merging two sorted lists.
2046 for (const auto &I : B.attrs())
2047 addAttribute(I);
2048
2049 return *this;
2050}
2051
2053 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2054 return *this;
2055}
2056
2058 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2059}
2060
2062 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2063 auto It = lower_bound(Attrs, A, AttributeComparator());
2064 if (It != Attrs.end() && It->hasAttribute(A))
2065 return *It;
2066 return {};
2067}
2068
2070 auto It = lower_bound(Attrs, A, AttributeComparator());
2071 if (It != Attrs.end() && It->hasAttribute(A))
2072 return *It;
2073 return {};
2074}
2075
2077 return getAttribute(A).isValid();
2078}
2079
2081 return getAttribute(A).isValid();
2082}
2083
2085 return Attrs == B.Attrs;
2086}
2087
2088//===----------------------------------------------------------------------===//
2089// AttributeFuncs Function Defintions
2090//===----------------------------------------------------------------------===//
2091
2092/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2093/// follows the same type rules as FPMathOperator.
2094///
2095/// TODO: Consider relaxing to any FP type struct fields.
2097 while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
2098 Ty = ArrTy->getElementType();
2099 return Ty->isFPOrFPVectorTy();
2100}
2101
2102/// Which attributes cannot be applied to a type.
2104 AttributeSafetyKind ASK) {
2105 AttributeMask Incompatible;
2106
2107 if (!Ty->isIntegerTy()) {
2108 // Attributes that only apply to integers.
2109 if (ASK & ASK_SAFE_TO_DROP)
2110 Incompatible.addAttribute(Attribute::AllocAlign);
2111 if (ASK & ASK_UNSAFE_TO_DROP)
2112 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2113 }
2114
2115 if (!Ty->isIntOrIntVectorTy()) {
2116 // Attributes that only apply to integers or vector of integers.
2117 if (ASK & ASK_SAFE_TO_DROP)
2118 Incompatible.addAttribute(Attribute::Range);
2119 }
2120
2121 if (!Ty->isPointerTy()) {
2122 // Attributes that only apply to pointers.
2123 if (ASK & ASK_SAFE_TO_DROP)
2124 Incompatible.addAttribute(Attribute::NoAlias)
2125 .addAttribute(Attribute::NoCapture)
2126 .addAttribute(Attribute::NonNull)
2127 .addAttribute(Attribute::ReadNone)
2128 .addAttribute(Attribute::ReadOnly)
2129 .addAttribute(Attribute::Dereferenceable)
2130 .addAttribute(Attribute::DereferenceableOrNull)
2131 .addAttribute(Attribute::Writable)
2132 .addAttribute(Attribute::DeadOnUnwind)
2133 .addAttribute(Attribute::Initializes);
2134 if (ASK & ASK_UNSAFE_TO_DROP)
2135 Incompatible.addAttribute(Attribute::Nest)
2136 .addAttribute(Attribute::SwiftError)
2137 .addAttribute(Attribute::Preallocated)
2138 .addAttribute(Attribute::InAlloca)
2139 .addAttribute(Attribute::ByVal)
2140 .addAttribute(Attribute::StructRet)
2141 .addAttribute(Attribute::ByRef)
2142 .addAttribute(Attribute::ElementType)
2143 .addAttribute(Attribute::AllocatedPointer);
2144 }
2145
2146 // Attributes that only apply to pointers or vectors of pointers.
2147 if (!Ty->isPtrOrPtrVectorTy()) {
2148 if (ASK & ASK_SAFE_TO_DROP)
2149 Incompatible.addAttribute(Attribute::Alignment);
2150 }
2151
2152 if (ASK & ASK_SAFE_TO_DROP) {
2154 Incompatible.addAttribute(Attribute::NoFPClass);
2155 }
2156
2157 // Some attributes can apply to all "values" but there are no `void` values.
2158 if (Ty->isVoidTy()) {
2159 if (ASK & ASK_SAFE_TO_DROP)
2160 Incompatible.addAttribute(Attribute::NoUndef);
2161 }
2162
2163 return Incompatible;
2164}
2165
2167 AttributeMask AM;
2168 AM.addAttribute(Attribute::NoUndef);
2169 AM.addAttribute(Attribute::Dereferenceable);
2170 AM.addAttribute(Attribute::DereferenceableOrNull);
2171 return AM;
2172}
2173
2174/// Callees with dynamic denormal modes are compatible with any caller mode.
2175static bool denormModeCompatible(DenormalMode CallerMode,
2176 DenormalMode CalleeMode) {
2177 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2178 return true;
2179
2180 // If they don't exactly match, it's OK if the mismatched component is
2181 // dynamic.
2182 if (CalleeMode.Input == CallerMode.Input &&
2183 CalleeMode.Output == DenormalMode::Dynamic)
2184 return true;
2185
2186 if (CalleeMode.Output == CallerMode.Output &&
2187 CalleeMode.Input == DenormalMode::Dynamic)
2188 return true;
2189 return false;
2190}
2191
2192static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2193 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2194 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2195
2196 if (denormModeCompatible(CallerMode, CalleeMode)) {
2197 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2198 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2199 if (CallerModeF32 == DenormalMode::getInvalid())
2200 CallerModeF32 = CallerMode;
2201 if (CalleeModeF32 == DenormalMode::getInvalid())
2202 CalleeModeF32 = CalleeMode;
2203 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2204 }
2205
2206 return false;
2207}
2208
2209static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2210 // Do not inline strictfp function into non-strictfp one. It would require
2211 // conversion of all FP operations in host function to constrained intrinsics.
2212 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2213 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2214}
2215
2216template<typename AttrClass>
2217static bool isEqual(const Function &Caller, const Function &Callee) {
2218 return Caller.getFnAttribute(AttrClass::getKind()) ==
2219 Callee.getFnAttribute(AttrClass::getKind());
2220}
2221
2222static bool isEqual(const Function &Caller, const Function &Callee,
2223 const StringRef &AttrName) {
2224 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2225}
2226
2227/// Compute the logical AND of the attributes of the caller and the
2228/// callee.
2229///
2230/// This function sets the caller's attribute to false if the callee's attribute
2231/// is false.
2232template<typename AttrClass>
2233static void setAND(Function &Caller, const Function &Callee) {
2234 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2235 !AttrClass::isSet(Callee, AttrClass::getKind()))
2236 AttrClass::set(Caller, AttrClass::getKind(), false);
2237}
2238
2239/// Compute the logical OR of the attributes of the caller and the
2240/// callee.
2241///
2242/// This function sets the caller's attribute to true if the callee's attribute
2243/// is true.
2244template<typename AttrClass>
2245static void setOR(Function &Caller, const Function &Callee) {
2246 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2247 AttrClass::isSet(Callee, AttrClass::getKind()))
2248 AttrClass::set(Caller, AttrClass::getKind(), true);
2249}
2250
2251/// If the inlined function had a higher stack protection level than the
2252/// calling function, then bump up the caller's stack protection level.
2253static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2254 // If the calling function has *no* stack protection level (e.g. it was built
2255 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2256 // change it as that could change the program's semantics.
2257 if (!Caller.hasStackProtectorFnAttr())
2258 return;
2259
2260 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2261 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2262 // clutter to the IR.
2263 AttributeMask OldSSPAttr;
2264 OldSSPAttr.addAttribute(Attribute::StackProtect)
2265 .addAttribute(Attribute::StackProtectStrong)
2266 .addAttribute(Attribute::StackProtectReq);
2267
2268 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2269 Caller.removeFnAttrs(OldSSPAttr);
2270 Caller.addFnAttr(Attribute::StackProtectReq);
2271 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2272 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2273 Caller.removeFnAttrs(OldSSPAttr);
2274 Caller.addFnAttr(Attribute::StackProtectStrong);
2275 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2276 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2277 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2278 Caller.addFnAttr(Attribute::StackProtect);
2279}
2280
2281/// If the inlined function required stack probes, then ensure that
2282/// the calling function has those too.
2283static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2284 if (!Caller.hasFnAttribute("probe-stack") &&
2285 Callee.hasFnAttribute("probe-stack")) {
2286 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2287 }
2288}
2289
2290/// If the inlined function defines the size of guard region
2291/// on the stack, then ensure that the calling function defines a guard region
2292/// that is no larger.
2293static void
2295 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2296 if (CalleeAttr.isValid()) {
2297 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2298 if (CallerAttr.isValid()) {
2299 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2300 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2301 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2302
2303 if (CallerStackProbeSize > CalleeStackProbeSize) {
2304 Caller.addFnAttr(CalleeAttr);
2305 }
2306 } else {
2307 Caller.addFnAttr(CalleeAttr);
2308 }
2309 }
2310}
2311
2312/// If the inlined function defines a min legal vector width, then ensure
2313/// the calling function has the same or larger min legal vector width. If the
2314/// caller has the attribute, but the callee doesn't, we need to remove the
2315/// attribute from the caller since we can't make any guarantees about the
2316/// caller's requirements.
2317/// This function is called after the inlining decision has been made so we have
2318/// to merge the attribute this way. Heuristics that would use
2319/// min-legal-vector-width to determine inline compatibility would need to be
2320/// handled as part of inline cost analysis.
2321static void
2323 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2324 if (CallerAttr.isValid()) {
2325 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2326 if (CalleeAttr.isValid()) {
2327 uint64_t CallerVectorWidth, CalleeVectorWidth;
2328 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2329 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2330 if (CallerVectorWidth < CalleeVectorWidth)
2331 Caller.addFnAttr(CalleeAttr);
2332 } else {
2333 // If the callee doesn't have the attribute then we don't know anything
2334 // and must drop the attribute from the caller.
2335 Caller.removeFnAttr("min-legal-vector-width");
2336 }
2337 }
2338}
2339
2340/// If the inlined function has null_pointer_is_valid attribute,
2341/// set this attribute in the caller post inlining.
2342static void
2344 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2345 Caller.addFnAttr(Attribute::NullPointerIsValid);
2346 }
2347}
2348
2349struct EnumAttr {
2350 static bool isSet(const Function &Fn,
2351 Attribute::AttrKind Kind) {
2352 return Fn.hasFnAttribute(Kind);
2353 }
2354
2355 static void set(Function &Fn,
2356 Attribute::AttrKind Kind, bool Val) {
2357 if (Val)
2358 Fn.addFnAttr(Kind);
2359 else
2360 Fn.removeFnAttr(Kind);
2361 }
2362};
2363
2365 static bool isSet(const Function &Fn,
2366 StringRef Kind) {
2367 auto A = Fn.getFnAttribute(Kind);
2368 return A.getValueAsString() == "true";
2369 }
2370
2371 static void set(Function &Fn,
2372 StringRef Kind, bool Val) {
2373 Fn.addFnAttr(Kind, Val ? "true" : "false");
2374 }
2375};
2376
2377#define GET_ATTR_NAMES
2378#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2379 struct ENUM_NAME##Attr : EnumAttr { \
2380 static enum Attribute::AttrKind getKind() { \
2381 return llvm::Attribute::ENUM_NAME; \
2382 } \
2383 };
2384#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2385 struct ENUM_NAME##Attr : StrBoolAttr { \
2386 static StringRef getKind() { return #DISPLAY_NAME; } \
2387 };
2388#include "llvm/IR/Attributes.inc"
2389
2390#define GET_ATTR_COMPAT_FUNC
2391#include "llvm/IR/Attributes.inc"
2392
2394 const Function &Callee) {
2395 return hasCompatibleFnAttrs(Caller, Callee);
2396}
2397
2399 const Function &B) {
2400 return hasCompatibleFnAttrs(A, B);
2401}
2402
2404 const Function &Callee) {
2405 mergeFnAttrs(Caller, Callee);
2406}
2407
2409 const Function &ToMerge) {
2410
2411 // We merge functions so that they meet the most general case.
2412 // For example, if the NoNansFPMathAttr is set in one function, but not in
2413 // the other, in the merged function we can say that the NoNansFPMathAttr
2414 // is not set.
2415 // However if we have the SpeculativeLoadHardeningAttr set true in one
2416 // function, but not the other, we make sure that the function retains
2417 // that aspect in the merged function.
2418 mergeFnAttrs(Base, ToMerge);
2419}
2420
2422 uint64_t Width) {
2423 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2424 if (Attr.isValid()) {
2425 uint64_t OldWidth;
2426 Attr.getValueAsString().getAsInteger(0, OldWidth);
2427 if (Width > OldWidth)
2428 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2429 }
2430}
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)
Definition: Attributes.cpp:86
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
Definition: Attributes.cpp:726
@ RetAttr
Definition: Attributes.cpp:729
@ ParamAttr
Definition: Attributes.cpp:728
@ FnAttr
Definition: Attributes.cpp:727
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)
Definition: Attributes.cpp:60
static uint64_t packVScaleRangeArgs(unsigned MinValue, std::optional< unsigned > MaxValue)
Definition: Attributes.cpp:80
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
Definition: Attributes.cpp:58
static std::pair< unsigned, std::optional< unsigned > > unpackAllocSizeArgs(uint64_t Num)
Definition: Attributes.cpp:70
static bool checkDenormMode(const Function &Caller, const Function &Callee)
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)
Definition: Attributes.cpp:735
static const char * getModRefStr(ModRefInfo MR)
Definition: Attributes.cpp:508
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:533
std::string Name
This file defines a hash set that can be used to remove duplication of nodes in a graph.
#define I(x, y, z)
Definition: MD5.cpp:58
Load MIR Sample Profile
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
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...
void Profile(FoldingSetNodeID &id) const
Used to insert APInt objects, or objects that contain APInt objects, into FoldingSets.
Definition: APInt.cpp:155
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
const T & back() const
back - Get the last element.
Definition: ArrayRef.h:174
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition: ArrayRef.h:228
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
iterator begin() const
Definition: ArrayRef.h:153
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
Class to represent array types.
Definition: DerivedTypes.h:371
AttrBuilder & addStructRetAttr(Type *Ty)
This turns a sret type into the form used internally in Attribute.
AttrBuilder & addAlignmentAttr(MaybeAlign Align)
This turns an alignment into the form used internally in Attribute.
AttrBuilder & addVScaleRangeAttrFromRawRepr(uint64_t RawVScaleRangeRepr)
Add a vscale_range attribute, using the representation returned by Attribute.getIntValue().
std::optional< uint64_t > getRawIntAttr(Attribute::AttrKind Kind) const
Return raw (possibly packed/encoded) value of integer attribute or std::nullopt if not set.
AttrBuilder & addAllocKindAttr(AllocFnKind Kind)
Attribute getAttribute(Attribute::AttrKind Kind) const
Return Attribute with the given Kind.
AttrBuilder & addByRefAttr(Type *Ty)
This turns a byref type into the form used internally in Attribute.
AttrBuilder & addNoFPClassAttr(FPClassTest NoFPClassMask)
bool overlaps(const AttributeMask &AM) const
Return true if the builder has any attribute that's in the specified builder.
AttrBuilder & merge(const AttrBuilder &B)
Add the attributes from the builder.
AttrBuilder & addVScaleRangeAttr(unsigned MinValue, std::optional< unsigned > MaxValue)
This turns two ints into the form used internally in Attribute.
AttrBuilder(LLVMContext &Ctx)
Definition: Attributes.h:1038
AttrBuilder & addRawIntAttr(Attribute::AttrKind Kind, uint64_t Value)
Add integer attribute with raw value (packed/encoded if necessary).
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
AttrBuilder & addByValAttr(Type *Ty)
This turns a byval type into the form used internally in Attribute.
AttrBuilder & addDereferenceableAttr(uint64_t Bytes)
This turns the number of dereferenceable bytes into the form used internally in Attribute.
AttrBuilder & addInitializesAttr(const ConstantRangeList &CRL)
Add initializes attribute.
bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
AttrBuilder & addMemoryAttr(MemoryEffects ME)
Add memory effect attribute.
AttrBuilder & addConstantRangeListAttr(Attribute::AttrKind Kind, ArrayRef< ConstantRange > Val)
Add a ConstantRangeList attribute with the given ranges.
AttrBuilder & addConstantRangeAttr(Attribute::AttrKind Kind, const ConstantRange &CR)
Add a ConstantRange attribute with the given range.
AttrBuilder & addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr)
Add an allocsize attribute, using the representation returned by Attribute.getIntValue().
AttrBuilder & addPreallocatedAttr(Type *Ty)
This turns a preallocated type into the form used internally in Attribute.
AttrBuilder & addStackAlignmentAttr(MaybeAlign Align)
This turns a stack alignment into the form used internally in Attribute.
AttrBuilder & addInAllocaAttr(Type *Ty)
This turns an inalloca type into the form used internally in Attribute.
AttrBuilder & removeAttribute(Attribute::AttrKind Val)
Remove an attribute from the builder.
bool operator==(const AttrBuilder &B) const
Type * getTypeAttr(Attribute::AttrKind Kind) const
Retrieve type for the given type attribute.
AttrBuilder & remove(const AttributeMask &AM)
Remove the attributes from the builder.
AttrBuilder & addDereferenceableOrNullAttr(uint64_t Bytes)
This turns the number of dereferenceable_or_null bytes into the form used internally in Attribute.
AttrBuilder & addTypeAttr(Attribute::AttrKind Kind, Type *Ty)
Add a type attribute with the given type.
std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
Retrieve the allocsize args, or std::nullopt if the attribute does not exist.
AttrBuilder & addAllocSizeAttr(unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
This turns one (or two) ints into the form used internally in Attribute.
AttrBuilder & addRangeAttr(const ConstantRange &CR)
Add range attribute.
AttrBuilder & addUWTableAttr(UWTableKind Kind)
This turns the unwind table kind into the form used internally in Attribute.
void addAttribute(Attribute::AttrKind Kind)
bool hasAttribute(Attribute::AttrKind Kind) const
bool isConstantRangeAttribute() const
Definition: AttributeImpl.h:66
bool hasAttribute(Attribute::AttrKind A) const
Definition: Attributes.cpp:758
void Profile(FoldingSetNodeID &ID) const
Definition: AttributeImpl.h:92
Type * getValueAsType() const
Definition: Attributes.cpp:794
Attribute::AttrKind getKindAsEnum() const
Definition: Attributes.cpp:768
bool operator<(const AttributeImpl &AI) const
Used when sorting the attributes.
Definition: Attributes.cpp:811
uint64_t getValueAsInt() const
Definition: Attributes.cpp:774
bool isIntAttribute() const
Definition: AttributeImpl.h:63
bool isTypeAttribute() const
Definition: AttributeImpl.h:65
bool getValueAsBool() const
Definition: Attributes.cpp:779
StringRef getKindAsString() const
Definition: Attributes.cpp:784
StringRef getValueAsString() const
Definition: Attributes.cpp:789
bool isEnumAttribute() const
Definition: AttributeImpl.h:62
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Definition: Attributes.cpp:805
bool isConstantRangeListAttribute() const
Definition: AttributeImpl.h:69
bool isStringAttribute() const
Definition: AttributeImpl.h:64
const ConstantRange & getValueAsConstantRange() const
Definition: Attributes.cpp:799
bool hasAttrSomewhere(Attribute::AttrKind Kind, unsigned *Index=nullptr) const
Return true if the specified attribute is set for at least one parameter or for the return value.
iterator begin() const
void Profile(FoldingSetNodeID &ID) const
AttributeListImpl(ArrayRef< AttributeSet > Sets)
iterator end() const
friend class AttributeList
bool hasAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
Type * getParamStructRetType(unsigned ArgNo) const
Return the sret type for the specified function parameter.
AttributeList addDereferenceableParamAttr(LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const
Add the dereferenceable attribute to the attribute set at the given arg index.
AttributeList removeAttributeAtIndex(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Remove the specified attribute at the specified index from this attribute list.
AttributeList addRangeRetAttr(LLVMContext &C, const ConstantRange &CR) const
Add the range attribute to the attribute set at the return value index.
bool hasAttributesAtIndex(unsigned Index) const
Return true if attribute exists at the given index.
friend class AttributeListImpl
Definition: Attributes.h:478
AttributeSet getFnAttrs() const
The function attributes are returned.
index_iterator indexes() const
Use this to iterate over the valid attribute indexes.
Definition: Attributes.h:982
AttributeList removeAttributesAtIndex(LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const
Remove the specified attributes at the specified index from this attribute list.
friend class AttributeSet
Definition: Attributes.h:479
AttributeList()=default
AttributeList addAllocSizeParamAttr(LLVMContext &C, unsigned ArgNo, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
Add the allocsize attribute to the attribute set at the given arg index.
iterator begin() const
MaybeAlign getRetStackAlignment() const
Get the stack alignment of the return value.
AttributeList addRetAttributes(LLVMContext &C, const AttrBuilder &B) const
Add a return value attribute to the list.
Definition: Attributes.h:598
void print(raw_ostream &O) const
AttributeList addDereferenceableRetAttr(LLVMContext &C, uint64_t Bytes) const
Add the dereferenceable attribute to the attribute set at the given index.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
AllocFnKind getAllocKind() const
bool isEmpty() const
Return true if there are no attributes.
Definition: Attributes.h:994
AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
friend class AttrBuilder
Definition: Attributes.h:477
bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
uint64_t getParamDereferenceableBytes(unsigned Index) const
Get the number of dereferenceable bytes (or zero if unknown) of an arg.
MaybeAlign getParamAlignment(unsigned ArgNo) const
Return the alignment for the specified function parameter.
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 end() const
Type * getParamInAllocaType(unsigned ArgNo) const
Return the inalloca type for the specified function parameter.
unsigned getNumAttrSets() const
FPClassTest getRetNoFPClass() const
Get the disallowed floating-point classes of the return value.
std::string getAsString(unsigned Index, bool InAttrGrp=false) const
Return the attributes at the index as a string.
UWTableKind getUWTableKind() const
Get the unwind table kind requested for the function.
MaybeAlign getRetAlignment() const
Return the alignment of the return value.
Type * getParamElementType(unsigned ArgNo) const
Return the elementtype type for the specified function parameter.
Attribute getAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const
Return the attribute object that exists at the given index.
Type * getParamPreallocatedType(unsigned ArgNo) const
Return the preallocated type for the specified function parameter.
bool hasParentContext(LLVMContext &C) const
Return true if this attribute list belongs to the LLVMContext.
const AttributeSet * iterator
Definition: Attributes.h:950
MaybeAlign getFnStackAlignment() const
Get the stack alignment of the function.
AttributeList addAttributesAtIndex(LLVMContext &C, unsigned Index, const AttrBuilder &B) const
Add attributes to the attribute set at the given index.
Type * getParamByValType(unsigned ArgNo) const
Return the byval type for the specified function parameter.
MaybeAlign getParamStackAlignment(unsigned ArgNo) const
Return the stack alignment for the specified function parameter.
uint64_t getRetDereferenceableBytes() const
Get the number of dereferenceable bytes (or zero if unknown) of the return value.
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const
Get the number of dereferenceable_or_null bytes (or zero if unknown) of an arg.
AttributeList addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const
Add the dereferenceable_or_null attribute to the attribute set at the given arg index.
AttributeSet getAttributes(unsigned Index) const
The attributes for the specified index are returned.
FPClassTest getParamNoFPClass(unsigned ArgNo) const
Get the disallowed floating-point classes of the argument value.
Type * getParamByRefType(unsigned ArgNo) const
Return the byref type for the specified function parameter.
AttributeList addAttributeAtIndex(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Add an attribute to the attribute set at the given index.
AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
AttributeList addParamAttributes(LLVMContext &C, unsigned ArgNo, const AttrBuilder &B) const
Add an argument attribute to the list.
Definition: Attributes.h:627
uint64_t getRetDereferenceableOrNullBytes() const
Get the number of dereferenceable_or_null bytes (or zero if unknown) of the return value.
AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const
Add an argument attribute to the list.
Definition: Attributes.h:606
MemoryEffects getMemoryEffects() const
Returns memory effects of the function.
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
Definition: AttributeMask.h:44
bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
Definition: AttributeMask.h:67
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
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
uint64_t getDereferenceableBytes() const
unsigned getNumAttributes() const
Return the number of attributes this AttributeList contains.
void Profile(FoldingSetNodeID &ID) const
std::string getAsString(bool InAttrGrp) const
static AttributeSetNode * get(LLVMContext &C, const AttrBuilder &B)
FPClassTest getNoFPClass() const
Attribute getAttribute(Attribute::AttrKind Kind) const
AllocFnKind getAllocKind() const
Definition: Attributes.cpp:985
bool hasAttributes() const
Return true if attributes exists in this set.
Definition: Attributes.h:390
AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Remove the specified attribute from this set.
Definition: Attributes.cpp:879
Type * getInAllocaType() const
Definition: Attributes.cpp:958
Type * getByValType() const
Definition: Attributes.cpp:946
AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
Definition: Attributes.cpp:866
MemoryEffects getMemoryEffects() const
Definition: Attributes.cpp:989
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
Definition: Attributes.cpp:910
Type * getStructRetType() const
Definition: Attributes.cpp:950
std::string getAsString(bool InAttrGrp=false) const
Definition: Attributes.cpp:997
unsigned getVScaleRangeMin() const
Definition: Attributes.cpp:973
std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
Definition: Attributes.cpp:967
UWTableKind getUWTableKind() const
Definition: Attributes.cpp:981
bool hasParentContext(LLVMContext &C) const
Return true if this attribute set belongs to the LLVMContext.
iterator begin() const
iterator end() const
AttributeSet removeAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const
Remove the specified attributes from this set.
Definition: Attributes.cpp:895
std::optional< unsigned > getVScaleRangeMax() const
Definition: Attributes.cpp:977
MaybeAlign getStackAlignment() const
Definition: Attributes.cpp:930
Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
Definition: Attributes.cpp:918
Type * getPreallocatedType() const
Definition: Attributes.cpp:954
uint64_t getDereferenceableBytes() const
Definition: Attributes.cpp:934
MaybeAlign getAlignment() const
Definition: Attributes.cpp:926
FPClassTest getNoFPClass() const
Definition: Attributes.cpp:993
Type * getElementType() const
Definition: Attributes.cpp:962
Type * getByRefType() const
Definition: Attributes.cpp:942
AttributeSet()=default
AttributeSet is a trivially copyable value type.
static AttributeSet get(LLVMContext &C, const AttrBuilder &B)
Definition: Attributes.cpp:843
uint64_t getDereferenceableOrNullBytes() const
Definition: Attributes.cpp:938
unsigned getNumAttributes() const
Return the number of attributes in this set.
Definition: Attributes.cpp:906
AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
Definition: Attributes.cpp:851
void dump() const
bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
Definition: Attributes.cpp:347
static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:259
static Attribute::AttrKind getAttrKindFromName(StringRef AttrName)
Definition: Attributes.cpp:304
bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
Definition: Attributes.cpp:339
static Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment)
Definition: Attributes.cpp:238
const ConstantRange & getRange() const
Returns the value of the range attribute.
Definition: Attributes.cpp:496
bool isIntAttribute() const
Return true if the attribute is an integer attribute.
Definition: Attributes.cpp:343
static Attribute getWithByRefType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:263
std::optional< unsigned > getVScaleRangeMax() const
Returns the maximum value for the vscale_range attribute or std::nullopt when unknown.
Definition: Attributes.cpp:466
uint64_t getValueAsInt() const
Return the attribute's value as an integer.
Definition: Attributes.cpp:371
unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
Definition: Attributes.cpp:460
AllocFnKind getAllocKind() const
Definition: Attributes.cpp:478
bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
Definition: Attributes.cpp:355
StringRef getKindAsString() const
Return the attribute's kind as a string.
Definition: Attributes.cpp:385
static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:267
static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
Definition: Attributes.cpp:94
static bool canUseAsRetAttr(AttrKind Kind)
Definition: Attributes.cpp:750
static bool isTypeAttrKind(AttrKind Kind)
Definition: Attributes.h:105
std::string getAsString(bool InAttrGrp=false) const
The Attribute is converted to a string of equivalent mnemonic.
Definition: Attributes.cpp:522
uint64_t getDereferenceableOrNullBytes() const
Returns the number of dereferenceable_or_null bytes from the dereferenceable_or_null attribute.
Definition: Attributes.cpp:446
static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
Definition: Attributes.cpp:243
std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
Definition: Attributes.cpp:454
static Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind)
Definition: Attributes.cpp:275
FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
Definition: Attributes.cpp:490
static Attribute getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
Definition: Attributes.cpp:291
Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
Definition: Attributes.cpp:363
Attribute()=default
bool getValueAsBool() const
Return the attribute's value as a boolean.
Definition: Attributes.cpp:378
ArrayRef< ConstantRange > getInitializes() const
Returns the value of the initializes attribute.
Definition: Attributes.cpp:502
const ConstantRange & getValueAsConstantRange() const
Return the attribute's value as a ConstantRange.
Definition: Attributes.cpp:406
uint64_t getDereferenceableBytes() const
Returns the number of dereferenceable bytes from the dereferenceable attribute.
Definition: Attributes.cpp:439
static Attribute getWithVScaleRangeArgs(LLVMContext &Context, unsigned MinValue, unsigned MaxValue)
Definition: Attributes.cpp:298
MemoryEffects getMemoryEffects() const
Returns memory effects.
Definition: Attributes.cpp:484
void Profile(FoldingSetNodeID &ID) const
Definition: Attributes.cpp:722
UWTableKind getUWTableKind() const
Definition: Attributes.cpp:472
static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, uint64_t Bytes)
Definition: Attributes.cpp:249
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
Definition: Attributes.cpp:412
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:392
static bool isExistingAttribute(StringRef Name)
Return true if the provided string matches the IR name of an attribute.
Definition: Attributes.cpp:327
static StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind)
Definition: Attributes.cpp:313
static bool canUseAsFnAttr(AttrKind Kind)
Definition: Attributes.cpp:742
static Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
Definition: Attributes.cpp:285
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition: Attributes.h:86
@ None
No attributes have been set.
Definition: Attributes.h:88
@ EndAttrKinds
Sentinel value useful for loops.
Definition: Attributes.h:91
static bool isConstantRangeAttrKind(AttrKind Kind)
Definition: Attributes.h:108
bool hasParentContext(LLVMContext &C) const
Return true if this attribute belongs to the LLVMContext.
Definition: Attributes.cpp:707
bool isTypeAttribute() const
Return true if the attribute is a type attribute.
Definition: Attributes.cpp:351
static Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:271
static bool isIntAttrKind(AttrKind Kind)
Definition: Attributes.h:102
static bool isConstantRangeListAttrKind(AttrKind Kind)
Definition: Attributes.h:111
bool isConstantRangeListAttribute() const
Return true if the attribute is a ConstantRangeList attribute.
Definition: Attributes.cpp:359
static Attribute getWithByValType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:255
bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
Definition: Attributes.cpp:418
static bool isEnumAttrKind(AttrKind Kind)
Definition: Attributes.h:99
static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
Definition: Attributes.cpp:280
static bool canUseAsParamAttr(AttrKind Kind)
Definition: Attributes.cpp:746
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:203
MaybeAlign getStackAlignment() const
Returns the stack alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:433
MaybeAlign getAlignment() const
Returns the alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:427
bool operator<(Attribute A) const
Less-than operator. Useful for sorting the attributes list.
Definition: Attributes.cpp:715
static Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
Definition: Attributes.cpp:233
Type * getValueAsType() const
Return the attribute's value as a Type.
Definition: Attributes.cpp:399
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
Definition: Allocator.h:148
static size_t totalSizeToAlloc(ArrayRef< ConstantRange > Val)
This class represents a list of constant ranges.
ArrayRef< ConstantRange > rangesRef() const
void print(raw_ostream &OS) const
Print out the ranges to a stream.
This class represents a range of values.
Definition: ConstantRange.h:47
const APInt & getLower() const
Return the lower value for this range.
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.
uint32_t getBitWidth() const
Get the bit width of this ConstantRange.
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
Definition: FoldingSet.h:327
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition: Function.cpp:653
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition: Function.cpp:769
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition: Function.cpp:701
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:743
FoldingSet< AttributeImpl > AttrsSet
BumpPtrAllocator Alloc
FoldingSet< AttributeSetNode > AttrsSetNodes
FoldingSet< AttributeListImpl > AttrsLists
SpecificBumpPtrAllocator< ConstantRangeAttributeImpl > ConstantRangeAttributeAlloc
std::vector< ConstantRangeListAttributeImpl * > ConstantRangeListAttributes
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
LLVMContextImpl *const pImpl
Definition: LLVMContext.h:69
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition: ModRef.h:165
static MemoryEffectsBase createFromIntValue(uint32_t Data)
Create MemoryEffectsBase from an encoded integer value (used by memory attribute).
Definition: ModRef.h:154
static auto locations()
Returns iterator over all supported location kinds.
Definition: ModRef.h:95
uint32_t toIntValue() const
Convert MemoryEffectsBase into an encoded integer value (used by memory attribute).
Definition: ModRef.h:160
static MemoryEffectsBase unknown()
Create MemoryEffectsBase that can read and write any memory.
Definition: ModRef.h:112
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:950
void reserve(size_type N)
Definition: SmallVector.h:676
void resize(size_type N)
Definition: SmallVector.h:651
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
static size_t totalSizeToAlloc(StringRef Kind, StringRef Val)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:455
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:215
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
R Default(T Value)
Definition: StringSwitch.h:182
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
Definition: Type.h:230
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:251
void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
Definition: Type.h:258
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:224
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
Definition: Type.h:212
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:139
LLVM Value Representation.
Definition: Value.h:74
static constexpr uint64_t MaximumAlignment
Definition: Value.h:807
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:661
This class provides various memory handling functions that manipulate MemoryBlock instances.
Definition: Memory.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool areInlineCompatible(const Function &Caller, const Function &Callee)
AttributeMask getUBImplyingAttributes()
Get param/return attributes which imply immediate undefined behavior if an invalid value is passed.
bool isNoFPClassCompatibleType(Type *Ty)
Returns true if this is a type legal for the 'nofpclass' attribute.
bool areOutlineCompatible(const Function &A, const Function &B)
Checks if there are any incompatible function attributes between A and B.
void updateMinLegalVectorWidthAttr(Function &Fn, uint64_t Width)
Update min-legal-vector-width if it is in Attribute and less than Width.
void mergeAttributesForOutlining(Function &Base, const Function &ToMerge)
Merges the functions attributes from ToMerge into function Base.
void mergeAttributesForInlining(Function &Caller, const Function &Callee)
Merge caller's and callee's attributes.
AttributeMask typeIncompatible(Type *Ty, AttributeSafetyKind ASK=ASK_ALL)
Which attributes cannot be applied to a type.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:1722
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
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:1680
AllocFnKind
Definition: Attributes.h:49
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2098
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:1729
UWTableKind
Definition: CodeGen.h:120
@ None
No unwind table requested.
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1647
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
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:1736
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:1909
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
Definition: ModRef.h:27
@ Ref
The access may reference the value stored in memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ Mod
The access may modify the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
@ ArgMem
Access to memory via argument pointers.
@ Other
Any other memory.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ InaccessibleMem
Memory that is inaccessible via LLVM IR.
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:1961
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1824
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:2082
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
Attribute comparator that only compares attribute keys.
bool operator()(Attribute A0, StringRef Kind) const
bool operator()(Attribute A0, Attribute A1) const
bool operator()(Attribute A0, Attribute::AttrKind Kind) const
static void set(Function &Fn, Attribute::AttrKind Kind, bool Val)
static bool isSet(const Function &Fn, Attribute::AttrKind Kind)
static bool isSet(const Function &Fn, StringRef Kind)
static void set(Function &Fn, StringRef Kind, bool Val)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
Represent subnormal handling kind for floating point instruction inputs and outputs.
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getInvalid()
DenormalModeKind Output
Denormal flushing mode for floating point instruction results in the default floating point environme...
static constexpr DenormalMode getDynamic()
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition: Alignment.h:117
Function object to check whether the first component of a container supported by std::get (like std::...
Definition: STLExtras.h:1450