LLVM 19.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 LLVMContextImpl *pImpl = Context.pImpl;
176 ID.AddInteger(Kind);
177 CR.getLower().Profile(ID);
178 CR.getUpper().Profile(ID);
179
180 void *InsertPoint;
181 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
182
183 if (!PA) {
184 // If we didn't find any existing attributes of the same shape then create a
185 // new one and insert it.
186 PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
188 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
189 }
190
191 // Return the Attribute that we found or created.
192 return Attribute(PA);
193}
194
198 "Not a ConstantRangeList attribute");
199 LLVMContextImpl *pImpl = Context.pImpl;
201 ID.AddInteger(Kind);
202 ID.AddInteger(Val.size());
203 for (auto &CR : Val) {
204 CR.getLower().Profile(ID);
205 CR.getUpper().Profile(ID);
206 }
207
208 void *InsertPoint;
209 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
210
211 if (!PA) {
212 // If we didn't find any existing attributes of the same shape then create a
213 // new one and insert it.
214 // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
215 // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
216 // allocation and record the allocated pointer in
217 // `ConstantRangeListAttributes`. LLVMContext destructor will call the
218 // destructor of the allocated pointer explicitly.
219 void *Mem = pImpl->Alloc.Allocate(
222 PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
223 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
224 pImpl->ConstantRangeListAttributes.push_back(
225 reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
226 }
227
228 // Return the Attribute that we found or created.
229 return Attribute(PA);
230}
231
233 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
234 return get(Context, Alignment, A.value());
235}
236
238 assert(A <= 0x100 && "Alignment too large.");
239 return get(Context, StackAlignment, A.value());
240}
241
243 uint64_t Bytes) {
244 assert(Bytes && "Bytes must be non-zero.");
245 return get(Context, Dereferenceable, Bytes);
246}
247
249 uint64_t Bytes) {
250 assert(Bytes && "Bytes must be non-zero.");
251 return get(Context, DereferenceableOrNull, Bytes);
252}
253
255 return get(Context, ByVal, Ty);
256}
257
259 return get(Context, StructRet, Ty);
260}
261
263 return get(Context, ByRef, Ty);
264}
265
267 return get(Context, Preallocated, Ty);
268}
269
271 return get(Context, InAlloca, Ty);
272}
273
275 UWTableKind Kind) {
276 return get(Context, UWTable, uint64_t(Kind));
277}
278
280 MemoryEffects ME) {
281 return get(Context, Memory, ME.toIntValue());
282}
283
285 FPClassTest ClassMask) {
286 return get(Context, NoFPClass, ClassMask);
287}
288
290Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
291 const std::optional<unsigned> &NumElemsArg) {
292 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
293 "Invalid allocsize arguments -- given allocsize(0, 0)");
294 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
295}
296
298 unsigned MinValue,
299 unsigned MaxValue) {
300 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
301}
302
304 return StringSwitch<Attribute::AttrKind>(AttrName)
305#define GET_ATTR_NAMES
306#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
307 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
308#include "llvm/IR/Attributes.inc"
310}
311
313 switch (AttrKind) {
314#define GET_ATTR_NAMES
315#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
316 case Attribute::ENUM_NAME: \
317 return #DISPLAY_NAME;
318#include "llvm/IR/Attributes.inc"
319 case Attribute::None:
320 return "none";
321 default:
322 llvm_unreachable("invalid Kind");
323 }
324}
325
328#define GET_ATTR_NAMES
329#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
330#include "llvm/IR/Attributes.inc"
331 .Default(false);
332}
333
334//===----------------------------------------------------------------------===//
335// Attribute Accessor Methods
336//===----------------------------------------------------------------------===//
337
339 return pImpl && pImpl->isEnumAttribute();
340}
341
343 return pImpl && pImpl->isIntAttribute();
344}
345
347 return pImpl && pImpl->isStringAttribute();
348}
349
351 return pImpl && pImpl->isTypeAttribute();
352}
353
355 return pImpl && pImpl->isConstantRangeAttribute();
356}
357
359 return pImpl && pImpl->isConstantRangeListAttribute();
360}
361
363 if (!pImpl) return None;
366 "Invalid attribute type to get the kind as an enum!");
367 return pImpl->getKindAsEnum();
368}
369
371 if (!pImpl) return 0;
373 "Expected the attribute to be an integer attribute!");
374 return pImpl->getValueAsInt();
375}
376
378 if (!pImpl) return false;
380 "Expected the attribute to be a string attribute!");
381 return pImpl->getValueAsBool();
382}
383
385 if (!pImpl) return {};
387 "Invalid attribute type to get the kind as a string!");
388 return pImpl->getKindAsString();
389}
390
392 if (!pImpl) return {};
394 "Invalid attribute type to get the value as a string!");
395 return pImpl->getValueAsString();
396}
397
399 if (!pImpl) return {};
401 "Invalid attribute type to get the value as a type!");
402 return pImpl->getValueAsType();
403}
404
407 "Invalid attribute type to get the value as a ConstantRange!");
408 return pImpl->getValueAsConstantRange();
409}
410
413 "Invalid attribute type to get the value as a ConstantRangeList!");
414 return pImpl->getValueAsConstantRangeList();
415}
416
418 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
419}
420
422 if (!isStringAttribute()) return false;
423 return pImpl && pImpl->hasAttribute(Kind);
424}
425
427 assert(hasAttribute(Attribute::Alignment) &&
428 "Trying to get alignment from non-alignment attribute!");
429 return MaybeAlign(pImpl->getValueAsInt());
430}
431
433 assert(hasAttribute(Attribute::StackAlignment) &&
434 "Trying to get alignment from non-alignment attribute!");
435 return MaybeAlign(pImpl->getValueAsInt());
436}
437
439 assert(hasAttribute(Attribute::Dereferenceable) &&
440 "Trying to get dereferenceable bytes from "
441 "non-dereferenceable attribute!");
442 return pImpl->getValueAsInt();
443}
444
446 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
447 "Trying to get dereferenceable bytes from "
448 "non-dereferenceable attribute!");
449 return pImpl->getValueAsInt();
450}
451
452std::pair<unsigned, std::optional<unsigned>>
454 assert(hasAttribute(Attribute::AllocSize) &&
455 "Trying to get allocsize args from non-allocsize attribute");
456 return unpackAllocSizeArgs(pImpl->getValueAsInt());
457}
458
460 assert(hasAttribute(Attribute::VScaleRange) &&
461 "Trying to get vscale args from non-vscale attribute");
462 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
463}
464
465std::optional<unsigned> Attribute::getVScaleRangeMax() const {
466 assert(hasAttribute(Attribute::VScaleRange) &&
467 "Trying to get vscale args from non-vscale attribute");
468 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
469}
470
472 assert(hasAttribute(Attribute::UWTable) &&
473 "Trying to get unwind table kind from non-uwtable attribute");
474 return UWTableKind(pImpl->getValueAsInt());
475}
476
478 assert(hasAttribute(Attribute::AllocKind) &&
479 "Trying to get allockind value from non-allockind attribute");
480 return AllocFnKind(pImpl->getValueAsInt());
481}
482
484 assert(hasAttribute(Attribute::Memory) &&
485 "Can only call getMemoryEffects() on memory attribute");
487}
488
490 assert(hasAttribute(Attribute::NoFPClass) &&
491 "Can only call getNoFPClass() on nofpclass attribute");
492 return static_cast<FPClassTest>(pImpl->getValueAsInt());
493}
494
496 assert(hasAttribute(Attribute::Range) &&
497 "Trying to get range args from non-range attribute");
498 return pImpl->getValueAsConstantRange();
499}
500
502 assert(hasAttribute(Attribute::Initializes) &&
503 "Trying to get initializes attr from non-ConstantRangeList attribute");
504 return pImpl->getValueAsConstantRangeList();
505}
506
507static const char *getModRefStr(ModRefInfo MR) {
508 switch (MR) {
510 return "none";
511 case ModRefInfo::Ref:
512 return "read";
513 case ModRefInfo::Mod:
514 return "write";
516 return "readwrite";
517 }
518 llvm_unreachable("Invalid ModRefInfo");
519}
520
521std::string Attribute::getAsString(bool InAttrGrp) const {
522 if (!pImpl) return {};
523
524 if (isEnumAttribute())
526
527 if (isTypeAttribute()) {
528 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
529 Result += '(';
530 raw_string_ostream OS(Result);
531 getValueAsType()->print(OS, false, true);
532 OS.flush();
533 Result += ')';
534 return Result;
535 }
536
537 // FIXME: These should be output like this:
538 //
539 // align=4
540 // alignstack=8
541 //
542 if (hasAttribute(Attribute::Alignment))
543 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
544 : "align " + Twine(getValueAsInt()))
545 .str();
546
547 auto AttrWithBytesToString = [&](const char *Name) {
548 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
549 : Name + ("(" + Twine(getValueAsInt())) + ")")
550 .str();
551 };
552
553 if (hasAttribute(Attribute::StackAlignment))
554 return AttrWithBytesToString("alignstack");
555
556 if (hasAttribute(Attribute::Dereferenceable))
557 return AttrWithBytesToString("dereferenceable");
558
559 if (hasAttribute(Attribute::DereferenceableOrNull))
560 return AttrWithBytesToString("dereferenceable_or_null");
561
562 if (hasAttribute(Attribute::AllocSize)) {
563 unsigned ElemSize;
564 std::optional<unsigned> NumElems;
565 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
566
567 return (NumElems
568 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
569 : "allocsize(" + Twine(ElemSize) + ")")
570 .str();
571 }
572
573 if (hasAttribute(Attribute::VScaleRange)) {
574 unsigned MinValue = getVScaleRangeMin();
575 std::optional<unsigned> MaxValue = getVScaleRangeMax();
576 return ("vscale_range(" + Twine(MinValue) + "," +
577 Twine(MaxValue.value_or(0)) + ")")
578 .str();
579 }
580
581 if (hasAttribute(Attribute::UWTable)) {
583 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
584 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
585 }
586
587 if (hasAttribute(Attribute::AllocKind)) {
588 AllocFnKind Kind = getAllocKind();
591 parts.push_back("alloc");
593 parts.push_back("realloc");
595 parts.push_back("free");
597 parts.push_back("uninitialized");
599 parts.push_back("zeroed");
601 parts.push_back("aligned");
602 return ("allockind(\"" +
603 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
604 .str();
605 }
606
607 if (hasAttribute(Attribute::Memory)) {
608 std::string Result;
609 raw_string_ostream OS(Result);
610 bool First = true;
611 OS << "memory(";
612
614
615 // Print access kind for "other" as the default access kind. This way it
616 // will apply to any new location kinds that get split out of "other".
618 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
619 First = false;
620 OS << getModRefStr(OtherMR);
621 }
622
623 for (auto Loc : MemoryEffects::locations()) {
624 ModRefInfo MR = ME.getModRef(Loc);
625 if (MR == OtherMR)
626 continue;
627
628 if (!First)
629 OS << ", ";
630 First = false;
631
632 switch (Loc) {
634 OS << "argmem: ";
635 break;
637 OS << "inaccessiblemem: ";
638 break;
640 llvm_unreachable("This is represented as the default access kind");
641 }
642 OS << getModRefStr(MR);
643 }
644 OS << ")";
645 OS.flush();
646 return Result;
647 }
648
649 if (hasAttribute(Attribute::NoFPClass)) {
650 std::string Result = "nofpclass";
651 raw_string_ostream OS(Result);
652 OS << getNoFPClass();
653 return Result;
654 }
655
656 if (hasAttribute(Attribute::Range)) {
657 std::string Result;
658 raw_string_ostream OS(Result);
660 OS << "range(";
661 OS << "i" << CR.getBitWidth() << " ";
662 OS << CR.getLower() << ", " << CR.getUpper();
663 OS << ")";
664 OS.flush();
665 return Result;
666 }
667
668 if (hasAttribute(Attribute::Initializes)) {
669 std::string Result;
670 raw_string_ostream OS(Result);
672 OS << "initializes(";
673 CRL.print(OS);
674 OS << ")";
675 OS.flush();
676 return Result;
677 }
678
679 // Convert target-dependent attributes to strings of the form:
680 //
681 // "kind"
682 // "kind" = "value"
683 //
684 if (isStringAttribute()) {
685 std::string Result;
686 {
687 raw_string_ostream OS(Result);
688 OS << '"' << getKindAsString() << '"';
689
690 // Since some attribute strings contain special characters that cannot be
691 // printable, those have to be escaped to make the attribute value
692 // printable as is. e.g. "\01__gnu_mcount_nc"
693 const auto &AttrVal = pImpl->getValueAsString();
694 if (!AttrVal.empty()) {
695 OS << "=\"";
696 printEscapedString(AttrVal, OS);
697 OS << "\"";
698 }
699 }
700 return Result;
701 }
702
703 llvm_unreachable("Unknown attribute");
704}
705
707 assert(isValid() && "invalid Attribute doesn't refer to any context");
709 pImpl->Profile(ID);
710 void *Unused;
711 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
712}
713
715 if (!pImpl && !A.pImpl) return false;
716 if (!pImpl) return true;
717 if (!A.pImpl) return false;
718 return *pImpl < *A.pImpl;
719}
720
722 ID.AddPointer(pImpl);
723}
724
726 FnAttr = (1 << 0),
727 ParamAttr = (1 << 1),
728 RetAttr = (1 << 2),
729};
730
731#define GET_ATTR_PROP_TABLE
732#include "llvm/IR/Attributes.inc"
733
735 AttributeProperty Prop) {
736 unsigned Index = Kind - 1;
737 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
738 return AttrPropTable[Index] & Prop;
739}
740
742 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
743}
744
746 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
747}
748
750 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
751}
752
753//===----------------------------------------------------------------------===//
754// AttributeImpl Definition
755//===----------------------------------------------------------------------===//
756
758 if (isStringAttribute()) return false;
759 return getKindAsEnum() == A;
760}
761
763 if (!isStringAttribute()) return false;
764 return getKindAsString() == Kind;
765}
766
770 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
771}
772
775 return static_cast<const IntAttributeImpl *>(this)->getValue();
776}
777
779 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
780 return getValueAsString() == "true";
781}
782
785 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
786}
787
790 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
791}
792
795 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
796}
797
800 return static_cast<const ConstantRangeAttributeImpl *>(this)
801 ->getConstantRangeValue();
802}
803
806 return static_cast<const ConstantRangeListAttributeImpl *>(this)
807 ->getConstantRangeListValue();
808}
809
811 if (this == &AI)
812 return false;
813
814 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
815 // relative to their enum value) and then strings.
816 if (!isStringAttribute()) {
817 if (AI.isStringAttribute())
818 return true;
819 if (getKindAsEnum() != AI.getKindAsEnum())
820 return getKindAsEnum() < AI.getKindAsEnum();
821 assert(!AI.isEnumAttribute() && "Non-unique attribute");
822 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
823 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
825 "Unclear how to compare range list");
826 // TODO: Is this actually needed?
827 assert(AI.isIntAttribute() && "Only possibility left");
828 return getValueAsInt() < AI.getValueAsInt();
829 }
830
831 if (!AI.isStringAttribute())
832 return false;
833 if (getKindAsString() == AI.getKindAsString())
834 return getValueAsString() < AI.getValueAsString();
835 return getKindAsString() < AI.getKindAsString();
836}
837
838//===----------------------------------------------------------------------===//
839// AttributeSet Definition
840//===----------------------------------------------------------------------===//
841
844}
845
847 return AttributeSet(AttributeSetNode::get(C, Attrs));
848}
849
851 Attribute::AttrKind Kind) const {
852 if (hasAttribute(Kind)) return *this;
853 AttrBuilder B(C);
854 B.addAttribute(Kind);
856}
857
859 StringRef Value) const {
860 AttrBuilder B(C);
861 B.addAttribute(Kind, Value);
863}
864
866 const AttributeSet AS) const {
867 if (!hasAttributes())
868 return AS;
869
870 if (!AS.hasAttributes())
871 return *this;
872
873 AttrBuilder B(C, *this);
874 B.merge(AttrBuilder(C, AS));
875 return get(C, B);
876}
877
879 Attribute::AttrKind Kind) const {
880 if (!hasAttribute(Kind)) return *this;
881 AttrBuilder B(C, *this);
882 B.removeAttribute(Kind);
883 return get(C, B);
884}
885
887 StringRef Kind) const {
888 if (!hasAttribute(Kind)) return *this;
889 AttrBuilder B(C, *this);
890 B.removeAttribute(Kind);
891 return get(C, B);
892}
893
895 const AttributeMask &Attrs) const {
896 AttrBuilder B(C, *this);
897 // If there is nothing to remove, directly return the original set.
898 if (!B.overlaps(Attrs))
899 return *this;
900
901 B.remove(Attrs);
902 return get(C, B);
903}
904
906 return SetNode ? SetNode->getNumAttributes() : 0;
907}
908
910 return SetNode ? SetNode->hasAttribute(Kind) : false;
911}
912
914 return SetNode ? SetNode->hasAttribute(Kind) : false;
915}
916
918 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
919}
920
922 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
923}
924
926 return SetNode ? SetNode->getAlignment() : std::nullopt;
927}
928
930 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
931}
932
934 return SetNode ? SetNode->getDereferenceableBytes() : 0;
935}
936
938 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
939}
940
942 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
943}
944
946 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
947}
948
950 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
951}
952
954 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
955}
956
958 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
959}
960
962 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
963}
964
965std::optional<std::pair<unsigned, std::optional<unsigned>>>
967 if (SetNode)
968 return SetNode->getAllocSizeArgs();
969 return std::nullopt;
970}
971
973 return SetNode ? SetNode->getVScaleRangeMin() : 1;
974}
975
976std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
977 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
978}
979
981 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
982}
983
985 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
986}
987
989 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
990}
991
993 return SetNode ? SetNode->getNoFPClass() : fcNone;
994}
995
996std::string AttributeSet::getAsString(bool InAttrGrp) const {
997 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
998}
999
1001 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1003 SetNode->Profile(ID);
1004 void *Unused;
1005 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1006}
1007
1009 return SetNode ? SetNode->begin() : nullptr;
1010}
1011
1013 return SetNode ? SetNode->end() : nullptr;
1014}
1015
1016#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1018 dbgs() << "AS =\n";
1019 dbgs() << " { ";
1020 dbgs() << getAsString(true) << " }\n";
1021}
1022#endif
1023
1024//===----------------------------------------------------------------------===//
1025// AttributeSetNode Definition
1026//===----------------------------------------------------------------------===//
1027
1028AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1029 : NumAttrs(Attrs.size()) {
1030 // There's memory after the node where we can store the entries in.
1031 llvm::copy(Attrs, getTrailingObjects<Attribute>());
1032
1033 for (const auto &I : *this) {
1034 if (I.isStringAttribute())
1035 StringAttrs.insert({ I.getKindAsString(), I });
1036 else
1037 AvailableAttrs.addAttribute(I.getKindAsEnum());
1038 }
1039}
1040
1042 ArrayRef<Attribute> Attrs) {
1043 SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
1044 llvm::sort(SortedAttrs);
1045 return getSorted(C, SortedAttrs);
1046}
1047
1048AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1049 ArrayRef<Attribute> SortedAttrs) {
1050 if (SortedAttrs.empty())
1051 return nullptr;
1052
1053 // Build a key to look up the existing attributes.
1054 LLVMContextImpl *pImpl = C.pImpl;
1056
1057 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1058 for (const auto &Attr : SortedAttrs)
1059 Attr.Profile(ID);
1060
1061 void *InsertPoint;
1062 AttributeSetNode *PA =
1063 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1064
1065 // If we didn't find any existing attributes of the same shape then create a
1066 // new one and insert it.
1067 if (!PA) {
1068 // Coallocate entries after the AttributeSetNode itself.
1069 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1070 PA = new (Mem) AttributeSetNode(SortedAttrs);
1071 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1072 }
1073
1074 // Return the AttributeSetNode that we found or created.
1075 return PA;
1076}
1077
1079 return getSorted(C, B.attrs());
1080}
1081
1083 return StringAttrs.count(Kind);
1084}
1085
1086std::optional<Attribute>
1087AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1088 // Do a quick presence check.
1089 if (!hasAttribute(Kind))
1090 return std::nullopt;
1091
1092 // Attributes in a set are sorted by enum value, followed by string
1093 // attributes. Binary search the one we want.
1094 const Attribute *I =
1095 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1096 [](Attribute A, Attribute::AttrKind Kind) {
1097 return A.getKindAsEnum() < Kind;
1098 });
1099 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1100 return *I;
1101}
1102
1104 if (auto A = findEnumAttribute(Kind))
1105 return *A;
1106 return {};
1107}
1108
1110 return StringAttrs.lookup(Kind);
1111}
1112
1114 if (auto A = findEnumAttribute(Attribute::Alignment))
1115 return A->getAlignment();
1116 return std::nullopt;
1117}
1118
1120 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1121 return A->getStackAlignment();
1122 return std::nullopt;
1123}
1124
1126 if (auto A = findEnumAttribute(Kind))
1127 return A->getValueAsType();
1128 return nullptr;
1129}
1130
1132 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1133 return A->getDereferenceableBytes();
1134 return 0;
1135}
1136
1138 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1139 return A->getDereferenceableOrNullBytes();
1140 return 0;
1141}
1142
1143std::optional<std::pair<unsigned, std::optional<unsigned>>>
1145 if (auto A = findEnumAttribute(Attribute::AllocSize))
1146 return A->getAllocSizeArgs();
1147 return std::nullopt;
1148}
1149
1151 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1152 return A->getVScaleRangeMin();
1153 return 1;
1154}
1155
1156std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1157 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1158 return A->getVScaleRangeMax();
1159 return std::nullopt;
1160}
1161
1163 if (auto A = findEnumAttribute(Attribute::UWTable))
1164 return A->getUWTableKind();
1165 return UWTableKind::None;
1166}
1167
1169 if (auto A = findEnumAttribute(Attribute::AllocKind))
1170 return A->getAllocKind();
1171 return AllocFnKind::Unknown;
1172}
1173
1175 if (auto A = findEnumAttribute(Attribute::Memory))
1176 return A->getMemoryEffects();
1177 return MemoryEffects::unknown();
1178}
1179
1181 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1182 return A->getNoFPClass();
1183 return fcNone;
1184}
1185
1186std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1187 std::string Str;
1188 for (iterator I = begin(), E = end(); I != E; ++I) {
1189 if (I != begin())
1190 Str += ' ';
1191 Str += I->getAsString(InAttrGrp);
1192 }
1193 return Str;
1194}
1195
1196//===----------------------------------------------------------------------===//
1197// AttributeListImpl Definition
1198//===----------------------------------------------------------------------===//
1199
1200/// Map from AttributeList index to the internal array index. Adding one happens
1201/// to work, because -1 wraps around to 0.
1202static unsigned attrIdxToArrayIdx(unsigned Index) {
1203 return Index + 1;
1204}
1205
1207 : NumAttrSets(Sets.size()) {
1208 assert(!Sets.empty() && "pointless AttributeListImpl");
1209
1210 // There's memory after the node where we can store the entries in.
1211 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1212
1213 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1214 // summary bitsets.
1215 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1216 if (!I.isStringAttribute())
1217 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1218
1219 for (const auto &Set : Sets)
1220 for (const auto &I : Set)
1221 if (!I.isStringAttribute())
1222 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1223}
1224
1226 Profile(ID, ArrayRef(begin(), end()));
1227}
1228
1231 for (const auto &Set : Sets)
1232 ID.AddPointer(Set.SetNode);
1233}
1234
1236 unsigned *Index) const {
1237 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1238 return false;
1239
1240 if (Index) {
1241 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1242 if (begin()[I].hasAttribute(Kind)) {
1243 *Index = I - 1;
1244 break;
1245 }
1246 }
1247 }
1248
1249 return true;
1250}
1251
1252
1253#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1255 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1256}
1257#endif
1258
1259//===----------------------------------------------------------------------===//
1260// AttributeList Construction and Mutation Methods
1261//===----------------------------------------------------------------------===//
1262
1263AttributeList AttributeList::getImpl(LLVMContext &C,
1264 ArrayRef<AttributeSet> AttrSets) {
1265 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1266
1267 LLVMContextImpl *pImpl = C.pImpl;
1269 AttributeListImpl::Profile(ID, AttrSets);
1270
1271 void *InsertPoint;
1272 AttributeListImpl *PA =
1273 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1274
1275 // If we didn't find any existing attributes of the same shape then
1276 // create a new one and insert it.
1277 if (!PA) {
1278 // Coallocate entries after the AttributeListImpl itself.
1279 void *Mem = pImpl->Alloc.Allocate(
1280 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1281 alignof(AttributeListImpl));
1282 PA = new (Mem) AttributeListImpl(AttrSets);
1283 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1284 }
1285
1286 // Return the AttributesList that we found or created.
1287 return AttributeList(PA);
1288}
1289
1292 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1293 // If there are no attributes then return a null AttributesList pointer.
1294 if (Attrs.empty())
1295 return {};
1296
1298 "Misordered Attributes list!");
1299 assert(llvm::all_of(Attrs,
1300 [](const std::pair<unsigned, Attribute> &Pair) {
1301 return Pair.second.isValid();
1302 }) &&
1303 "Pointless attribute!");
1304
1305 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1306 // list.
1308 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1309 E = Attrs.end(); I != E; ) {
1310 unsigned Index = I->first;
1312 while (I != E && I->first == Index) {
1313 AttrVec.push_back(I->second);
1314 ++I;
1315 }
1316
1317 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1318 }
1319
1320 return get(C, AttrPairVec);
1321}
1322
1325 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1326 // If there are no attributes then return a null AttributesList pointer.
1327 if (Attrs.empty())
1328 return {};
1329
1331 "Misordered Attributes list!");
1332 assert(llvm::none_of(Attrs,
1333 [](const std::pair<unsigned, AttributeSet> &Pair) {
1334 return !Pair.second.hasAttributes();
1335 }) &&
1336 "Pointless attribute!");
1337
1338 unsigned MaxIndex = Attrs.back().first;
1339 // If the MaxIndex is FunctionIndex and there are other indices in front
1340 // of it, we need to use the largest of those to get the right size.
1341 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1342 MaxIndex = Attrs[Attrs.size() - 2].first;
1343
1344 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1345 for (const auto &Pair : Attrs)
1346 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1347
1348 return getImpl(C, AttrVec);
1349}
1350
1352 AttributeSet RetAttrs,
1353 ArrayRef<AttributeSet> ArgAttrs) {
1354 // Scan from the end to find the last argument with attributes. Most
1355 // arguments don't have attributes, so it's nice if we can have fewer unique
1356 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1357 unsigned NumSets = 0;
1358 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1359 if (ArgAttrs[I - 1].hasAttributes()) {
1360 NumSets = I + 2;
1361 break;
1362 }
1363 }
1364 if (NumSets == 0) {
1365 // Check function and return attributes if we didn't have argument
1366 // attributes.
1367 if (RetAttrs.hasAttributes())
1368 NumSets = 2;
1369 else if (FnAttrs.hasAttributes())
1370 NumSets = 1;
1371 }
1372
1373 // If all attribute sets were empty, we can use the empty attribute list.
1374 if (NumSets == 0)
1375 return {};
1376
1378 AttrSets.reserve(NumSets);
1379 // If we have any attributes, we always have function attributes.
1380 AttrSets.push_back(FnAttrs);
1381 if (NumSets > 1)
1382 AttrSets.push_back(RetAttrs);
1383 if (NumSets > 2) {
1384 // Drop the empty argument attribute sets at the end.
1385 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1386 llvm::append_range(AttrSets, ArgAttrs);
1387 }
1388
1389 return getImpl(C, AttrSets);
1390}
1391
1393 AttributeSet Attrs) {
1394 if (!Attrs.hasAttributes())
1395 return {};
1397 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1398 AttrSets[Index] = Attrs;
1399 return getImpl(C, AttrSets);
1400}
1401
1403 const AttrBuilder &B) {
1404 return get(C, Index, AttributeSet::get(C, B));
1405}
1406
1410 for (const auto K : Kinds)
1411 Attrs.emplace_back(Index, Attribute::get(C, K));
1412 return get(C, Attrs);
1413}
1414
1417 ArrayRef<uint64_t> Values) {
1418 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1420 auto VI = Values.begin();
1421 for (const auto K : Kinds)
1422 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1423 return get(C, Attrs);
1424}
1425
1427 ArrayRef<StringRef> Kinds) {
1429 for (const auto &K : Kinds)
1430 Attrs.emplace_back(Index, Attribute::get(C, K));
1431 return get(C, Attrs);
1432}
1433
1436 if (Attrs.empty())
1437 return {};
1438 if (Attrs.size() == 1)
1439 return Attrs[0];
1440
1441 unsigned MaxSize = 0;
1442 for (const auto &List : Attrs)
1443 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1444
1445 // If every list was empty, there is no point in merging the lists.
1446 if (MaxSize == 0)
1447 return {};
1448
1449 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1450 for (unsigned I = 0; I < MaxSize; ++I) {
1451 AttrBuilder CurBuilder(C);
1452 for (const auto &List : Attrs)
1453 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1454 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1455 }
1456
1457 return getImpl(C, NewAttrSets);
1458}
1459
1462 Attribute::AttrKind Kind) const {
1464 if (Attrs.hasAttribute(Kind))
1465 return *this;
1466 // TODO: Insert at correct position and avoid sort.
1467 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1468 NewAttrs.push_back(Attribute::get(C, Kind));
1469 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1470}
1471
1473 StringRef Kind,
1474 StringRef Value) const {
1475 AttrBuilder B(C);
1476 B.addAttribute(Kind, Value);
1477 return addAttributesAtIndex(C, Index, B);
1478}
1479
1481 Attribute A) const {
1482 AttrBuilder B(C);
1483 B.addAttribute(A);
1484 return addAttributesAtIndex(C, Index, B);
1485}
1486
1487AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1488 unsigned Index,
1489 AttributeSet Attrs) const {
1491 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1492 if (Index >= AttrSets.size())
1493 AttrSets.resize(Index + 1);
1494 AttrSets[Index] = Attrs;
1495
1496 // Remove trailing empty attribute sets.
1497 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1498 AttrSets.pop_back();
1499 if (AttrSets.empty())
1500 return {};
1501 return AttributeList::getImpl(C, AttrSets);
1502}
1503
1505 unsigned Index,
1506 const AttrBuilder &B) const {
1507 if (!B.hasAttributes())
1508 return *this;
1509
1510 if (!pImpl)
1512
1513 AttrBuilder Merged(C, getAttributes(Index));
1514 Merged.merge(B);
1515 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1516}
1517
1519 ArrayRef<unsigned> ArgNos,
1520 Attribute A) const {
1521 assert(llvm::is_sorted(ArgNos));
1522
1523 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1524 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1525 if (MaxIndex >= AttrSets.size())
1526 AttrSets.resize(MaxIndex + 1);
1527
1528 for (unsigned ArgNo : ArgNos) {
1529 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1530 AttrBuilder B(C, AttrSets[Index]);
1531 B.addAttribute(A);
1532 AttrSets[Index] = AttributeSet::get(C, B);
1533 }
1534
1535 return getImpl(C, AttrSets);
1536}
1537
1540 Attribute::AttrKind Kind) const {
1542 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1543 if (Attrs == NewAttrs)
1544 return *this;
1545 return setAttributesAtIndex(C, Index, NewAttrs);
1546}
1547
1549 unsigned Index,
1550 StringRef Kind) const {
1552 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1553 if (Attrs == NewAttrs)
1554 return *this;
1555 return setAttributesAtIndex(C, Index, NewAttrs);
1556}
1557
1559 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1561 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1562 // If nothing was removed, return the original list.
1563 if (Attrs == NewAttrs)
1564 return *this;
1565 return setAttributesAtIndex(C, Index, NewAttrs);
1566}
1567
1570 unsigned WithoutIndex) const {
1571 if (!pImpl)
1572 return {};
1573 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1574 return *this;
1575 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1576}
1577
1579 uint64_t Bytes) const {
1580 AttrBuilder B(C);
1581 B.addDereferenceableAttr(Bytes);
1582 return addRetAttributes(C, B);
1583}
1584
1586 unsigned Index,
1587 uint64_t Bytes) const {
1588 AttrBuilder B(C);
1589 B.addDereferenceableAttr(Bytes);
1590 return addParamAttributes(C, Index, B);
1591}
1592
1595 uint64_t Bytes) const {
1596 AttrBuilder B(C);
1597 B.addDereferenceableOrNullAttr(Bytes);
1598 return addParamAttributes(C, Index, B);
1599}
1600
1602 const ConstantRange &CR) const {
1603 AttrBuilder B(C);
1604 B.addRangeAttr(CR);
1605 return addRetAttributes(C, B);
1606}
1607
1609 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1610 const std::optional<unsigned> &NumElemsArg) {
1611 AttrBuilder B(C);
1612 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1613 return addParamAttributes(C, Index, B);
1614}
1615
1616//===----------------------------------------------------------------------===//
1617// AttributeList Accessor Methods
1618//===----------------------------------------------------------------------===//
1619
1621 return getAttributes(ArgNo + FirstArgIndex);
1622}
1623
1625 return getAttributes(ReturnIndex);
1626}
1627
1630}
1631
1633 Attribute::AttrKind Kind) const {
1634 return getAttributes(Index).hasAttribute(Kind);
1635}
1636
1638 return getAttributes(Index).hasAttribute(Kind);
1639}
1640
1643}
1644
1646 return pImpl && pImpl->hasFnAttribute(Kind);
1647}
1648
1651}
1652
1654 unsigned *Index) const {
1655 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1656}
1657
1659 Attribute::AttrKind Kind) const {
1660 return getAttributes(Index).getAttribute(Kind);
1661}
1662
1664 StringRef Kind) const {
1665 return getAttributes(Index).getAttribute(Kind);
1666}
1667
1670}
1671
1673 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1674}
1675
1678}
1679
1682}
1683
1686}
1687
1690}
1691
1694}
1695
1698}
1699
1702}
1703
1705 return getFnAttrs().getStackAlignment();
1706}
1707
1709 return getRetAttrs().getStackAlignment();
1710}
1711
1714}
1715
1718}
1719
1722}
1723
1727}
1728
1730 return getRetAttrs().getNoFPClass();
1731}
1732
1735}
1736
1738 return getFnAttrs().getUWTableKind();
1739}
1740
1742 return getFnAttrs().getAllocKind();
1743}
1744
1746 return getFnAttrs().getMemoryEffects();
1747}
1748
1749std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1750 return getAttributes(Index).getAsString(InAttrGrp);
1751}
1752
1755 if (!pImpl || Index >= getNumAttrSets())
1756 return {};
1757 return pImpl->begin()[Index];
1758}
1759
1761 assert(!isEmpty() && "an empty attribute list has no parent context");
1763 pImpl->Profile(ID);
1764 void *Unused;
1765 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1766}
1767
1769 return pImpl ? pImpl->begin() : nullptr;
1770}
1771
1773 return pImpl ? pImpl->end() : nullptr;
1774}
1775
1776//===----------------------------------------------------------------------===//
1777// AttributeList Introspection Methods
1778//===----------------------------------------------------------------------===//
1779
1781 return pImpl ? pImpl->NumAttrSets : 0;
1782}
1783
1785 O << "AttributeList[\n";
1786
1787 for (unsigned i : indexes()) {
1788 if (!getAttributes(i).hasAttributes())
1789 continue;
1790 O << " { ";
1791 switch (i) {
1793 O << "return";
1794 break;
1796 O << "function";
1797 break;
1798 default:
1799 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1800 }
1801 O << " => " << getAsString(i) << " }\n";
1802 }
1803
1804 O << "]\n";
1805}
1806
1807#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1809#endif
1810
1811//===----------------------------------------------------------------------===//
1812// AttrBuilder Method Implementations
1813//===----------------------------------------------------------------------===//
1814
1816 append_range(Attrs, AS);
1817 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
1818}
1819
1820void AttrBuilder::clear() { Attrs.clear(); }
1821
1822/// Attribute comparator that only compares attribute keys. Enum attributes are
1823/// sorted before string attributes.
1825 bool operator()(Attribute A0, Attribute A1) const {
1826 bool A0IsString = A0.isStringAttribute();
1827 bool A1IsString = A1.isStringAttribute();
1828 if (A0IsString) {
1829 if (A1IsString)
1830 return A0.getKindAsString() < A1.getKindAsString();
1831 else
1832 return false;
1833 }
1834 if (A1IsString)
1835 return true;
1836 return A0.getKindAsEnum() < A1.getKindAsEnum();
1837 }
1839 if (A0.isStringAttribute())
1840 return false;
1841 return A0.getKindAsEnum() < Kind;
1842 }
1843 bool operator()(Attribute A0, StringRef Kind) const {
1844 if (A0.isStringAttribute())
1845 return A0.getKindAsString() < Kind;
1846 return true;
1847 }
1848};
1849
1850template <typename K>
1852 Attribute Attr) {
1853 auto It = lower_bound(Attrs, Kind, AttributeComparator());
1854 if (It != Attrs.end() && It->hasAttribute(Kind))
1855 std::swap(*It, Attr);
1856 else
1857 Attrs.insert(It, Attr);
1858}
1859
1861 if (Attr.isStringAttribute())
1862 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1863 else
1864 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
1865 return *this;
1866}
1867
1869 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
1870 return *this;
1871}
1872
1874 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
1875 return *this;
1876}
1877
1879 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1880 auto It = lower_bound(Attrs, Val, AttributeComparator());
1881 if (It != Attrs.end() && It->hasAttribute(Val))
1882 Attrs.erase(It);
1883 return *this;
1884}
1885
1887 auto It = lower_bound(Attrs, A, AttributeComparator());
1888 if (It != Attrs.end() && It->hasAttribute(A))
1889 Attrs.erase(It);
1890 return *this;
1891}
1892
1893std::optional<uint64_t>
1895 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
1896 Attribute A = getAttribute(Kind);
1897 if (A.isValid())
1898 return A.getValueAsInt();
1899 return std::nullopt;
1900}
1901
1903 uint64_t Value) {
1904 return addAttribute(Attribute::get(Ctx, Kind, Value));
1905}
1906
1907std::optional<std::pair<unsigned, std::optional<unsigned>>>
1909 Attribute A = getAttribute(Attribute::AllocSize);
1910 if (A.isValid())
1911 return A.getAllocSizeArgs();
1912 return std::nullopt;
1913}
1914
1916 if (!Align)
1917 return *this;
1918
1919 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1920 return addRawIntAttr(Attribute::Alignment, Align->value());
1921}
1922
1924 // Default alignment, allow the target to define how to align it.
1925 if (!Align)
1926 return *this;
1927
1928 assert(*Align <= 0x100 && "Alignment too large.");
1929 return addRawIntAttr(Attribute::StackAlignment, Align->value());
1930}
1931
1933 if (Bytes == 0) return *this;
1934
1935 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
1936}
1937
1939 if (Bytes == 0)
1940 return *this;
1941
1942 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
1943}
1944
1947 const std::optional<unsigned> &NumElems) {
1948 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1949}
1950
1952 // (0, 0) is our "not present" value, so we need to check for it here.
1953 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1954 return addRawIntAttr(Attribute::AllocSize, RawArgs);
1955}
1956
1958 std::optional<unsigned> MaxValue) {
1959 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
1960}
1961
1963 // (0, 0) is not present hence ignore this case
1964 if (RawArgs == 0)
1965 return *this;
1966
1967 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1968}
1969
1971 if (Kind == UWTableKind::None)
1972 return *this;
1973 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
1974}
1975
1977 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
1978}
1979
1981 if (Mask == fcNone)
1982 return *this;
1983
1984 return addRawIntAttr(Attribute::NoFPClass, Mask);
1985}
1986
1988 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
1989}
1990
1992 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
1993 Attribute A = getAttribute(Kind);
1994 return A.isValid() ? A.getValueAsType() : nullptr;
1995}
1996
1998 return addAttribute(Attribute::get(Ctx, Kind, Ty));
1999}
2000
2002 return addTypeAttr(Attribute::ByVal, Ty);
2003}
2004
2006 return addTypeAttr(Attribute::StructRet, Ty);
2007}
2008
2010 return addTypeAttr(Attribute::ByRef, Ty);
2011}
2012
2014 return addTypeAttr(Attribute::Preallocated, Ty);
2015}
2016
2018 return addTypeAttr(Attribute::InAlloca, Ty);
2019}
2020
2022 const ConstantRange &CR) {
2023 return addAttribute(Attribute::get(Ctx, Kind, CR));
2024}
2025
2027 return addConstantRangeAttr(Attribute::Range, CR);
2028}
2029
2033 return addAttribute(Attribute::get(Ctx, Kind, Val));
2034}
2035
2037 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2038}
2039
2041 // TODO: Could make this O(n) as we're merging two sorted lists.
2042 for (const auto &I : B.attrs())
2043 addAttribute(I);
2044
2045 return *this;
2046}
2047
2049 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2050 return *this;
2051}
2052
2054 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2055}
2056
2058 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2059 auto It = lower_bound(Attrs, A, AttributeComparator());
2060 if (It != Attrs.end() && It->hasAttribute(A))
2061 return *It;
2062 return {};
2063}
2064
2066 auto It = lower_bound(Attrs, A, AttributeComparator());
2067 if (It != Attrs.end() && It->hasAttribute(A))
2068 return *It;
2069 return {};
2070}
2071
2073 return getAttribute(A).isValid();
2074}
2075
2077 return getAttribute(A).isValid();
2078}
2079
2081 return Attrs == B.Attrs;
2082}
2083
2084//===----------------------------------------------------------------------===//
2085// AttributeFuncs Function Defintions
2086//===----------------------------------------------------------------------===//
2087
2088/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2089/// follows the same type rules as FPMathOperator.
2090///
2091/// TODO: Consider relaxing to any FP type struct fields.
2093 while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
2094 Ty = ArrTy->getElementType();
2095 return Ty->isFPOrFPVectorTy();
2096}
2097
2098/// Which attributes cannot be applied to a type.
2100 AttributeSafetyKind ASK) {
2101 AttributeMask Incompatible;
2102
2103 if (!Ty->isIntegerTy()) {
2104 // Attributes that only apply to integers.
2105 if (ASK & ASK_SAFE_TO_DROP)
2106 Incompatible.addAttribute(Attribute::AllocAlign);
2107 if (ASK & ASK_UNSAFE_TO_DROP)
2108 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2109 }
2110
2111 if (!Ty->isIntOrIntVectorTy()) {
2112 // Attributes that only apply to integers or vector of integers.
2113 if (ASK & ASK_SAFE_TO_DROP)
2114 Incompatible.addAttribute(Attribute::Range);
2115 }
2116
2117 if (!Ty->isPointerTy()) {
2118 // Attributes that only apply to pointers.
2119 if (ASK & ASK_SAFE_TO_DROP)
2120 Incompatible.addAttribute(Attribute::NoAlias)
2121 .addAttribute(Attribute::NoCapture)
2122 .addAttribute(Attribute::NonNull)
2123 .addAttribute(Attribute::ReadNone)
2124 .addAttribute(Attribute::ReadOnly)
2125 .addAttribute(Attribute::Dereferenceable)
2126 .addAttribute(Attribute::DereferenceableOrNull)
2127 .addAttribute(Attribute::Writable)
2128 .addAttribute(Attribute::DeadOnUnwind)
2129 .addAttribute(Attribute::Initializes);
2130 if (ASK & ASK_UNSAFE_TO_DROP)
2131 Incompatible.addAttribute(Attribute::Nest)
2132 .addAttribute(Attribute::SwiftError)
2133 .addAttribute(Attribute::Preallocated)
2134 .addAttribute(Attribute::InAlloca)
2135 .addAttribute(Attribute::ByVal)
2136 .addAttribute(Attribute::StructRet)
2137 .addAttribute(Attribute::ByRef)
2138 .addAttribute(Attribute::ElementType)
2139 .addAttribute(Attribute::AllocatedPointer);
2140 }
2141
2142 // Attributes that only apply to pointers or vectors of pointers.
2143 if (!Ty->isPtrOrPtrVectorTy()) {
2144 if (ASK & ASK_SAFE_TO_DROP)
2145 Incompatible.addAttribute(Attribute::Alignment);
2146 }
2147
2148 if (ASK & ASK_SAFE_TO_DROP) {
2150 Incompatible.addAttribute(Attribute::NoFPClass);
2151 }
2152
2153 // Some attributes can apply to all "values" but there are no `void` values.
2154 if (Ty->isVoidTy()) {
2155 if (ASK & ASK_SAFE_TO_DROP)
2156 Incompatible.addAttribute(Attribute::NoUndef);
2157 }
2158
2159 return Incompatible;
2160}
2161
2163 AttributeMask AM;
2164 AM.addAttribute(Attribute::NoUndef);
2165 AM.addAttribute(Attribute::Dereferenceable);
2166 AM.addAttribute(Attribute::DereferenceableOrNull);
2167 return AM;
2168}
2169
2170/// Callees with dynamic denormal modes are compatible with any caller mode.
2171static bool denormModeCompatible(DenormalMode CallerMode,
2172 DenormalMode CalleeMode) {
2173 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2174 return true;
2175
2176 // If they don't exactly match, it's OK if the mismatched component is
2177 // dynamic.
2178 if (CalleeMode.Input == CallerMode.Input &&
2179 CalleeMode.Output == DenormalMode::Dynamic)
2180 return true;
2181
2182 if (CalleeMode.Output == CallerMode.Output &&
2183 CalleeMode.Input == DenormalMode::Dynamic)
2184 return true;
2185 return false;
2186}
2187
2188static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2189 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2190 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2191
2192 if (denormModeCompatible(CallerMode, CalleeMode)) {
2193 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2194 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2195 if (CallerModeF32 == DenormalMode::getInvalid())
2196 CallerModeF32 = CallerMode;
2197 if (CalleeModeF32 == DenormalMode::getInvalid())
2198 CalleeModeF32 = CalleeMode;
2199 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2200 }
2201
2202 return false;
2203}
2204
2205static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2206 // Do not inline strictfp function into non-strictfp one. It would require
2207 // conversion of all FP operations in host function to constrained intrinsics.
2208 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2209 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2210}
2211
2212template<typename AttrClass>
2213static bool isEqual(const Function &Caller, const Function &Callee) {
2214 return Caller.getFnAttribute(AttrClass::getKind()) ==
2215 Callee.getFnAttribute(AttrClass::getKind());
2216}
2217
2218static bool isEqual(const Function &Caller, const Function &Callee,
2219 const StringRef &AttrName) {
2220 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2221}
2222
2223/// Compute the logical AND of the attributes of the caller and the
2224/// callee.
2225///
2226/// This function sets the caller's attribute to false if the callee's attribute
2227/// is false.
2228template<typename AttrClass>
2229static void setAND(Function &Caller, const Function &Callee) {
2230 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2231 !AttrClass::isSet(Callee, AttrClass::getKind()))
2232 AttrClass::set(Caller, AttrClass::getKind(), false);
2233}
2234
2235/// Compute the logical OR of the attributes of the caller and the
2236/// callee.
2237///
2238/// This function sets the caller's attribute to true if the callee's attribute
2239/// is true.
2240template<typename AttrClass>
2241static void setOR(Function &Caller, const Function &Callee) {
2242 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2243 AttrClass::isSet(Callee, AttrClass::getKind()))
2244 AttrClass::set(Caller, AttrClass::getKind(), true);
2245}
2246
2247/// If the inlined function had a higher stack protection level than the
2248/// calling function, then bump up the caller's stack protection level.
2249static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2250 // If the calling function has *no* stack protection level (e.g. it was built
2251 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2252 // change it as that could change the program's semantics.
2253 if (!Caller.hasStackProtectorFnAttr())
2254 return;
2255
2256 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2257 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2258 // clutter to the IR.
2259 AttributeMask OldSSPAttr;
2260 OldSSPAttr.addAttribute(Attribute::StackProtect)
2261 .addAttribute(Attribute::StackProtectStrong)
2262 .addAttribute(Attribute::StackProtectReq);
2263
2264 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2265 Caller.removeFnAttrs(OldSSPAttr);
2266 Caller.addFnAttr(Attribute::StackProtectReq);
2267 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2268 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2269 Caller.removeFnAttrs(OldSSPAttr);
2270 Caller.addFnAttr(Attribute::StackProtectStrong);
2271 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2272 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2273 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2274 Caller.addFnAttr(Attribute::StackProtect);
2275}
2276
2277/// If the inlined function required stack probes, then ensure that
2278/// the calling function has those too.
2279static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2280 if (!Caller.hasFnAttribute("probe-stack") &&
2281 Callee.hasFnAttribute("probe-stack")) {
2282 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2283 }
2284}
2285
2286/// If the inlined function defines the size of guard region
2287/// on the stack, then ensure that the calling function defines a guard region
2288/// that is no larger.
2289static void
2291 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2292 if (CalleeAttr.isValid()) {
2293 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2294 if (CallerAttr.isValid()) {
2295 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2296 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2297 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2298
2299 if (CallerStackProbeSize > CalleeStackProbeSize) {
2300 Caller.addFnAttr(CalleeAttr);
2301 }
2302 } else {
2303 Caller.addFnAttr(CalleeAttr);
2304 }
2305 }
2306}
2307
2308/// If the inlined function defines a min legal vector width, then ensure
2309/// the calling function has the same or larger min legal vector width. If the
2310/// caller has the attribute, but the callee doesn't, we need to remove the
2311/// attribute from the caller since we can't make any guarantees about the
2312/// caller's requirements.
2313/// This function is called after the inlining decision has been made so we have
2314/// to merge the attribute this way. Heuristics that would use
2315/// min-legal-vector-width to determine inline compatibility would need to be
2316/// handled as part of inline cost analysis.
2317static void
2319 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2320 if (CallerAttr.isValid()) {
2321 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2322 if (CalleeAttr.isValid()) {
2323 uint64_t CallerVectorWidth, CalleeVectorWidth;
2324 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2325 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2326 if (CallerVectorWidth < CalleeVectorWidth)
2327 Caller.addFnAttr(CalleeAttr);
2328 } else {
2329 // If the callee doesn't have the attribute then we don't know anything
2330 // and must drop the attribute from the caller.
2331 Caller.removeFnAttr("min-legal-vector-width");
2332 }
2333 }
2334}
2335
2336/// If the inlined function has null_pointer_is_valid attribute,
2337/// set this attribute in the caller post inlining.
2338static void
2340 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2341 Caller.addFnAttr(Attribute::NullPointerIsValid);
2342 }
2343}
2344
2345struct EnumAttr {
2346 static bool isSet(const Function &Fn,
2347 Attribute::AttrKind Kind) {
2348 return Fn.hasFnAttribute(Kind);
2349 }
2350
2351 static void set(Function &Fn,
2352 Attribute::AttrKind Kind, bool Val) {
2353 if (Val)
2354 Fn.addFnAttr(Kind);
2355 else
2356 Fn.removeFnAttr(Kind);
2357 }
2358};
2359
2361 static bool isSet(const Function &Fn,
2362 StringRef Kind) {
2363 auto A = Fn.getFnAttribute(Kind);
2364 return A.getValueAsString() == "true";
2365 }
2366
2367 static void set(Function &Fn,
2368 StringRef Kind, bool Val) {
2369 Fn.addFnAttr(Kind, Val ? "true" : "false");
2370 }
2371};
2372
2373#define GET_ATTR_NAMES
2374#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2375 struct ENUM_NAME##Attr : EnumAttr { \
2376 static enum Attribute::AttrKind getKind() { \
2377 return llvm::Attribute::ENUM_NAME; \
2378 } \
2379 };
2380#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2381 struct ENUM_NAME##Attr : StrBoolAttr { \
2382 static StringRef getKind() { return #DISPLAY_NAME; } \
2383 };
2384#include "llvm/IR/Attributes.inc"
2385
2386#define GET_ATTR_COMPAT_FUNC
2387#include "llvm/IR/Attributes.inc"
2388
2390 const Function &Callee) {
2391 return hasCompatibleFnAttrs(Caller, Callee);
2392}
2393
2395 const Function &B) {
2396 return hasCompatibleFnAttrs(A, B);
2397}
2398
2400 const Function &Callee) {
2401 mergeFnAttrs(Caller, Callee);
2402}
2403
2405 const Function &ToMerge) {
2406
2407 // We merge functions so that they meet the most general case.
2408 // For example, if the NoNansFPMathAttr is set in one function, but not in
2409 // the other, in the merged function we can say that the NoNansFPMathAttr
2410 // is not set.
2411 // However if we have the SpeculativeLoadHardeningAttr set true in one
2412 // function, but not the other, we make sure that the function retains
2413 // that aspect in the merged function.
2414 mergeFnAttrs(Base, ToMerge);
2415}
2416
2418 uint64_t Width) {
2419 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2420 if (Attr.isValid()) {
2421 uint64_t OldWidth;
2422 Attr.getValueAsString().getAsInteger(0, OldWidth);
2423 if (Width > OldWidth)
2424 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2425 }
2426}
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:725
@ RetAttr
Definition: Attributes.cpp:728
@ ParamAttr
Definition: Attributes.cpp:727
@ FnAttr
Definition: Attributes.cpp:726
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:734
static const char * getModRefStr(ModRefInfo MR)
Definition: Attributes.cpp:507
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:537
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:757
void Profile(FoldingSetNodeID &ID) const
Definition: AttributeImpl.h:92
Type * getValueAsType() const
Definition: Attributes.cpp:793
Attribute::AttrKind getKindAsEnum() const
Definition: Attributes.cpp:767
bool operator<(const AttributeImpl &AI) const
Used when sorting the attributes.
Definition: Attributes.cpp:810
uint64_t getValueAsInt() const
Definition: Attributes.cpp:773
bool isIntAttribute() const
Definition: AttributeImpl.h:63
bool isTypeAttribute() const
Definition: AttributeImpl.h:65
bool getValueAsBool() const
Definition: Attributes.cpp:778
StringRef getKindAsString() const
Definition: Attributes.cpp:783
StringRef getValueAsString() const
Definition: Attributes.cpp:788
bool isEnumAttribute() const
Definition: AttributeImpl.h:62
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Definition: Attributes.cpp:804
bool isConstantRangeListAttribute() const
Definition: AttributeImpl.h:69
bool isStringAttribute() const
Definition: AttributeImpl.h:64
const ConstantRange & getValueAsConstantRange() const
Definition: Attributes.cpp:798
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:984
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:878
Type * getInAllocaType() const
Definition: Attributes.cpp:957
Type * getByValType() const
Definition: Attributes.cpp:945
AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
Definition: Attributes.cpp:865
MemoryEffects getMemoryEffects() const
Definition: Attributes.cpp:988
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
Definition: Attributes.cpp:909
Type * getStructRetType() const
Definition: Attributes.cpp:949
std::string getAsString(bool InAttrGrp=false) const
Definition: Attributes.cpp:996
unsigned getVScaleRangeMin() const
Definition: Attributes.cpp:972
std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
Definition: Attributes.cpp:966
UWTableKind getUWTableKind() const
Definition: Attributes.cpp:980
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:894
std::optional< unsigned > getVScaleRangeMax() const
Definition: Attributes.cpp:976
MaybeAlign getStackAlignment() const
Definition: Attributes.cpp:929
Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
Definition: Attributes.cpp:917
Type * getPreallocatedType() const
Definition: Attributes.cpp:953
uint64_t getDereferenceableBytes() const
Definition: Attributes.cpp:933
MaybeAlign getAlignment() const
Definition: Attributes.cpp:925
FPClassTest getNoFPClass() const
Definition: Attributes.cpp:992
Type * getElementType() const
Definition: Attributes.cpp:961
Type * getByRefType() const
Definition: Attributes.cpp:941
AttributeSet()=default
AttributeSet is a trivially copyable value type.
static AttributeSet get(LLVMContext &C, const AttrBuilder &B)
Definition: Attributes.cpp:842
uint64_t getDereferenceableOrNullBytes() const
Definition: Attributes.cpp:937
unsigned getNumAttributes() const
Return the number of attributes in this set.
Definition: Attributes.cpp:905
AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
Definition: Attributes.cpp:850
void dump() const
bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
Definition: Attributes.cpp:346
static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:258
static Attribute::AttrKind getAttrKindFromName(StringRef AttrName)
Definition: Attributes.cpp:303
bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
Definition: Attributes.cpp:338
static Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment)
Definition: Attributes.cpp:237
const ConstantRange & getRange() const
Returns the value of the range attribute.
Definition: Attributes.cpp:495
bool isIntAttribute() const
Return true if the attribute is an integer attribute.
Definition: Attributes.cpp:342
static Attribute getWithByRefType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:262
std::optional< unsigned > getVScaleRangeMax() const
Returns the maximum value for the vscale_range attribute or std::nullopt when unknown.
Definition: Attributes.cpp:465
uint64_t getValueAsInt() const
Return the attribute's value as an integer.
Definition: Attributes.cpp:370
unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
Definition: Attributes.cpp:459
AllocFnKind getAllocKind() const
Definition: Attributes.cpp:477
bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
Definition: Attributes.cpp:354
StringRef getKindAsString() const
Return the attribute's kind as a string.
Definition: Attributes.cpp:384
static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:266
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:749
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:521
uint64_t getDereferenceableOrNullBytes() const
Returns the number of dereferenceable_or_null bytes from the dereferenceable_or_null attribute.
Definition: Attributes.cpp:445
static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
Definition: Attributes.cpp:242
std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
Definition: Attributes.cpp:453
static Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind)
Definition: Attributes.cpp:274
FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
Definition: Attributes.cpp:489
static Attribute getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
Definition: Attributes.cpp:290
Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
Definition: Attributes.cpp:362
Attribute()=default
bool getValueAsBool() const
Return the attribute's value as a boolean.
Definition: Attributes.cpp:377
ArrayRef< ConstantRange > getInitializes() const
Returns the value of the initializes attribute.
Definition: Attributes.cpp:501
const ConstantRange & getValueAsConstantRange() const
Return the attribute's value as a ConstantRange.
Definition: Attributes.cpp:405
uint64_t getDereferenceableBytes() const
Returns the number of dereferenceable bytes from the dereferenceable attribute.
Definition: Attributes.cpp:438
static Attribute getWithVScaleRangeArgs(LLVMContext &Context, unsigned MinValue, unsigned MaxValue)
Definition: Attributes.cpp:297
MemoryEffects getMemoryEffects() const
Returns memory effects.
Definition: Attributes.cpp:483
void Profile(FoldingSetNodeID &ID) const
Definition: Attributes.cpp:721
UWTableKind getUWTableKind() const
Definition: Attributes.cpp:471
static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, uint64_t Bytes)
Definition: Attributes.cpp:248
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
Definition: Attributes.cpp:411
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:391
static bool isExistingAttribute(StringRef Name)
Return true if the provided string matches the IR name of an attribute.
Definition: Attributes.cpp:326
static StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind)
Definition: Attributes.cpp:312
static bool canUseAsFnAttr(AttrKind Kind)
Definition: Attributes.cpp:741
static Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
Definition: Attributes.cpp:284
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:706
bool isTypeAttribute() const
Return true if the attribute is a type attribute.
Definition: Attributes.cpp:350
static Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:270
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:358
static Attribute getWithByValType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:254
bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
Definition: Attributes.cpp:417
static bool isEnumAttrKind(AttrKind Kind)
Definition: Attributes.h:99
static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
Definition: Attributes.cpp:279
static bool canUseAsParamAttr(AttrKind Kind)
Definition: Attributes.cpp:745
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:432
MaybeAlign getAlignment() const
Returns the alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:426
bool operator<(Attribute A) const
Less-than operator. Useful for sorting the attributes list.
Definition: Attributes.cpp:714
static Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
Definition: Attributes.cpp:232
Type * getValueAsType() const
Return the attribute's value as a Type.
Definition: Attributes.cpp:398
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.
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:600
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition: Function.cpp:716
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition: Function.cpp:648
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:690
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:463
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:223
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:234
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:255
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:262
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:228
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
Definition: Type.h:216
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:140
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:2067
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:1902
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:1954
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:2051
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