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