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