LLVM 22.0.0git
Attributes.cpp
Go to the documentation of this file.
1//===- Attributes.cpp - Implement AttributesList --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// \file
10// This file implements the Attribute, AttributeImpl, AttrBuilder,
11// AttributeListImpl, and AttributeList classes.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/IR/Attributes.h"
16#include "AttributeImpl.h"
17#include "LLVMContextImpl.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/FoldingSet.h"
20#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/StringRef.h"
25#include "llvm/Config/llvm-config.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/LLVMContext.h"
31#include "llvm/IR/Operator.h"
32#include "llvm/IR/Type.h"
35#include "llvm/Support/ModRef.h"
37#include <algorithm>
38#include <cassert>
39#include <cstddef>
40#include <cstdint>
41#include <limits>
42#include <optional>
43#include <string>
44#include <tuple>
45#include <utility>
46
47using namespace llvm;
48
49//===----------------------------------------------------------------------===//
50// Attribute Construction Methods
51//===----------------------------------------------------------------------===//
52
53// allocsize has two integer arguments, but because they're both 32 bits, we can
54// pack them into one 64-bit value, at the cost of making said value
55// nonsensical.
56//
57// In order to do this, we need to reserve one value of the second (optional)
58// allocsize argument to signify "not present."
59static const unsigned AllocSizeNumElemsNotPresent = -1;
60
61static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
62 const std::optional<unsigned> &NumElemsArg) {
63 assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
64 "Attempting to pack a reserved value");
65
66 return uint64_t(ElemSizeArg) << 32 |
67 NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
68}
69
70static std::pair<unsigned, std::optional<unsigned>>
72 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
73 unsigned ElemSizeArg = Num >> 32;
74
75 std::optional<unsigned> NumElemsArg;
76 if (NumElems != AllocSizeNumElemsNotPresent)
77 NumElemsArg = NumElems;
78 return std::make_pair(ElemSizeArg, NumElemsArg);
79}
80
81static uint64_t packVScaleRangeArgs(unsigned MinValue,
82 std::optional<unsigned> MaxValue) {
83 return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
84}
85
86static std::pair<unsigned, std::optional<unsigned>>
88 unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
89 unsigned MinValue = Value >> 32;
90
91 return std::make_pair(MinValue,
92 MaxValue > 0 ? MaxValue : std::optional<unsigned>());
93}
94
96 uint64_t Val) {
97 bool IsIntAttr = Attribute::isIntAttrKind(Kind);
98 assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
99 "Not an enum or int attribute");
100
101 LLVMContextImpl *pImpl = Context.pImpl;
103 ID.AddInteger(Kind);
104 if (IsIntAttr)
105 ID.AddInteger(Val);
106 else
107 assert(Val == 0 && "Value must be zero for enum attributes");
108
109 void *InsertPoint;
110 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
111
112 if (!PA) {
113 // If we didn't find any existing attributes of the same shape then create a
114 // new one and insert it.
115 if (!IsIntAttr)
116 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
117 else
118 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
119 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
120 }
121
122 // Return the Attribute that we found or created.
123 return Attribute(PA);
124}
125
127 LLVMContextImpl *pImpl = Context.pImpl;
129 ID.AddString(Kind);
130 if (!Val.empty()) ID.AddString(Val);
131
132 void *InsertPoint;
133 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
134
135 if (!PA) {
136 // If we didn't find any existing attributes of the same shape then create a
137 // new one and insert it.
138 void *Mem =
140 alignof(StringAttributeImpl));
141 PA = new (Mem) StringAttributeImpl(Kind, Val);
142 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
143 }
144
145 // Return the Attribute that we found or created.
146 return Attribute(PA);
147}
148
150 Type *Ty) {
151 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
152 LLVMContextImpl *pImpl = Context.pImpl;
154 ID.AddInteger(Kind);
155 ID.AddPointer(Ty);
156
157 void *InsertPoint;
158 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
159
160 if (!PA) {
161 // If we didn't find any existing attributes of the same shape then create a
162 // new one and insert it.
163 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
164 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
165 }
166
167 // Return the Attribute that we found or created.
168 return Attribute(PA);
169}
170
172 const ConstantRange &CR) {
174 "Not a ConstantRange attribute");
175 assert(!CR.isFullSet() && "ConstantRange attribute must not be full");
176 LLVMContextImpl *pImpl = Context.pImpl;
178 ID.AddInteger(Kind);
179 CR.getLower().Profile(ID);
180 CR.getUpper().Profile(ID);
181
182 void *InsertPoint;
183 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
184
185 if (!PA) {
186 // If we didn't find any existing attributes of the same shape then create a
187 // new one and insert it.
188 PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
190 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
191 }
192
193 // Return the Attribute that we found or created.
194 return Attribute(PA);
195}
196
200 "Not a ConstantRangeList attribute");
201 LLVMContextImpl *pImpl = Context.pImpl;
203 ID.AddInteger(Kind);
204 ID.AddInteger(Val.size());
205 for (auto &CR : Val) {
206 CR.getLower().Profile(ID);
207 CR.getUpper().Profile(ID);
208 }
209
210 void *InsertPoint;
211 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
212
213 if (!PA) {
214 // If we didn't find any existing attributes of the same shape then create a
215 // new one and insert it.
216 // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
217 // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
218 // allocation and record the allocated pointer in
219 // `ConstantRangeListAttributes`. LLVMContext destructor will call the
220 // destructor of the allocated pointer explicitly.
221 void *Mem = pImpl->Alloc.Allocate(
224 PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
225 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
226 pImpl->ConstantRangeListAttributes.push_back(
227 reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
228 }
229
230 // Return the Attribute that we found or created.
231 return Attribute(PA);
232}
233
235 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
236 return get(Context, Alignment, A.value());
237}
238
240 assert(A <= 0x100 && "Alignment too large.");
241 return get(Context, StackAlignment, A.value());
242}
243
245 uint64_t Bytes) {
246 assert(Bytes && "Bytes must be non-zero.");
247 return get(Context, Dereferenceable, Bytes);
248}
249
251 uint64_t Bytes) {
252 assert(Bytes && "Bytes must be non-zero.");
253 return get(Context, DereferenceableOrNull, Bytes);
254}
255
257 return get(Context, ByVal, Ty);
258}
259
261 return get(Context, StructRet, Ty);
262}
263
265 return get(Context, ByRef, Ty);
266}
267
269 return get(Context, Preallocated, Ty);
270}
271
273 return get(Context, InAlloca, Ty);
274}
275
277 UWTableKind Kind) {
278 return get(Context, UWTable, uint64_t(Kind));
279}
280
282 MemoryEffects ME) {
283 return get(Context, Memory, ME.toIntValue());
284}
285
287 FPClassTest ClassMask) {
288 return get(Context, NoFPClass, ClassMask);
289}
290
292 return get(Context, Captures, CI.toIntValue());
293}
294
296Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
297 const std::optional<unsigned> &NumElemsArg) {
298 assert(!(ElemSizeArg == 0 && NumElemsArg == 0) &&
299 "Invalid allocsize arguments -- given allocsize(0, 0)");
300 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
301}
302
304 return get(Context, AllocKind, static_cast<uint64_t>(Kind));
305}
306
308 unsigned MinValue,
309 unsigned MaxValue) {
310 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
311}
312
314 return StringSwitch<Attribute::AttrKind>(AttrName)
315#define GET_ATTR_NAMES
316#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
317 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
318#include "llvm/IR/Attributes.inc"
320}
321
323 switch (AttrKind) {
324#define GET_ATTR_NAMES
325#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
326 case Attribute::ENUM_NAME: \
327 return #DISPLAY_NAME;
328#include "llvm/IR/Attributes.inc"
329 case Attribute::None:
330 return "none";
331 default:
332 llvm_unreachable("invalid Kind");
333 }
334}
335
338#define GET_ATTR_NAMES
339#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
340#include "llvm/IR/Attributes.inc"
341 .Default(false);
342}
343
344//===----------------------------------------------------------------------===//
345// Attribute Accessor Methods
346//===----------------------------------------------------------------------===//
347
349 return pImpl && pImpl->isEnumAttribute();
350}
351
353 return pImpl && pImpl->isIntAttribute();
354}
355
357 return pImpl && pImpl->isStringAttribute();
358}
359
361 return pImpl && pImpl->isTypeAttribute();
362}
363
365 return pImpl && pImpl->isConstantRangeAttribute();
366}
367
369 return pImpl && pImpl->isConstantRangeListAttribute();
370}
371
373 if (!pImpl) return None;
375 "Invalid attribute type to get the kind as an enum!");
376 return pImpl->getKindAsEnum();
377}
378
380 if (!pImpl) return 0;
382 "Expected the attribute to be an integer attribute!");
383 return pImpl->getValueAsInt();
384}
385
387 if (!pImpl) return false;
389 "Expected the attribute to be a string attribute!");
390 return pImpl->getValueAsBool();
391}
392
394 if (!pImpl) return {};
396 "Invalid attribute type to get the kind as a string!");
397 return pImpl->getKindAsString();
398}
399
401 if (!pImpl) return {};
403 "Invalid attribute type to get the value as a string!");
404 return pImpl->getValueAsString();
405}
406
408 if (!pImpl) return {};
410 "Invalid attribute type to get the value as a type!");
411 return pImpl->getValueAsType();
412}
413
416 "Invalid attribute type to get the value as a ConstantRange!");
417 return pImpl->getValueAsConstantRange();
418}
419
422 "Invalid attribute type to get the value as a ConstantRangeList!");
423 return pImpl->getValueAsConstantRangeList();
424}
425
427 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
428}
429
431 if (!isStringAttribute()) return false;
432 return pImpl && pImpl->hasAttribute(Kind);
433}
434
436 assert(hasAttribute(Attribute::Alignment) &&
437 "Trying to get alignment from non-alignment attribute!");
438 return MaybeAlign(pImpl->getValueAsInt());
439}
440
442 assert(hasAttribute(Attribute::StackAlignment) &&
443 "Trying to get alignment from non-alignment attribute!");
444 return MaybeAlign(pImpl->getValueAsInt());
445}
446
448 assert(hasAttribute(Attribute::Dereferenceable) &&
449 "Trying to get dereferenceable bytes from "
450 "non-dereferenceable attribute!");
451 return pImpl->getValueAsInt();
452}
453
455 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
456 "Trying to get dereferenceable bytes from "
457 "non-dereferenceable attribute!");
458 return pImpl->getValueAsInt();
459}
460
461std::pair<unsigned, std::optional<unsigned>>
463 assert(hasAttribute(Attribute::AllocSize) &&
464 "Trying to get allocsize args from non-allocsize attribute");
465 return unpackAllocSizeArgs(pImpl->getValueAsInt());
466}
467
469 assert(hasAttribute(Attribute::VScaleRange) &&
470 "Trying to get vscale args from non-vscale attribute");
471 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
472}
473
474std::optional<unsigned> Attribute::getVScaleRangeMax() const {
475 assert(hasAttribute(Attribute::VScaleRange) &&
476 "Trying to get vscale args from non-vscale attribute");
477 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
478}
479
481 assert(hasAttribute(Attribute::UWTable) &&
482 "Trying to get unwind table kind from non-uwtable attribute");
483 return UWTableKind(pImpl->getValueAsInt());
484}
485
487 assert(hasAttribute(Attribute::AllocKind) &&
488 "Trying to get allockind value from non-allockind attribute");
489 return AllocFnKind(pImpl->getValueAsInt());
490}
491
493 assert(hasAttribute(Attribute::Memory) &&
494 "Can only call getMemoryEffects() on memory attribute");
496}
497
499 assert(hasAttribute(Attribute::Captures) &&
500 "Can only call getCaptureInfo() on captures attribute");
502}
503
505 assert(hasAttribute(Attribute::NoFPClass) &&
506 "Can only call getNoFPClass() on nofpclass attribute");
507 return static_cast<FPClassTest>(pImpl->getValueAsInt());
508}
509
511 assert(hasAttribute(Attribute::Range) &&
512 "Trying to get range args from non-range attribute");
513 return pImpl->getValueAsConstantRange();
514}
515
517 assert(hasAttribute(Attribute::Initializes) &&
518 "Trying to get initializes attr from non-ConstantRangeList attribute");
519 return pImpl->getValueAsConstantRangeList();
520}
521
522static const char *getModRefStr(ModRefInfo MR) {
523 switch (MR) {
525 return "none";
526 case ModRefInfo::Ref:
527 return "read";
528 case ModRefInfo::Mod:
529 return "write";
531 return "readwrite";
532 }
533 llvm_unreachable("Invalid ModRefInfo");
534}
535
536std::string Attribute::getAsString(bool InAttrGrp) const {
537 if (!pImpl) return {};
538
539 if (isEnumAttribute())
541
542 if (isTypeAttribute()) {
543 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
544 Result += '(';
545 raw_string_ostream OS(Result);
546 getValueAsType()->print(OS, false, true);
547 OS.flush();
548 Result += ')';
549 return Result;
550 }
551
552 // FIXME: These should be output like this:
553 //
554 // align=4
555 // alignstack=8
556 //
557 if (hasAttribute(Attribute::Alignment))
558 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
559 : "align " + Twine(getValueAsInt()))
560 .str();
561
562 auto AttrWithBytesToString = [&](const char *Name) {
563 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
564 : Name + ("(" + Twine(getValueAsInt())) + ")")
565 .str();
566 };
567
568 if (hasAttribute(Attribute::StackAlignment))
569 return AttrWithBytesToString("alignstack");
570
571 if (hasAttribute(Attribute::Dereferenceable))
572 return AttrWithBytesToString("dereferenceable");
573
574 if (hasAttribute(Attribute::DereferenceableOrNull))
575 return AttrWithBytesToString("dereferenceable_or_null");
576
577 if (hasAttribute(Attribute::AllocSize)) {
578 unsigned ElemSize;
579 std::optional<unsigned> NumElems;
580 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
581
582 return (NumElems
583 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
584 : "allocsize(" + Twine(ElemSize) + ")")
585 .str();
586 }
587
588 if (hasAttribute(Attribute::VScaleRange)) {
589 unsigned MinValue = getVScaleRangeMin();
590 std::optional<unsigned> MaxValue = getVScaleRangeMax();
591 return ("vscale_range(" + Twine(MinValue) + "," +
592 Twine(MaxValue.value_or(0)) + ")")
593 .str();
594 }
595
596 if (hasAttribute(Attribute::UWTable)) {
598 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
599 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
600 }
601
602 if (hasAttribute(Attribute::AllocKind)) {
603 AllocFnKind Kind = getAllocKind();
606 parts.push_back("alloc");
608 parts.push_back("realloc");
610 parts.push_back("free");
612 parts.push_back("uninitialized");
614 parts.push_back("zeroed");
616 parts.push_back("aligned");
617 return ("allockind(\"" +
618 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
619 .str();
620 }
621
622 if (hasAttribute(Attribute::Memory)) {
623 std::string Result;
624 raw_string_ostream OS(Result);
625 bool First = true;
626 OS << "memory(";
627
629
630 // Print access kind for "other" as the default access kind. This way it
631 // will apply to any new location kinds that get split out of "other".
633 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
634 First = false;
635 OS << getModRefStr(OtherMR);
636 }
637
638 for (auto Loc : MemoryEffects::locations()) {
639 ModRefInfo MR = ME.getModRef(Loc);
640 if (MR == OtherMR)
641 continue;
642
643 if (!First)
644 OS << ", ";
645 First = false;
646
647 switch (Loc) {
649 OS << "argmem: ";
650 break;
652 OS << "inaccessiblemem: ";
653 break;
655 OS << "errnomem: ";
656 break;
658 llvm_unreachable("This is represented as the default access kind");
659 }
660 OS << getModRefStr(MR);
661 }
662 OS << ")";
663 OS.flush();
664 return Result;
665 }
666
667 if (hasAttribute(Attribute::Captures)) {
668 std::string Result;
669 raw_string_ostream OS(Result);
670 OS << getCaptureInfo();
671 return Result;
672 }
673
674 if (hasAttribute(Attribute::NoFPClass)) {
675 std::string Result = "nofpclass";
676 raw_string_ostream OS(Result);
677 OS << getNoFPClass();
678 return Result;
679 }
680
681 if (hasAttribute(Attribute::Range)) {
682 std::string Result;
683 raw_string_ostream OS(Result);
685 OS << "range(";
686 OS << "i" << CR.getBitWidth() << " ";
687 OS << CR.getLower() << ", " << CR.getUpper();
688 OS << ")";
689 OS.flush();
690 return Result;
691 }
692
693 if (hasAttribute(Attribute::Initializes)) {
694 std::string Result;
695 raw_string_ostream OS(Result);
697 OS << "initializes(";
698 CRL.print(OS);
699 OS << ")";
700 OS.flush();
701 return Result;
702 }
703
704 // Convert target-dependent attributes to strings of the form:
705 //
706 // "kind"
707 // "kind" = "value"
708 //
709 if (isStringAttribute()) {
710 std::string Result;
711 {
712 raw_string_ostream OS(Result);
713 OS << '"' << getKindAsString() << '"';
714
715 // Since some attribute strings contain special characters that cannot be
716 // printable, those have to be escaped to make the attribute value
717 // printable as is. e.g. "\01__gnu_mcount_nc"
718 const auto &AttrVal = pImpl->getValueAsString();
719 if (!AttrVal.empty()) {
720 OS << "=\"";
721 printEscapedString(AttrVal, OS);
722 OS << "\"";
723 }
724 }
725 return Result;
726 }
727
728 llvm_unreachable("Unknown attribute");
729}
730
732 assert(isValid() && "invalid Attribute doesn't refer to any context");
734 pImpl->Profile(ID);
735 void *Unused;
736 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
737}
738
740 if (!pImpl && !A.pImpl)
741 return 0;
742 if (!pImpl)
743 return 1;
744 if (!A.pImpl)
745 return -1;
746 return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
747}
748
750 if (!pImpl && !A.pImpl) return false;
751 if (!pImpl) return true;
752 if (!A.pImpl) return false;
753 return *pImpl < *A.pImpl;
754}
755
757 ID.AddPointer(pImpl);
758}
759
761 FnAttr = (1 << 0),
762 ParamAttr = (1 << 1),
763 RetAttr = (1 << 2),
765 IntersectAnd = (1 << 3),
766 IntersectMin = (2 << 3),
767 IntersectCustom = (3 << 3),
769};
770
771#define GET_ATTR_PROP_TABLE
772#include "llvm/IR/Attributes.inc"
773
775 unsigned Index = Kind - 1;
776 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
777 return AttrPropTable[Index];
778}
779
781 AttributeProperty Prop) {
782 return getAttributeProperties(Kind) & Prop;
783}
784
786 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
787}
788
790 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
791}
792
794 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
795}
796
798 AttributeProperty Prop) {
799 assert((Prop == AttributeProperty::IntersectPreserve ||
800 Prop == AttributeProperty::IntersectAnd ||
801 Prop == AttributeProperty::IntersectMin ||
802 Prop == AttributeProperty::IntersectCustom) &&
803 "Unknown intersect property");
804 return (getAttributeProperties(Kind) &
805 AttributeProperty::IntersectPropertyMask) == Prop;
806}
807
809 return hasIntersectProperty(Kind, AttributeProperty::IntersectPreserve);
810}
812 return hasIntersectProperty(Kind, AttributeProperty::IntersectAnd);
813}
815 return hasIntersectProperty(Kind, AttributeProperty::IntersectMin);
816}
818 return hasIntersectProperty(Kind, AttributeProperty::IntersectCustom);
819}
820
821//===----------------------------------------------------------------------===//
822// AttributeImpl Definition
823//===----------------------------------------------------------------------===//
824
826 if (isStringAttribute()) return false;
827 return getKindAsEnum() == A;
828}
829
831 if (!isStringAttribute()) return false;
832 return getKindAsString() == Kind;
833}
834
838 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
839}
840
843 return static_cast<const IntAttributeImpl *>(this)->getValue();
844}
845
847 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
848 return getValueAsString() == "true";
849}
850
853 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
854}
855
858 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
859}
860
863 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
864}
865
868 return static_cast<const ConstantRangeAttributeImpl *>(this)
869 ->getConstantRangeValue();
870}
871
874 return static_cast<const ConstantRangeListAttributeImpl *>(this)
875 ->getConstantRangeListValue();
876}
877
878int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
879 if (this == &AI)
880 return 0;
881
882 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
883 // relative to their enum value) and then strings.
884 if (!isStringAttribute()) {
885 if (AI.isStringAttribute())
886 return -1;
887
888 if (getKindAsEnum() != AI.getKindAsEnum())
889 return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
890 else if (KindOnly)
891 return 0;
892
893 assert(!AI.isEnumAttribute() && "Non-unique attribute");
894 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
895 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
897 "Unclear how to compare range list");
898 // TODO: Is this actually needed?
899 assert(AI.isIntAttribute() && "Only possibility left");
900 if (getValueAsInt() < AI.getValueAsInt())
901 return -1;
902 return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
903 }
904 if (!AI.isStringAttribute())
905 return 1;
906 if (KindOnly)
908 if (getKindAsString() == AI.getKindAsString())
911}
912
914 return cmp(AI, /*KindOnly=*/false) < 0;
915}
916
917//===----------------------------------------------------------------------===//
918// AttributeSet Definition
919//===----------------------------------------------------------------------===//
920
923}
924
926 return AttributeSet(AttributeSetNode::get(C, Attrs));
927}
928
930 Attribute::AttrKind Kind) const {
931 if (hasAttribute(Kind)) return *this;
932 AttrBuilder B(C);
933 B.addAttribute(Kind);
935}
936
938 StringRef Value) const {
939 AttrBuilder B(C);
940 B.addAttribute(Kind, Value);
942}
943
945 const AttributeSet AS) const {
946 if (!hasAttributes())
947 return AS;
948
949 if (!AS.hasAttributes())
950 return *this;
951
952 AttrBuilder B(C, *this);
953 B.merge(AttrBuilder(C, AS));
954 return get(C, B);
955}
956
958 const AttrBuilder &B) const {
959 if (!hasAttributes())
960 return get(C, B);
961
962 if (!B.hasAttributes())
963 return *this;
964
965 AttrBuilder Merged(C, *this);
966 Merged.merge(B);
967 return get(C, Merged);
968}
969
971 Attribute::AttrKind Kind) const {
972 if (!hasAttribute(Kind)) return *this;
973 AttrBuilder B(C, *this);
974 B.removeAttribute(Kind);
975 return get(C, B);
976}
977
979 StringRef Kind) const {
980 if (!hasAttribute(Kind)) return *this;
981 AttrBuilder B(C, *this);
982 B.removeAttribute(Kind);
983 return get(C, B);
984}
985
987 const AttributeMask &Attrs) const {
988 AttrBuilder B(C, *this);
989 // If there is nothing to remove, directly return the original set.
990 if (!B.overlaps(Attrs))
991 return *this;
992
993 B.remove(Attrs);
994 return get(C, B);
995}
996
997std::optional<AttributeSet>
999 if (*this == Other)
1000 return *this;
1001
1002 AttrBuilder Intersected(C);
1003 // Iterate over both attr sets at once.
1004 auto ItBegin0 = begin();
1005 auto ItEnd0 = end();
1006 auto ItBegin1 = Other.begin();
1007 auto ItEnd1 = Other.end();
1008
1009 while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
1010 // Loop through all attributes in both this and Other in sorted order. If
1011 // the attribute is only present in one of the sets, it will be set in
1012 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
1013 Attribute Attr0, Attr1;
1014 if (ItBegin1 == ItEnd1)
1015 Attr0 = *ItBegin0++;
1016 else if (ItBegin0 == ItEnd0)
1017 Attr0 = *ItBegin1++;
1018 else {
1019 int Cmp = ItBegin0->cmpKind(*ItBegin1);
1020 if (Cmp == 0) {
1021 Attr0 = *ItBegin0++;
1022 Attr1 = *ItBegin1++;
1023 } else if (Cmp < 0)
1024 Attr0 = *ItBegin0++;
1025 else
1026 Attr0 = *ItBegin1++;
1027 }
1028 assert(Attr0.isValid() && "Iteration should always yield a valid attr");
1029
1030 auto IntersectEq = [&]() {
1031 if (!Attr1.isValid())
1032 return false;
1033 if (Attr0 != Attr1)
1034 return false;
1035 Intersected.addAttribute(Attr0);
1036 return true;
1037 };
1038
1039 // Non-enum assume we must preserve. Handle early so we can unconditionally
1040 // use Kind below.
1041 if (!Attr0.hasKindAsEnum()) {
1042 if (!IntersectEq())
1043 return std::nullopt;
1044 continue;
1045 }
1046
1047 Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1048 // If we don't have both attributes, then fail if the attribute is
1049 // must-preserve or drop it otherwise.
1050 if (!Attr1.isValid()) {
1052 return std::nullopt;
1053 continue;
1054 }
1055
1056 // We have both attributes so apply the intersection rule.
1057 assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1058 "Iterator picked up two different attributes in the same iteration");
1059
1060 // Attribute we can intersect with "and"
1061 if (Attribute::intersectWithAnd(Kind)) {
1063 "Invalid attr type of intersectAnd");
1064 Intersected.addAttribute(Kind);
1065 continue;
1066 }
1067
1068 // Attribute we can intersect with "min"
1069 if (Attribute::intersectWithMin(Kind)) {
1071 "Invalid attr type of intersectMin");
1072 uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1073 Intersected.addRawIntAttr(Kind, NewVal);
1074 continue;
1075 }
1076 // Attribute we can intersect but need a custom rule for.
1078 switch (Kind) {
1079 case Attribute::Alignment:
1080 // If `byval` is present, alignment become must-preserve. This is
1081 // handled below if we have `byval`.
1082 Intersected.addAlignmentAttr(
1083 std::min(Attr0.getAlignment().valueOrOne(),
1084 Attr1.getAlignment().valueOrOne()));
1085 break;
1086 case Attribute::Memory:
1087 Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1088 Attr1.getMemoryEffects());
1089 break;
1090 case Attribute::Captures:
1091 Intersected.addCapturesAttr(Attr0.getCaptureInfo() |
1092 Attr1.getCaptureInfo());
1093 break;
1094 case Attribute::NoFPClass:
1095 Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1096 Attr1.getNoFPClass());
1097 break;
1098 case Attribute::Range: {
1099 ConstantRange Range0 = Attr0.getRange();
1100 ConstantRange Range1 = Attr1.getRange();
1101 ConstantRange NewRange = Range0.unionWith(Range1);
1102 if (!NewRange.isFullSet())
1103 Intersected.addRangeAttr(NewRange);
1104 } break;
1105 default:
1106 llvm_unreachable("Unknown attribute with custom intersection rule");
1107 }
1108 continue;
1109 }
1110
1111 // Attributes with no intersection rule. Only intersect if they are equal.
1112 // Otherwise fail.
1113 if (!IntersectEq())
1114 return std::nullopt;
1115
1116 // Special handling of `byval`. `byval` essentially turns align attr into
1117 // must-preserve
1118 if (Kind == Attribute::ByVal &&
1119 getAttribute(Attribute::Alignment) !=
1120 Other.getAttribute(Attribute::Alignment))
1121 return std::nullopt;
1122 }
1123
1124 return get(C, Intersected);
1125}
1126
1128 return SetNode ? SetNode->getNumAttributes() : 0;
1129}
1130
1132 return SetNode ? SetNode->hasAttribute(Kind) : false;
1133}
1134
1136 return SetNode ? SetNode->hasAttribute(Kind) : false;
1137}
1138
1140 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1141}
1142
1144 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1145}
1146
1148 return SetNode ? SetNode->getAlignment() : std::nullopt;
1149}
1150
1152 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
1153}
1154
1156 return SetNode ? SetNode->getDereferenceableBytes() : 0;
1157}
1158
1160 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
1161}
1162
1164 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
1165}
1166
1168 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
1169}
1170
1172 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
1173}
1174
1176 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
1177}
1178
1180 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
1181}
1182
1184 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
1185}
1186
1187std::optional<std::pair<unsigned, std::optional<unsigned>>>
1189 if (SetNode)
1190 return SetNode->getAllocSizeArgs();
1191 return std::nullopt;
1192}
1193
1195 return SetNode ? SetNode->getVScaleRangeMin() : 1;
1196}
1197
1198std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1199 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
1200}
1201
1203 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
1204}
1205
1207 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
1208}
1209
1211 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
1212}
1213
1215 return SetNode ? SetNode->getCaptureInfo() : CaptureInfo::all();
1216}
1217
1219 return SetNode ? SetNode->getNoFPClass() : fcNone;
1220}
1221
1222std::string AttributeSet::getAsString(bool InAttrGrp) const {
1223 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
1224}
1225
1227 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1229 SetNode->Profile(ID);
1230 void *Unused;
1231 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1232}
1233
1235 return SetNode ? SetNode->begin() : nullptr;
1236}
1237
1239 return SetNode ? SetNode->end() : nullptr;
1240}
1241
1242#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1244 dbgs() << "AS =\n";
1245 dbgs() << " { ";
1246 dbgs() << getAsString(true) << " }\n";
1247}
1248#endif
1249
1250//===----------------------------------------------------------------------===//
1251// AttributeSetNode Definition
1252//===----------------------------------------------------------------------===//
1253
1254AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1255 : NumAttrs(Attrs.size()) {
1256 // There's memory after the node where we can store the entries in.
1257 llvm::copy(Attrs, getTrailingObjects());
1258
1259 for (const auto &I : *this) {
1260 if (I.isStringAttribute())
1261 StringAttrs.insert({ I.getKindAsString(), I });
1262 else
1263 AvailableAttrs.addAttribute(I.getKindAsEnum());
1264 }
1265}
1266
1268 ArrayRef<Attribute> Attrs) {
1269 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1270 llvm::sort(SortedAttrs);
1271 return getSorted(C, SortedAttrs);
1272}
1273
1274AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1275 ArrayRef<Attribute> SortedAttrs) {
1276 if (SortedAttrs.empty())
1277 return nullptr;
1278
1279 // Build a key to look up the existing attributes.
1280 LLVMContextImpl *pImpl = C.pImpl;
1282
1283 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1284 for (const auto &Attr : SortedAttrs)
1285 Attr.Profile(ID);
1286
1287 void *InsertPoint;
1288 AttributeSetNode *PA =
1289 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1290
1291 // If we didn't find any existing attributes of the same shape then create a
1292 // new one and insert it.
1293 if (!PA) {
1294 // Coallocate entries after the AttributeSetNode itself.
1295 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1296 PA = new (Mem) AttributeSetNode(SortedAttrs);
1297 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1298 }
1299
1300 // Return the AttributeSetNode that we found or created.
1301 return PA;
1302}
1303
1305 return getSorted(C, B.attrs());
1306}
1307
1309 return StringAttrs.count(Kind);
1310}
1311
1312std::optional<Attribute>
1313AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1314 // Do a quick presence check.
1315 if (!hasAttribute(Kind))
1316 return std::nullopt;
1317
1318 // Attributes in a set are sorted by enum value, followed by string
1319 // attributes. Binary search the one we want.
1320 const Attribute *I =
1321 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1322 [](Attribute A, Attribute::AttrKind Kind) {
1323 return A.getKindAsEnum() < Kind;
1324 });
1325 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1326 return *I;
1327}
1328
1330 if (auto A = findEnumAttribute(Kind))
1331 return *A;
1332 return {};
1333}
1334
1336 return StringAttrs.lookup(Kind);
1337}
1338
1340 if (auto A = findEnumAttribute(Attribute::Alignment))
1341 return A->getAlignment();
1342 return std::nullopt;
1343}
1344
1346 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1347 return A->getStackAlignment();
1348 return std::nullopt;
1349}
1350
1352 if (auto A = findEnumAttribute(Kind))
1353 return A->getValueAsType();
1354 return nullptr;
1355}
1356
1358 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1359 return A->getDereferenceableBytes();
1360 return 0;
1361}
1362
1364 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1365 return A->getDereferenceableOrNullBytes();
1366 return 0;
1367}
1368
1369std::optional<std::pair<unsigned, std::optional<unsigned>>>
1371 if (auto A = findEnumAttribute(Attribute::AllocSize))
1372 return A->getAllocSizeArgs();
1373 return std::nullopt;
1374}
1375
1377 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1378 return A->getVScaleRangeMin();
1379 return 1;
1380}
1381
1382std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1383 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1384 return A->getVScaleRangeMax();
1385 return std::nullopt;
1386}
1387
1389 if (auto A = findEnumAttribute(Attribute::UWTable))
1390 return A->getUWTableKind();
1391 return UWTableKind::None;
1392}
1393
1395 if (auto A = findEnumAttribute(Attribute::AllocKind))
1396 return A->getAllocKind();
1397 return AllocFnKind::Unknown;
1398}
1399
1401 if (auto A = findEnumAttribute(Attribute::Memory))
1402 return A->getMemoryEffects();
1403 return MemoryEffects::unknown();
1404}
1405
1407 if (auto A = findEnumAttribute(Attribute::Captures))
1408 return A->getCaptureInfo();
1409 return CaptureInfo::all();
1410}
1411
1413 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1414 return A->getNoFPClass();
1415 return fcNone;
1416}
1417
1418std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1419 std::string Str;
1420 for (iterator I = begin(), E = end(); I != E; ++I) {
1421 if (I != begin())
1422 Str += ' ';
1423 Str += I->getAsString(InAttrGrp);
1424 }
1425 return Str;
1426}
1427
1428//===----------------------------------------------------------------------===//
1429// AttributeListImpl Definition
1430//===----------------------------------------------------------------------===//
1431
1432/// Map from AttributeList index to the internal array index. Adding one happens
1433/// to work, because -1 wraps around to 0.
1434static unsigned attrIdxToArrayIdx(unsigned Index) {
1435 return Index + 1;
1436}
1437
1439 : NumAttrSets(Sets.size()) {
1440 assert(!Sets.empty() && "pointless AttributeListImpl");
1441
1442 // There's memory after the node where we can store the entries in.
1444
1445 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1446 // summary bitsets.
1447 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1448 if (!I.isStringAttribute())
1449 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1450
1451 for (const auto &Set : Sets)
1452 for (const auto &I : Set)
1453 if (!I.isStringAttribute())
1454 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1455}
1456
1458 Profile(ID, ArrayRef(begin(), end()));
1459}
1460
1463 for (const auto &Set : Sets)
1464 ID.AddPointer(Set.SetNode);
1465}
1466
1468 unsigned *Index) const {
1469 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1470 return false;
1471
1472 if (Index) {
1473 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1474 if (begin()[I].hasAttribute(Kind)) {
1475 *Index = I - 1;
1476 break;
1477 }
1478 }
1479 }
1480
1481 return true;
1482}
1483
1484
1485#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1487 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1488}
1489#endif
1490
1491//===----------------------------------------------------------------------===//
1492// AttributeList Construction and Mutation Methods
1493//===----------------------------------------------------------------------===//
1494
1495AttributeList AttributeList::getImpl(LLVMContext &C,
1496 ArrayRef<AttributeSet> AttrSets) {
1497 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1498
1499 LLVMContextImpl *pImpl = C.pImpl;
1501 AttributeListImpl::Profile(ID, AttrSets);
1502
1503 void *InsertPoint;
1504 AttributeListImpl *PA =
1505 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1506
1507 // If we didn't find any existing attributes of the same shape then
1508 // create a new one and insert it.
1509 if (!PA) {
1510 // Coallocate entries after the AttributeListImpl itself.
1511 void *Mem = pImpl->Alloc.Allocate(
1512 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1513 alignof(AttributeListImpl));
1514 PA = new (Mem) AttributeListImpl(AttrSets);
1515 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1516 }
1517
1518 // Return the AttributesList that we found or created.
1519 return AttributeList(PA);
1520}
1521
1524 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1525 // If there are no attributes then return a null AttributesList pointer.
1526 if (Attrs.empty())
1527 return {};
1528
1530 "Misordered Attributes list!");
1531 assert(llvm::all_of(Attrs,
1532 [](const std::pair<unsigned, Attribute> &Pair) {
1533 return Pair.second.isValid();
1534 }) &&
1535 "Pointless attribute!");
1536
1537 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1538 // list.
1540 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1541 E = Attrs.end(); I != E; ) {
1542 unsigned Index = I->first;
1544 while (I != E && I->first == Index) {
1545 AttrVec.push_back(I->second);
1546 ++I;
1547 }
1548
1549 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1550 }
1551
1552 return get(C, AttrPairVec);
1553}
1554
1557 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1558 // If there are no attributes then return a null AttributesList pointer.
1559 if (Attrs.empty())
1560 return {};
1561
1563 "Misordered Attributes list!");
1564 assert(llvm::none_of(Attrs,
1565 [](const std::pair<unsigned, AttributeSet> &Pair) {
1566 return !Pair.second.hasAttributes();
1567 }) &&
1568 "Pointless attribute!");
1569
1570 unsigned MaxIndex = Attrs.back().first;
1571 // If the MaxIndex is FunctionIndex and there are other indices in front
1572 // of it, we need to use the largest of those to get the right size.
1573 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1574 MaxIndex = Attrs[Attrs.size() - 2].first;
1575
1576 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1577 for (const auto &Pair : Attrs)
1578 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1579
1580 return getImpl(C, AttrVec);
1581}
1582
1584 AttributeSet RetAttrs,
1585 ArrayRef<AttributeSet> ArgAttrs) {
1586 // Scan from the end to find the last argument with attributes. Most
1587 // arguments don't have attributes, so it's nice if we can have fewer unique
1588 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1589 unsigned NumSets = 0;
1590 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1591 if (ArgAttrs[I - 1].hasAttributes()) {
1592 NumSets = I + 2;
1593 break;
1594 }
1595 }
1596 if (NumSets == 0) {
1597 // Check function and return attributes if we didn't have argument
1598 // attributes.
1599 if (RetAttrs.hasAttributes())
1600 NumSets = 2;
1601 else if (FnAttrs.hasAttributes())
1602 NumSets = 1;
1603 }
1604
1605 // If all attribute sets were empty, we can use the empty attribute list.
1606 if (NumSets == 0)
1607 return {};
1608
1610 AttrSets.reserve(NumSets);
1611 // If we have any attributes, we always have function attributes.
1612 AttrSets.push_back(FnAttrs);
1613 if (NumSets > 1)
1614 AttrSets.push_back(RetAttrs);
1615 if (NumSets > 2) {
1616 // Drop the empty argument attribute sets at the end.
1617 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1618 llvm::append_range(AttrSets, ArgAttrs);
1619 }
1620
1621 return getImpl(C, AttrSets);
1622}
1623
1625 AttributeSet Attrs) {
1626 if (!Attrs.hasAttributes())
1627 return {};
1628 Index = attrIdxToArrayIdx(Index);
1629 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1630 AttrSets[Index] = Attrs;
1631 return getImpl(C, AttrSets);
1632}
1633
1635 const AttrBuilder &B) {
1636 return get(C, Index, AttributeSet::get(C, B));
1637}
1638
1642 for (const auto K : Kinds)
1643 Attrs.emplace_back(Index, Attribute::get(C, K));
1644 return get(C, Attrs);
1645}
1646
1649 ArrayRef<uint64_t> Values) {
1650 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1652 auto VI = Values.begin();
1653 for (const auto K : Kinds)
1654 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1655 return get(C, Attrs);
1656}
1657
1659 ArrayRef<StringRef> Kinds) {
1661 for (const auto &K : Kinds)
1662 Attrs.emplace_back(Index, Attribute::get(C, K));
1663 return get(C, Attrs);
1664}
1665
1668 if (Attrs.empty())
1669 return {};
1670 if (Attrs.size() == 1)
1671 return Attrs[0];
1672
1673 unsigned MaxSize = 0;
1674 for (const auto &List : Attrs)
1675 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1676
1677 // If every list was empty, there is no point in merging the lists.
1678 if (MaxSize == 0)
1679 return {};
1680
1681 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1682 for (unsigned I = 0; I < MaxSize; ++I) {
1683 AttrBuilder CurBuilder(C);
1684 for (const auto &List : Attrs)
1685 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1686 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1687 }
1688
1689 return getImpl(C, NewAttrSets);
1690}
1691
1694 Attribute::AttrKind Kind) const {
1695 AttributeSet Attrs = getAttributes(Index);
1696 if (Attrs.hasAttribute(Kind))
1697 return *this;
1698 // TODO: Insert at correct position and avoid sort.
1699 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1700 NewAttrs.push_back(Attribute::get(C, Kind));
1701 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1702}
1703
1705 StringRef Kind,
1706 StringRef Value) const {
1707 AttrBuilder B(C);
1708 B.addAttribute(Kind, Value);
1709 return addAttributesAtIndex(C, Index, B);
1710}
1711
1713 Attribute A) const {
1714 AttrBuilder B(C);
1715 B.addAttribute(A);
1716 return addAttributesAtIndex(C, Index, B);
1717}
1718
1719AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1720 unsigned Index,
1721 AttributeSet Attrs) const {
1722 Index = attrIdxToArrayIdx(Index);
1723 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1724 if (Index >= AttrSets.size())
1725 AttrSets.resize(Index + 1);
1726 AttrSets[Index] = Attrs;
1727
1728 // Remove trailing empty attribute sets.
1729 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1730 AttrSets.pop_back();
1731 if (AttrSets.empty())
1732 return {};
1733 return AttributeList::getImpl(C, AttrSets);
1734}
1735
1737 unsigned Index,
1738 const AttrBuilder &B) const {
1739 if (!B.hasAttributes())
1740 return *this;
1741
1742 if (!pImpl)
1743 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1744
1745 AttrBuilder Merged(C, getAttributes(Index));
1746 Merged.merge(B);
1747 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1748}
1749
1751 ArrayRef<unsigned> ArgNos,
1752 Attribute A) const {
1753 assert(llvm::is_sorted(ArgNos));
1754
1755 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1756 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1757 if (MaxIndex >= AttrSets.size())
1758 AttrSets.resize(MaxIndex + 1);
1759
1760 for (unsigned ArgNo : ArgNos) {
1761 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1762 AttrBuilder B(C, AttrSets[Index]);
1763 B.addAttribute(A);
1764 AttrSets[Index] = AttributeSet::get(C, B);
1765 }
1766
1767 return getImpl(C, AttrSets);
1768}
1769
1772 Attribute::AttrKind Kind) const {
1773 AttributeSet Attrs = getAttributes(Index);
1774 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1775 if (Attrs == NewAttrs)
1776 return *this;
1777 return setAttributesAtIndex(C, Index, NewAttrs);
1778}
1779
1781 unsigned Index,
1782 StringRef Kind) const {
1783 AttributeSet Attrs = getAttributes(Index);
1784 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1785 if (Attrs == NewAttrs)
1786 return *this;
1787 return setAttributesAtIndex(C, Index, NewAttrs);
1788}
1789
1791 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1792 AttributeSet Attrs = getAttributes(Index);
1793 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1794 // If nothing was removed, return the original list.
1795 if (Attrs == NewAttrs)
1796 return *this;
1797 return setAttributesAtIndex(C, Index, NewAttrs);
1798}
1799
1802 unsigned WithoutIndex) const {
1803 if (!pImpl)
1804 return {};
1805 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1806 return *this;
1807 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1808}
1809
1811 uint64_t Bytes) const {
1812 AttrBuilder B(C);
1813 B.addDereferenceableAttr(Bytes);
1814 return addRetAttributes(C, B);
1815}
1816
1818 unsigned Index,
1819 uint64_t Bytes) const {
1820 AttrBuilder B(C);
1821 B.addDereferenceableAttr(Bytes);
1822 return addParamAttributes(C, Index, B);
1823}
1824
1827 uint64_t Bytes) const {
1828 AttrBuilder B(C);
1829 B.addDereferenceableOrNullAttr(Bytes);
1830 return addParamAttributes(C, Index, B);
1831}
1832
1834 const ConstantRange &CR) const {
1835 AttrBuilder B(C);
1836 B.addRangeAttr(CR);
1837 return addRetAttributes(C, B);
1838}
1839
1841 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1842 const std::optional<unsigned> &NumElemsArg) const {
1843 AttrBuilder B(C);
1844 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1845 return addParamAttributes(C, Index, B);
1846}
1847
1848std::optional<AttributeList>
1850 // Trivial case, the two lists are equal.
1851 if (*this == Other)
1852 return *this;
1853
1855 auto IndexIt =
1856 index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1857 for (unsigned Idx : IndexIt) {
1858 auto IntersectedAS =
1859 getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1860 // If any index fails to intersect, fail.
1861 if (!IntersectedAS)
1862 return std::nullopt;
1863 if (!IntersectedAS->hasAttributes())
1864 continue;
1865 IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1866 }
1867
1868 llvm::sort(IntersectedAttrs, llvm::less_first());
1869 return AttributeList::get(C, IntersectedAttrs);
1870}
1871
1872//===----------------------------------------------------------------------===//
1873// AttributeList Accessor Methods
1874//===----------------------------------------------------------------------===//
1875
1877 return getAttributes(ArgNo + FirstArgIndex);
1878}
1879
1881 return getAttributes(ReturnIndex);
1882}
1883
1886}
1887
1889 Attribute::AttrKind Kind) const {
1890 return getAttributes(Index).hasAttribute(Kind);
1891}
1892
1893bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1894 return getAttributes(Index).hasAttribute(Kind);
1895}
1896
1897bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1898 return getAttributes(Index).hasAttributes();
1899}
1900
1902 return pImpl && pImpl->hasFnAttribute(Kind);
1903}
1904
1907}
1908
1910 unsigned *Index) const {
1911 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1912}
1913
1915 Attribute::AttrKind Kind) const {
1916 return getAttributes(Index).getAttribute(Kind);
1917}
1918
1920 StringRef Kind) const {
1921 return getAttributes(Index).getAttribute(Kind);
1922}
1923
1926}
1927
1929 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1930}
1931
1934}
1935
1938}
1939
1942}
1943
1945 return getAttributes(Index + FirstArgIndex).getByRefType();
1946}
1947
1950}
1951
1954}
1955
1957 return getAttributes(Index + FirstArgIndex).getElementType();
1958}
1959
1961 return getFnAttrs().getStackAlignment();
1962}
1963
1965 return getRetAttrs().getStackAlignment();
1966}
1967
1970}
1971
1973 return getParamAttrs(Index).getDereferenceableBytes();
1974}
1975
1978}
1979
1983}
1984
1985std::optional<ConstantRange>
1986AttributeList::getParamRange(unsigned ArgNo) const {
1987 auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
1988 if (RangeAttr.isValid())
1989 return RangeAttr.getRange();
1990 return std::nullopt;
1991}
1992
1994 return getRetAttrs().getNoFPClass();
1995}
1996
1998 return getParamAttrs(Index).getNoFPClass();
1999}
2000
2002 return getFnAttrs().getUWTableKind();
2003}
2004
2006 return getFnAttrs().getAllocKind();
2007}
2008
2010 return getFnAttrs().getMemoryEffects();
2011}
2012
2013std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
2014 return getAttributes(Index).getAsString(InAttrGrp);
2015}
2016
2018 Index = attrIdxToArrayIdx(Index);
2019 if (!pImpl || Index >= getNumAttrSets())
2020 return {};
2021 return pImpl->begin()[Index];
2022}
2023
2025 assert(!isEmpty() && "an empty attribute list has no parent context");
2027 pImpl->Profile(ID);
2028 void *Unused;
2029 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
2030}
2031
2033 return pImpl ? pImpl->begin() : nullptr;
2034}
2035
2037 return pImpl ? pImpl->end() : nullptr;
2038}
2039
2040//===----------------------------------------------------------------------===//
2041// AttributeList Introspection Methods
2042//===----------------------------------------------------------------------===//
2043
2045 return pImpl ? pImpl->NumAttrSets : 0;
2046}
2047
2049 O << "AttributeList[\n";
2050
2051 for (unsigned i : indexes()) {
2052 if (!getAttributes(i).hasAttributes())
2053 continue;
2054 O << " { ";
2055 switch (i) {
2057 O << "return";
2058 break;
2060 O << "function";
2061 break;
2062 default:
2063 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2064 }
2065 O << " => " << getAsString(i) << " }\n";
2066 }
2067
2068 O << "]\n";
2069}
2070
2071#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2073#endif
2074
2075//===----------------------------------------------------------------------===//
2076// AttrBuilder Method Implementations
2077//===----------------------------------------------------------------------===//
2078
2080 append_range(Attrs, AS);
2081 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2082}
2083
2084void AttrBuilder::clear() { Attrs.clear(); }
2085
2086/// Attribute comparator that only compares attribute keys. Enum attributes are
2087/// sorted before string attributes.
2089 bool operator()(Attribute A0, Attribute A1) const {
2090 bool A0IsString = A0.isStringAttribute();
2091 bool A1IsString = A1.isStringAttribute();
2092 if (A0IsString) {
2093 if (A1IsString)
2094 return A0.getKindAsString() < A1.getKindAsString();
2095 else
2096 return false;
2097 }
2098 if (A1IsString)
2099 return true;
2100 return A0.getKindAsEnum() < A1.getKindAsEnum();
2101 }
2103 if (A0.isStringAttribute())
2104 return false;
2105 return A0.getKindAsEnum() < Kind;
2106 }
2107 bool operator()(Attribute A0, StringRef Kind) const {
2108 if (A0.isStringAttribute())
2109 return A0.getKindAsString() < Kind;
2110 return true;
2111 }
2112};
2113
2114template <typename K>
2116 Attribute Attr) {
2117 auto It = lower_bound(Attrs, Kind, AttributeComparator());
2118 if (It != Attrs.end() && It->hasAttribute(Kind))
2119 std::swap(*It, Attr);
2120 else
2121 Attrs.insert(It, Attr);
2122}
2123
2125 if (Attr.isStringAttribute())
2126 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2127 else
2128 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2129 return *this;
2130}
2131
2133 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2134 return *this;
2135}
2136
2138 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2139 return *this;
2140}
2141
2143 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2144 auto It = lower_bound(Attrs, Val, AttributeComparator());
2145 if (It != Attrs.end() && It->hasAttribute(Val))
2146 Attrs.erase(It);
2147 return *this;
2148}
2149
2151 auto It = lower_bound(Attrs, A, AttributeComparator());
2152 if (It != Attrs.end() && It->hasAttribute(A))
2153 Attrs.erase(It);
2154 return *this;
2155}
2156
2157std::optional<uint64_t>
2159 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2160 Attribute A = getAttribute(Kind);
2161 if (A.isValid())
2162 return A.getValueAsInt();
2163 return std::nullopt;
2164}
2165
2167 uint64_t Value) {
2168 return addAttribute(Attribute::get(Ctx, Kind, Value));
2169}
2170
2171std::optional<std::pair<unsigned, std::optional<unsigned>>>
2173 Attribute A = getAttribute(Attribute::AllocSize);
2174 if (A.isValid())
2175 return A.getAllocSizeArgs();
2176 return std::nullopt;
2177}
2178
2180 if (!Align)
2181 return *this;
2182
2183 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2184 return addRawIntAttr(Attribute::Alignment, Align->value());
2185}
2186
2188 // Default alignment, allow the target to define how to align it.
2189 if (!Align)
2190 return *this;
2191
2192 assert(*Align <= 0x100 && "Alignment too large.");
2193 return addRawIntAttr(Attribute::StackAlignment, Align->value());
2194}
2195
2197 if (Bytes == 0) return *this;
2198
2199 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2200}
2201
2203 if (Bytes == 0)
2204 return *this;
2205
2206 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2207}
2208
2211 const std::optional<unsigned> &NumElems) {
2212 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2213}
2214
2216 // (0, 0) is our "not present" value, so we need to check for it here.
2217 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2218 return addRawIntAttr(Attribute::AllocSize, RawArgs);
2219}
2220
2222 std::optional<unsigned> MaxValue) {
2223 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2224}
2225
2227 // (0, 0) is not present hence ignore this case
2228 if (RawArgs == 0)
2229 return *this;
2230
2231 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2232}
2233
2235 if (Kind == UWTableKind::None)
2236 return *this;
2237 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2238}
2239
2241 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2242}
2243
2245 return addRawIntAttr(Attribute::Captures, CI.toIntValue());
2246}
2247
2249 if (Mask == fcNone)
2250 return *this;
2251
2252 return addRawIntAttr(Attribute::NoFPClass, Mask);
2253}
2254
2256 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2257}
2258
2260 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2261 Attribute A = getAttribute(Kind);
2262 return A.isValid() ? A.getValueAsType() : nullptr;
2263}
2264
2266 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2267}
2268
2270 return addTypeAttr(Attribute::ByVal, Ty);
2271}
2272
2274 return addTypeAttr(Attribute::StructRet, Ty);
2275}
2276
2278 return addTypeAttr(Attribute::ByRef, Ty);
2279}
2280
2282 return addTypeAttr(Attribute::Preallocated, Ty);
2283}
2284
2286 return addTypeAttr(Attribute::InAlloca, Ty);
2287}
2288
2290 const ConstantRange &CR) {
2291 if (CR.isFullSet())
2292 return *this;
2293
2294 return addAttribute(Attribute::get(Ctx, Kind, CR));
2295}
2296
2298 return addConstantRangeAttr(Attribute::Range, CR);
2299}
2300
2304 return addAttribute(Attribute::get(Ctx, Kind, Val));
2305}
2306
2308 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2309}
2310
2312 if (I.hasMetadata(LLVMContext::MD_nonnull))
2313 addAttribute(Attribute::NonNull);
2314
2315 if (I.hasMetadata(LLVMContext::MD_noundef))
2316 addAttribute(Attribute::NoUndef);
2317
2318 if (const MDNode *Align = I.getMetadata(LLVMContext::MD_align)) {
2319 ConstantInt *CI = mdconst::extract<ConstantInt>(Align->getOperand(0));
2321 }
2322
2323 if (const MDNode *Dereferenceable =
2324 I.getMetadata(LLVMContext::MD_dereferenceable)) {
2325 ConstantInt *CI =
2326 mdconst::extract<ConstantInt>(Dereferenceable->getOperand(0));
2328 }
2329
2330 if (const MDNode *DereferenceableOrNull =
2331 I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) {
2332 ConstantInt *CI =
2333 mdconst::extract<ConstantInt>(DereferenceableOrNull->getOperand(0));
2335 }
2336
2337 if (const MDNode *Range = I.getMetadata(LLVMContext::MD_range))
2339
2340 return *this;
2341}
2342
2344 // TODO: Could make this O(n) as we're merging two sorted lists.
2345 for (const auto &I : B.attrs())
2346 addAttribute(I);
2347
2348 return *this;
2349}
2350
2352 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2353 return *this;
2354}
2355
2357 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2358}
2359
2361 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2362 auto It = lower_bound(Attrs, A, AttributeComparator());
2363 if (It != Attrs.end() && It->hasAttribute(A))
2364 return *It;
2365 return {};
2366}
2367
2369 auto It = lower_bound(Attrs, A, AttributeComparator());
2370 if (It != Attrs.end() && It->hasAttribute(A))
2371 return *It;
2372 return {};
2373}
2374
2375std::optional<ConstantRange> AttrBuilder::getRange() const {
2376 const Attribute RangeAttr = getAttribute(Attribute::Range);
2377 if (RangeAttr.isValid())
2378 return RangeAttr.getRange();
2379 return std::nullopt;
2380}
2381
2383 return getAttribute(A).isValid();
2384}
2385
2387 return getAttribute(A).isValid();
2388}
2389
2391 return Attrs == B.Attrs;
2392}
2393
2394//===----------------------------------------------------------------------===//
2395// AttributeFuncs Function Defintions
2396//===----------------------------------------------------------------------===//
2397
2398/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2399/// follows the same type rules as FPMathOperator.
2402}
2403
2404/// Which attributes cannot be applied to a type.
2406 AttributeSafetyKind ASK) {
2407 AttributeMask Incompatible;
2408
2409 if (!Ty->isIntegerTy()) {
2410 // Attributes that only apply to integers.
2411 if (ASK & ASK_SAFE_TO_DROP)
2412 Incompatible.addAttribute(Attribute::AllocAlign);
2413 if (ASK & ASK_UNSAFE_TO_DROP)
2414 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2415 }
2416
2417 if (!Ty->isIntOrIntVectorTy()) {
2418 // Attributes that only apply to integers or vector of integers.
2419 if (ASK & ASK_SAFE_TO_DROP)
2420 Incompatible.addAttribute(Attribute::Range);
2421 } else {
2422 Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2423 if (RangeAttr.isValid() &&
2424 RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2425 Incompatible.addAttribute(Attribute::Range);
2426 }
2427
2428 if (!Ty->isPointerTy()) {
2429 // Attributes that only apply to pointers.
2430 if (ASK & ASK_SAFE_TO_DROP)
2431 Incompatible.addAttribute(Attribute::NoAlias)
2432 .addAttribute(Attribute::NonNull)
2433 .addAttribute(Attribute::ReadNone)
2434 .addAttribute(Attribute::ReadOnly)
2435 .addAttribute(Attribute::Dereferenceable)
2436 .addAttribute(Attribute::DereferenceableOrNull)
2437 .addAttribute(Attribute::Writable)
2438 .addAttribute(Attribute::DeadOnUnwind)
2439 .addAttribute(Attribute::Initializes)
2440 .addAttribute(Attribute::Captures)
2441 .addAttribute(Attribute::DeadOnReturn);
2442 if (ASK & ASK_UNSAFE_TO_DROP)
2443 Incompatible.addAttribute(Attribute::Nest)
2444 .addAttribute(Attribute::SwiftError)
2445 .addAttribute(Attribute::Preallocated)
2446 .addAttribute(Attribute::InAlloca)
2447 .addAttribute(Attribute::ByVal)
2448 .addAttribute(Attribute::StructRet)
2449 .addAttribute(Attribute::ByRef)
2450 .addAttribute(Attribute::ElementType)
2451 .addAttribute(Attribute::AllocatedPointer);
2452 }
2453
2454 // Attributes that only apply to pointers or vectors of pointers.
2455 if (!Ty->isPtrOrPtrVectorTy()) {
2456 if (ASK & ASK_SAFE_TO_DROP)
2457 Incompatible.addAttribute(Attribute::Alignment);
2458 }
2459
2460 if (ASK & ASK_SAFE_TO_DROP) {
2462 Incompatible.addAttribute(Attribute::NoFPClass);
2463 }
2464
2465 // Some attributes can apply to all "values" but there are no `void` values.
2466 if (Ty->isVoidTy()) {
2467 if (ASK & ASK_SAFE_TO_DROP)
2468 Incompatible.addAttribute(Attribute::NoUndef);
2469 }
2470
2471 return Incompatible;
2472}
2473
2475 AttributeMask AM;
2476 AM.addAttribute(Attribute::NoUndef);
2477 AM.addAttribute(Attribute::Dereferenceable);
2478 AM.addAttribute(Attribute::DereferenceableOrNull);
2479 return AM;
2480}
2481
2482/// Callees with dynamic denormal modes are compatible with any caller mode.
2483static bool denormModeCompatible(DenormalMode CallerMode,
2484 DenormalMode CalleeMode) {
2485 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2486 return true;
2487
2488 // If they don't exactly match, it's OK if the mismatched component is
2489 // dynamic.
2490 if (CalleeMode.Input == CallerMode.Input &&
2491 CalleeMode.Output == DenormalMode::Dynamic)
2492 return true;
2493
2494 if (CalleeMode.Output == CallerMode.Output &&
2495 CalleeMode.Input == DenormalMode::Dynamic)
2496 return true;
2497 return false;
2498}
2499
2500static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2501 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2502 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2503
2504 if (denormModeCompatible(CallerMode, CalleeMode)) {
2505 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2506 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2507 if (CallerModeF32 == DenormalMode::getInvalid())
2508 CallerModeF32 = CallerMode;
2509 if (CalleeModeF32 == DenormalMode::getInvalid())
2510 CalleeModeF32 = CalleeMode;
2511 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2512 }
2513
2514 return false;
2515}
2516
2517static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2518 // Do not inline strictfp function into non-strictfp one. It would require
2519 // conversion of all FP operations in host function to constrained intrinsics.
2520 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2521 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2522}
2523
2524template<typename AttrClass>
2525static bool isEqual(const Function &Caller, const Function &Callee) {
2526 return Caller.getFnAttribute(AttrClass::getKind()) ==
2527 Callee.getFnAttribute(AttrClass::getKind());
2528}
2529
2530static bool isEqual(const Function &Caller, const Function &Callee,
2531 const StringRef &AttrName) {
2532 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2533}
2534
2535/// Compute the logical AND of the attributes of the caller and the
2536/// callee.
2537///
2538/// This function sets the caller's attribute to false if the callee's attribute
2539/// is false.
2540template<typename AttrClass>
2541static void setAND(Function &Caller, const Function &Callee) {
2542 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2543 !AttrClass::isSet(Callee, AttrClass::getKind()))
2544 AttrClass::set(Caller, AttrClass::getKind(), false);
2545}
2546
2547/// Compute the logical OR of the attributes of the caller and the
2548/// callee.
2549///
2550/// This function sets the caller's attribute to true if the callee's attribute
2551/// is true.
2552template<typename AttrClass>
2553static void setOR(Function &Caller, const Function &Callee) {
2554 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2555 AttrClass::isSet(Callee, AttrClass::getKind()))
2556 AttrClass::set(Caller, AttrClass::getKind(), true);
2557}
2558
2559/// If the inlined function had a higher stack protection level than the
2560/// calling function, then bump up the caller's stack protection level.
2561static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2562 // If the calling function has *no* stack protection level (e.g. it was built
2563 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2564 // change it as that could change the program's semantics.
2565 if (!Caller.hasStackProtectorFnAttr())
2566 return;
2567
2568 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2569 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2570 // clutter to the IR.
2571 AttributeMask OldSSPAttr;
2572 OldSSPAttr.addAttribute(Attribute::StackProtect)
2573 .addAttribute(Attribute::StackProtectStrong)
2574 .addAttribute(Attribute::StackProtectReq);
2575
2576 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2577 Caller.removeFnAttrs(OldSSPAttr);
2578 Caller.addFnAttr(Attribute::StackProtectReq);
2579 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2580 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2581 Caller.removeFnAttrs(OldSSPAttr);
2582 Caller.addFnAttr(Attribute::StackProtectStrong);
2583 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2584 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2585 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2586 Caller.addFnAttr(Attribute::StackProtect);
2587}
2588
2589/// If the inlined function required stack probes, then ensure that
2590/// the calling function has those too.
2591static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2592 if (!Caller.hasFnAttribute("probe-stack") &&
2593 Callee.hasFnAttribute("probe-stack")) {
2594 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2595 }
2596}
2597
2598/// If the inlined function defines the size of guard region
2599/// on the stack, then ensure that the calling function defines a guard region
2600/// that is no larger.
2601static void
2603 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2604 if (CalleeAttr.isValid()) {
2605 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2606 if (CallerAttr.isValid()) {
2607 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2608 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2609 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2610
2611 if (CallerStackProbeSize > CalleeStackProbeSize) {
2612 Caller.addFnAttr(CalleeAttr);
2613 }
2614 } else {
2615 Caller.addFnAttr(CalleeAttr);
2616 }
2617 }
2618}
2619
2620/// If the inlined function defines a min legal vector width, then ensure
2621/// the calling function has the same or larger min legal vector width. If the
2622/// caller has the attribute, but the callee doesn't, we need to remove the
2623/// attribute from the caller since we can't make any guarantees about the
2624/// caller's requirements.
2625/// This function is called after the inlining decision has been made so we have
2626/// to merge the attribute this way. Heuristics that would use
2627/// min-legal-vector-width to determine inline compatibility would need to be
2628/// handled as part of inline cost analysis.
2629static void
2631 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2632 if (CallerAttr.isValid()) {
2633 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2634 if (CalleeAttr.isValid()) {
2635 uint64_t CallerVectorWidth, CalleeVectorWidth;
2636 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2637 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2638 if (CallerVectorWidth < CalleeVectorWidth)
2639 Caller.addFnAttr(CalleeAttr);
2640 } else {
2641 // If the callee doesn't have the attribute then we don't know anything
2642 // and must drop the attribute from the caller.
2643 Caller.removeFnAttr("min-legal-vector-width");
2644 }
2645 }
2646}
2647
2648/// If the inlined function has null_pointer_is_valid attribute,
2649/// set this attribute in the caller post inlining.
2650static void
2652 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2653 Caller.addFnAttr(Attribute::NullPointerIsValid);
2654 }
2655}
2656
2657struct EnumAttr {
2658 static bool isSet(const Function &Fn,
2659 Attribute::AttrKind Kind) {
2660 return Fn.hasFnAttribute(Kind);
2661 }
2662
2663 static void set(Function &Fn,
2664 Attribute::AttrKind Kind, bool Val) {
2665 if (Val)
2666 Fn.addFnAttr(Kind);
2667 else
2668 Fn.removeFnAttr(Kind);
2669 }
2670};
2671
2673 static bool isSet(const Function &Fn,
2674 StringRef Kind) {
2675 auto A = Fn.getFnAttribute(Kind);
2676 return A.getValueAsString() == "true";
2677 }
2678
2679 static void set(Function &Fn,
2680 StringRef Kind, bool Val) {
2681 Fn.addFnAttr(Kind, Val ? "true" : "false");
2682 }
2683};
2684
2685#define GET_ATTR_NAMES
2686#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2687 struct ENUM_NAME##Attr : EnumAttr { \
2688 static enum Attribute::AttrKind getKind() { \
2689 return llvm::Attribute::ENUM_NAME; \
2690 } \
2691 };
2692#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2693 struct ENUM_NAME##Attr : StrBoolAttr { \
2694 static StringRef getKind() { return #DISPLAY_NAME; } \
2695 };
2696#include "llvm/IR/Attributes.inc"
2697
2698#define GET_ATTR_COMPAT_FUNC
2699#include "llvm/IR/Attributes.inc"
2700
2702 const Function &Callee) {
2703 return hasCompatibleFnAttrs(Caller, Callee);
2704}
2705
2707 const Function &B) {
2708 return hasCompatibleFnAttrs(A, B);
2709}
2710
2712 const Function &Callee) {
2713 mergeFnAttrs(Caller, Callee);
2714}
2715
2717 const Function &ToMerge) {
2718
2719 // We merge functions so that they meet the most general case.
2720 // For example, if the NoNansFPMathAttr is set in one function, but not in
2721 // the other, in the merged function we can say that the NoNansFPMathAttr
2722 // is not set.
2723 // However if we have the SpeculativeLoadHardeningAttr set true in one
2724 // function, but not the other, we make sure that the function retains
2725 // that aspect in the merged function.
2726 mergeFnAttrs(Base, ToMerge);
2727}
2728
2730 uint64_t Width) {
2731 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2732 if (Attr.isValid()) {
2733 uint64_t OldWidth;
2734 Attr.getValueAsString().getAsInteger(0, OldWidth);
2735 if (Width > OldWidth)
2736 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2737 }
2738}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines various helper methods and classes used by LLVMContextImpl for creating and managin...
static void addAttributeImpl(SmallVectorImpl< Attribute > &Attrs, K Kind, Attribute Attr)
static void setAND(Function &Caller, const Function &Callee)
Compute the logical AND of the attributes of the caller and the callee.
static void adjustCallerStackProbes(Function &Caller, const Function &Callee)
If the inlined function required stack probes, then ensure that the calling function has those too.
static std::pair< unsigned, std::optional< unsigned > > unpackVScaleRangeArgs(uint64_t Value)
Definition: Attributes.cpp:87
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:760
@ RetAttr
Definition: Attributes.cpp:763
@ IntersectPreserve
Definition: Attributes.cpp:764
@ IntersectMin
Definition: Attributes.cpp:766
@ IntersectCustom
Definition: Attributes.cpp:767
@ ParamAttr
Definition: Attributes.cpp:762
@ FnAttr
Definition: Attributes.cpp:761
@ IntersectPropertyMask
Definition: Attributes.cpp:768
@ IntersectAnd
Definition: Attributes.cpp:765
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:61
static uint64_t packVScaleRangeArgs(unsigned MinValue, std::optional< unsigned > MaxValue)
Definition: Attributes.cpp:81
static bool hasIntersectProperty(Attribute::AttrKind Kind, AttributeProperty Prop)
Definition: Attributes.cpp:797
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:59
static std::pair< unsigned, std::optional< unsigned > > unpackAllocSizeArgs(uint64_t Num)
Definition: Attributes.cpp:71
static bool checkDenormMode(const Function &Caller, const Function &Callee)
static unsigned getAttributeProperties(Attribute::AttrKind Kind)
Definition: Attributes.cpp:774
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:780
static const char * getModRefStr(ModRefInfo MR)
Definition: Attributes.cpp:522
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:638
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file contains some templates that are useful if you are working with the STL at all.
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...
LLVM_ABI void Profile(FoldingSetNodeID &id) const
Used to insert APInt objects, or objects that contain APInt objects, into FoldingSets.
Definition: APInt.cpp:156
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
const T & back() const
back - Get the last element.
Definition: ArrayRef.h:156
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition: ArrayRef.h:224
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:147
iterator begin() const
Definition: ArrayRef.h:135
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:142
LLVM_ABI AttrBuilder & addStructRetAttr(Type *Ty)
This turns a sret type into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addAlignmentAttr(MaybeAlign Align)
This turns an alignment into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addVScaleRangeAttrFromRawRepr(uint64_t RawVScaleRangeRepr)
Add a vscale_range attribute, using the representation returned by Attribute.getIntValue().
LLVM_ABI void clear()
LLVM_ABI std::optional< uint64_t > getRawIntAttr(Attribute::AttrKind Kind) const
Return raw (possibly packed/encoded) value of integer attribute or std::nullopt if not set.
LLVM_ABI AttrBuilder & addAllocKindAttr(AllocFnKind Kind)
LLVM_ABI Attribute getAttribute(Attribute::AttrKind Kind) const
Return Attribute with the given Kind.
LLVM_ABI AttrBuilder & addByRefAttr(Type *Ty)
This turns a byref type into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addNoFPClassAttr(FPClassTest NoFPClassMask)
LLVM_ABI AttrBuilder & addCapturesAttr(CaptureInfo CI)
Add captures attribute.
LLVM_ABI bool overlaps(const AttributeMask &AM) const
Return true if the builder has any attribute that's in the specified builder.
LLVM_ABI AttrBuilder & merge(const AttrBuilder &B)
Add the attributes from the builder.
LLVM_ABI 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:1087
LLVM_ABI AttrBuilder & addRawIntAttr(Attribute::AttrKind Kind, uint64_t Value)
Add integer attribute with raw value (packed/encoded if necessary).
LLVM_ABI AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
LLVM_ABI AttrBuilder & addByValAttr(Type *Ty)
This turns a byval type into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addDereferenceableAttr(uint64_t Bytes)
This turns the number of dereferenceable bytes into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addInitializesAttr(const ConstantRangeList &CRL)
Add initializes attribute.
LLVM_ABI bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
LLVM_ABI AttrBuilder & addMemoryAttr(MemoryEffects ME)
Add memory effect attribute.
LLVM_ABI AttrBuilder & addConstantRangeListAttr(Attribute::AttrKind Kind, ArrayRef< ConstantRange > Val)
Add a ConstantRangeList attribute with the given ranges.
LLVM_ABI AttrBuilder & addConstantRangeAttr(Attribute::AttrKind Kind, const ConstantRange &CR)
Add a ConstantRange attribute with the given range.
LLVM_ABI AttrBuilder & addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr)
Add an allocsize attribute, using the representation returned by Attribute.getIntValue().
LLVM_ABI AttrBuilder & addPreallocatedAttr(Type *Ty)
This turns a preallocated type into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addStackAlignmentAttr(MaybeAlign Align)
This turns a stack alignment into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addInAllocaAttr(Type *Ty)
This turns an inalloca type into the form used internally in Attribute.
LLVM_ABI AttrBuilder & removeAttribute(Attribute::AttrKind Val)
Remove an attribute from the builder.
LLVM_ABI bool operator==(const AttrBuilder &B) const
LLVM_ABI Type * getTypeAttr(Attribute::AttrKind Kind) const
Retrieve type for the given type attribute.
LLVM_ABI AttrBuilder & remove(const AttributeMask &AM)
Remove the attributes from the builder.
LLVM_ABI AttrBuilder & addFromEquivalentMetadata(const Instruction &I)
Add 0 or more parameter attributes which are equivalent to metadata attached to I.
LLVM_ABI std::optional< ConstantRange > getRange() const
Retrieve the range if the attribute exists (std::nullopt is returned otherwise).
LLVM_ABI AttrBuilder & addDereferenceableOrNullAttr(uint64_t Bytes)
This turns the number of dereferenceable_or_null bytes into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addTypeAttr(Attribute::AttrKind Kind, Type *Ty)
Add a type attribute with the given type.
LLVM_ABI std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
Retrieve the allocsize args, or std::nullopt if the attribute does not exist.
LLVM_ABI AttrBuilder & addAllocSizeAttr(unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
This turns one (or two) ints into the form used internally in Attribute.
LLVM_ABI AttrBuilder & addRangeAttr(const ConstantRange &CR)
Add range attribute.
LLVM_ABI 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
int cmp(const AttributeImpl &AI, bool KindOnly) const
Used to sort attributes.
Definition: Attributes.cpp:878
bool isConstantRangeAttribute() const
Definition: AttributeImpl.h:66
bool hasAttribute(Attribute::AttrKind A) const
Definition: Attributes.cpp:825
void Profile(FoldingSetNodeID &ID) const
Definition: AttributeImpl.h:95
Type * getValueAsType() const
Definition: Attributes.cpp:861
Attribute::AttrKind getKindAsEnum() const
Definition: Attributes.cpp:835
bool operator<(const AttributeImpl &AI) const
Used when sorting the attributes.
Definition: Attributes.cpp:913
uint64_t getValueAsInt() const
Definition: Attributes.cpp:841
bool isIntAttribute() const
Definition: AttributeImpl.h:63
bool isTypeAttribute() const
Definition: AttributeImpl.h:65
bool getValueAsBool() const
Definition: Attributes.cpp:846
StringRef getKindAsString() const
Definition: Attributes.cpp:851
StringRef getValueAsString() const
Definition: Attributes.cpp:856
bool isEnumAttribute() const
Definition: AttributeImpl.h:62
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Definition: Attributes.cpp:872
bool isConstantRangeListAttribute() const
Definition: AttributeImpl.h:69
bool isStringAttribute() const
Definition: AttributeImpl.h:64
const ConstantRange & getValueAsConstantRange() const
Definition: Attributes.cpp:866
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
LLVM_ABI bool hasAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
LLVM_ABI Type * getParamStructRetType(unsigned ArgNo) const
Return the sret type for the specified function parameter.
LLVM_ABI AttributeList addDereferenceableParamAttr(LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const
Add the dereferenceable attribute to the attribute set at the given arg index.
LLVM_ABI AttributeList removeAttributeAtIndex(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Remove the specified attribute at the specified index from this attribute list.
LLVM_ABI AttributeList addRangeRetAttr(LLVMContext &C, const ConstantRange &CR) const
Add the range attribute to the attribute set at the return value index.
LLVM_ABI bool hasAttributesAtIndex(unsigned Index) const
Return true if attribute exists at the given index.
friend class AttributeListImpl
Definition: Attributes.h:520
LLVM_ABI AttributeSet getFnAttrs() const
The function attributes are returned.
index_iterator indexes() const
Use this to iterate over the valid attribute indexes.
Definition: Attributes.h:1031
LLVM_ABI 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:521
AttributeList()=default
LLVM_ABI iterator begin() const
LLVM_ABI 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:640
LLVM_ABI void print(raw_ostream &O) const
LLVM_ABI AttributeList addDereferenceableRetAttr(LLVMContext &C, uint64_t Bytes) const
Add the dereferenceable attribute to the attribute set at the given index.
static LLVM_ABI AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
LLVM_ABI AllocFnKind getAllocKind() const
bool isEmpty() const
Return true if there are no attributes.
Definition: Attributes.h:1043
LLVM_ABI AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
friend class AttrBuilder
Definition: Attributes.h:519
LLVM_ABI bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
LLVM_ABI uint64_t getParamDereferenceableBytes(unsigned Index) const
Get the number of dereferenceable bytes (or zero if unknown) of an arg.
LLVM_ABI MaybeAlign getParamAlignment(unsigned ArgNo) const
Return the alignment for the specified function parameter.
LLVM_ABI 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.
LLVM_ABI iterator end() const
LLVM_ABI Type * getParamInAllocaType(unsigned ArgNo) const
Return the inalloca type for the specified function parameter.
LLVM_ABI unsigned getNumAttrSets() const
LLVM_ABI FPClassTest getRetNoFPClass() const
Get the disallowed floating-point classes of the return value.
LLVM_ABI std::string getAsString(unsigned Index, bool InAttrGrp=false) const
Return the attributes at the index as a string.
LLVM_ABI UWTableKind getUWTableKind() const
Get the unwind table kind requested for the function.
LLVM_ABI MaybeAlign getRetAlignment() const
Return the alignment of the return value.
LLVM_ABI Type * getParamElementType(unsigned ArgNo) const
Return the elementtype type for the specified function parameter.
LLVM_ABI Attribute getAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const
Return the attribute object that exists at the given index.
LLVM_ABI Type * getParamPreallocatedType(unsigned ArgNo) const
Return the preallocated type for the specified function parameter.
LLVM_ABI bool hasParentContext(LLVMContext &C) const
Return true if this attribute list belongs to the LLVMContext.
const AttributeSet * iterator
Definition: Attributes.h:999
LLVM_ABI MaybeAlign getFnStackAlignment() const
Get the stack alignment of the function.
LLVM_ABI AttributeList addAttributesAtIndex(LLVMContext &C, unsigned Index, const AttrBuilder &B) const
Add attributes to the attribute set at the given index.
LLVM_ABI Type * getParamByValType(unsigned ArgNo) const
Return the byval type for the specified function parameter.
LLVM_ABI MaybeAlign getParamStackAlignment(unsigned ArgNo) const
Return the stack alignment for the specified function parameter.
LLVM_ABI uint64_t getRetDereferenceableBytes() const
Get the number of dereferenceable bytes (or zero if unknown) of the return value.
LLVM_ABI AttributeList addAllocSizeParamAttr(LLVMContext &C, unsigned ArgNo, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg) const
Add the allocsize attribute to the attribute set at the given arg index.
LLVM_ABI uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const
Get the number of dereferenceable_or_null bytes (or zero if unknown) of an arg.
LLVM_ABI 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.
LLVM_ABI AttributeSet getAttributes(unsigned Index) const
The attributes for the specified index are returned.
LLVM_ABI FPClassTest getParamNoFPClass(unsigned ArgNo) const
Get the disallowed floating-point classes of the argument value.
LLVM_ABI std::optional< AttributeList > intersectWith(LLVMContext &C, AttributeList Other) const
Try to intersect this AttributeList with Other.
LLVM_ABI Type * getParamByRefType(unsigned ArgNo) const
Return the byref type for the specified function parameter.
LLVM_ABI AttributeList addAttributeAtIndex(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Add an attribute to the attribute set at the given index.
LLVM_ABI 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:668
LLVM_ABI std::optional< ConstantRange > getParamRange(unsigned ArgNo) const
Get range (or std::nullopt if unknown) of an arg.
LLVM_ABI uint64_t getRetDereferenceableOrNullBytes() const
Get the number of dereferenceable_or_null bytes (or zero if unknown) of the return value.
LLVM_ABI void dump() const
AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const
Add an argument attribute to the list.
Definition: Attributes.h:648
LLVM_ABI 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
CaptureInfo getCaptureInfo() const
unsigned getVScaleRangeMin() const
MaybeAlign getAlignment() const
MemoryEffects getMemoryEffects() const
iterator begin() const
UWTableKind getUWTableKind() const
std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
iterator end() const
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
LLVM_ABI AllocFnKind getAllocKind() const
bool hasAttributes() const
Return true if attributes exists in this set.
Definition: Attributes.h:431
LLVM_ABI AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Remove the specified attribute from this set.
Definition: Attributes.cpp:970
LLVM_ABI Type * getInAllocaType() const
LLVM_ABI Type * getByValType() const
LLVM_ABI AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
Definition: Attributes.cpp:944
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
LLVM_ABI std::optional< AttributeSet > intersectWith(LLVMContext &C, AttributeSet Other) const
Try to intersect this AttributeSet with Other.
Definition: Attributes.cpp:998
LLVM_ABI Type * getStructRetType() const
LLVM_ABI std::string getAsString(bool InAttrGrp=false) const
LLVM_ABI unsigned getVScaleRangeMin() const
LLVM_ABI std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
LLVM_ABI UWTableKind getUWTableKind() const
LLVM_ABI bool hasParentContext(LLVMContext &C) const
Return true if this attribute set belongs to the LLVMContext.
LLVM_ABI iterator begin() const
LLVM_ABI iterator end() const
LLVM_ABI AttributeSet removeAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const
Remove the specified attributes from this set.
Definition: Attributes.cpp:986
LLVM_ABI std::optional< unsigned > getVScaleRangeMax() const
LLVM_ABI MaybeAlign getStackAlignment() const
LLVM_ABI Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
LLVM_ABI Type * getPreallocatedType() const
LLVM_ABI uint64_t getDereferenceableBytes() const
LLVM_ABI MaybeAlign getAlignment() const
LLVM_ABI FPClassTest getNoFPClass() const
LLVM_ABI Type * getElementType() const
LLVM_ABI Type * getByRefType() const
LLVM_ABI CaptureInfo getCaptureInfo() const
AttributeSet()=default
AttributeSet is a trivially copyable value type.
static LLVM_ABI AttributeSet get(LLVMContext &C, const AttrBuilder &B)
Definition: Attributes.cpp:921
LLVM_ABI uint64_t getDereferenceableOrNullBytes() const
LLVM_ABI unsigned getNumAttributes() const
Return the number of attributes in this set.
LLVM_ABI AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
Definition: Attributes.cpp:929
void dump() const
LLVM_ABI bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
Definition: Attributes.cpp:356
static LLVM_ABI Attribute getWithStructRetType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:260
static LLVM_ABI Attribute::AttrKind getAttrKindFromName(StringRef AttrName)
Definition: Attributes.cpp:313
LLVM_ABI bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
Definition: Attributes.cpp:348
static LLVM_ABI Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment)
Definition: Attributes.cpp:239
LLVM_ABI const ConstantRange & getRange() const
Returns the value of the range attribute.
Definition: Attributes.cpp:510
static LLVM_ABI bool intersectWithCustom(AttrKind Kind)
Definition: Attributes.cpp:817
LLVM_ABI bool isIntAttribute() const
Return true if the attribute is an integer attribute.
Definition: Attributes.cpp:352
static LLVM_ABI Attribute getWithByRefType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:264
LLVM_ABI std::optional< unsigned > getVScaleRangeMax() const
Returns the maximum value for the vscale_range attribute or std::nullopt when unknown.
Definition: Attributes.cpp:474
LLVM_ABI uint64_t getValueAsInt() const
Return the attribute's value as an integer.
Definition: Attributes.cpp:379
LLVM_ABI unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
Definition: Attributes.cpp:468
LLVM_ABI AllocFnKind getAllocKind() const
Definition: Attributes.cpp:486
LLVM_ABI bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
Definition: Attributes.cpp:364
static LLVM_ABI Attribute getWithAllocKind(LLVMContext &Context, AllocFnKind Kind)
Definition: Attributes.cpp:303
LLVM_ABI StringRef getKindAsString() const
Return the attribute's kind as a string.
Definition: Attributes.cpp:393
static LLVM_ABI Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:268
static LLVM_ABI bool intersectWithMin(AttrKind Kind)
Definition: Attributes.cpp:814
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
Definition: Attributes.cpp:95
static LLVM_ABI bool canUseAsRetAttr(AttrKind Kind)
Definition: Attributes.cpp:793
static bool isTypeAttrKind(AttrKind Kind)
Definition: Attributes.h:107
LLVM_ABI std::string getAsString(bool InAttrGrp=false) const
The Attribute is converted to a string of equivalent mnemonic.
Definition: Attributes.cpp:536
LLVM_ABI uint64_t getDereferenceableOrNullBytes() const
Returns the number of dereferenceable_or_null bytes from the dereferenceable_or_null attribute.
Definition: Attributes.cpp:454
static LLVM_ABI Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
Definition: Attributes.cpp:244
LLVM_ABI std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
Definition: Attributes.cpp:462
static LLVM_ABI Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind)
Definition: Attributes.cpp:276
LLVM_ABI FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
Definition: Attributes.cpp:504
static LLVM_ABI Attribute getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
Definition: Attributes.cpp:296
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
Definition: Attributes.cpp:372
Attribute()=default
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
Definition: Attributes.cpp:386
LLVM_ABI ArrayRef< ConstantRange > getInitializes() const
Returns the value of the initializes attribute.
Definition: Attributes.cpp:516
LLVM_ABI const ConstantRange & getValueAsConstantRange() const
Return the attribute's value as a ConstantRange.
Definition: Attributes.cpp:414
LLVM_ABI uint64_t getDereferenceableBytes() const
Returns the number of dereferenceable bytes from the dereferenceable attribute.
Definition: Attributes.cpp:447
static LLVM_ABI Attribute getWithVScaleRangeArgs(LLVMContext &Context, unsigned MinValue, unsigned MaxValue)
Definition: Attributes.cpp:307
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
Definition: Attributes.cpp:492
LLVM_ABI void Profile(FoldingSetNodeID &ID) const
Definition: Attributes.cpp:756
LLVM_ABI UWTableKind getUWTableKind() const
Definition: Attributes.cpp:480
static LLVM_ABI Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, uint64_t Bytes)
Definition: Attributes.cpp:250
LLVM_ABI ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
Definition: Attributes.cpp:420
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:400
static LLVM_ABI bool isExistingAttribute(StringRef Name)
Return true if the provided string matches the IR name of an attribute.
Definition: Attributes.cpp:336
bool hasKindAsEnum() const
Returns true if the attribute's kind can be represented as an enum (Enum, Integer,...
Definition: Attributes.h:233
static LLVM_ABI StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind)
Definition: Attributes.cpp:322
static LLVM_ABI bool canUseAsFnAttr(AttrKind Kind)
Definition: Attributes.cpp:785
static LLVM_ABI bool intersectWithAnd(AttrKind Kind)
Definition: Attributes.cpp:811
static LLVM_ABI Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
Definition: Attributes.cpp:286
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition: Attributes.h:88
@ None
No attributes have been set.
Definition: Attributes.h:90
@ EndAttrKinds
Sentinel value useful for loops.
Definition: Attributes.h:93
static bool isConstantRangeAttrKind(AttrKind Kind)
Definition: Attributes.h:110
LLVM_ABI bool hasParentContext(LLVMContext &C) const
Return true if this attribute belongs to the LLVMContext.
Definition: Attributes.cpp:731
LLVM_ABI bool isTypeAttribute() const
Return true if the attribute is a type attribute.
Definition: Attributes.cpp:360
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
Definition: Attributes.cpp:291
static LLVM_ABI Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:272
static bool isIntAttrKind(AttrKind Kind)
Definition: Attributes.h:104
static bool isConstantRangeListAttrKind(AttrKind Kind)
Definition: Attributes.h:113
LLVM_ABI bool isConstantRangeListAttribute() const
Return true if the attribute is a ConstantRangeList attribute.
Definition: Attributes.cpp:368
static LLVM_ABI Attribute getWithByValType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:256
LLVM_ABI bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
Definition: Attributes.cpp:426
static bool isEnumAttrKind(AttrKind Kind)
Definition: Attributes.h:101
static LLVM_ABI Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
Definition: Attributes.cpp:281
static LLVM_ABI bool canUseAsParamAttr(AttrKind Kind)
Definition: Attributes.cpp:789
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:223
LLVM_ABI MaybeAlign getStackAlignment() const
Returns the stack alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:441
LLVM_ABI MaybeAlign getAlignment() const
Returns the alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:435
LLVM_ABI CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
Definition: Attributes.cpp:498
static LLVM_ABI bool intersectMustPreserve(AttrKind Kind)
Definition: Attributes.cpp:808
LLVM_ABI int cmpKind(Attribute A) const
Used to sort attribute by kind.
Definition: Attributes.cpp:739
LLVM_ABI bool operator<(Attribute A) const
Less-than operator. Useful for sorting the attributes list.
Definition: Attributes.cpp:749
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
Definition: Attributes.cpp:234
LLVM_ABI Type * getValueAsType() const
Return the attribute's value as a Type.
Definition: Attributes.cpp:407
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
Definition: Allocator.h:149
Represents which components of the pointer may be captured in which location.
Definition: ModRef.h:354
static CaptureInfo createFromIntValue(uint32_t Data)
Definition: ModRef.h:425
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
Definition: ModRef.h:370
uint32_t toIntValue() const
Convert CaptureInfo into an encoded integer value (used by captures attribute).
Definition: ModRef.h:432
This is the shared class of boolean and integer constants.
Definition: Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:163
static size_t totalSizeToAlloc(ArrayRef< ConstantRange > Val)
This class represents a list of constant ranges.
ArrayRef< ConstantRange > rangesRef() const
LLVM_ABI void print(raw_ostream &OS) const
Print out the ranges to a stream.
This class represents a range of values.
Definition: ConstantRange.h:47
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI ConstantRange unionWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the union of this range with another range.
uint32_t getBitWidth() const
Get the bit width of this ConstantRange.
static bool isSupportedFloatingPointType(Type *Ty)
Returns true if Ty is a supported floating-point type for phi, select, or call FPMathOperators.
Definition: Operator.h:344
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
Definition: FoldingSet.h:330
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition: Function.cpp:637
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition: Function.cpp:762
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition: Function.cpp:685
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:727
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:68
Metadata node.
Definition: Metadata.h:1077
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition: ModRef.h:188
static MemoryEffectsBase createFromIntValue(uint32_t Data)
Create MemoryEffectsBase from an encoded integer value (used by memory attribute).
Definition: ModRef.h:177
static auto locations()
Returns iterator over all supported location kinds.
Definition: ModRef.h:98
uint32_t toIntValue() const
Convert MemoryEffectsBase into an encoded integer value (used by memory attribute).
Definition: ModRef.h:183
static MemoryEffectsBase unknown()
Create MemoryEffectsBase that can read and write any memory.
Definition: ModRef.h:115
size_t size() const
Definition: SmallVector.h:79
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
void reserve(size_type N)
Definition: SmallVector.h:664
void resize(size_type N)
Definition: SmallVector.h:639
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
static size_t totalSizeToAlloc(StringRef Kind, StringRef Val)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:480
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:233
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:151
int compare(StringRef RHS) const
compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...
Definition: StringRef.h:187
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
R Default(T Value)
Definition: StringSwitch.h:177
const T * getTrailingObjects() const
Returns a pointer to the trailing object array of the given type (which must be one of those specifie...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
Definition: Type.h:246
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:267
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
Definition: Type.h:270
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:240
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:139
LLVM Value Representation.
Definition: Value.h:75
static constexpr uint64_t MaximumAlignment
Definition: Value.h:830
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:662
This class provides various memory handling functions that manipulate MemoryBlock instances.
Definition: Memory.h:54
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI bool areInlineCompatible(const Function &Caller, const Function &Callee)
LLVM_ABI AttributeMask getUBImplyingAttributes()
Get param/return attributes which imply immediate undefined behavior if an invalid value is passed.
LLVM_ABI bool isNoFPClassCompatibleType(Type *Ty)
Returns true if this is a type legal for the 'nofpclass' attribute.
LLVM_ABI bool areOutlineCompatible(const Function &A, const Function &B)
Checks if there are any incompatible function attributes between A and B.
LLVM_ABI void updateMinLegalVectorWidthAttr(Function &Fn, uint64_t Width)
Update min-legal-vector-width if it is in Attribute and less than Width.
LLVM_ABI void mergeAttributesForOutlining(Function &Base, const Function &ToMerge)
Merges the functions attributes from ToMerge into function Base.
LLVM_ABI AttributeMask typeIncompatible(Type *Ty, AttributeSet AS, AttributeSafetyKind ASK=ASK_ALL)
Which attributes cannot be applied to a type.
LLVM_ABI void mergeAttributesForInlining(Function &Caller, const Function &Callee)
Merge caller's and callee's attributes.
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:1744
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:1702
AllocFnKind
Definition: Attributes.h:51
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2155
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1751
UWTableKind
Definition: CodeGen.h:148
@ None
No unwind table requested.
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1669
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1758
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:1939
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
Definition: ModRef.h:28
@ Ref
The access may reference the value stored in memory.
@ 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.
@ ErrnoMem
Errno 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:2013
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1854
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:2139
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:853
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
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition: Alignment.h:141
Function object to check whether the first component of a container supported by std::get (like std::...
Definition: STLExtras.h:1472