1 //===- Attributes.cpp - Implement AttributesList --------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 // This file implements the Attribute, AttributeImpl, AttrBuilder,
11 // AttributeListImpl, and AttributeList classes.
13 //===----------------------------------------------------------------------===//
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"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/Config/llvm-config.h"
26 #include "llvm/IR/AttributeMask.h"
27 #include "llvm/IR/ConstantRange.h"
28 #include "llvm/IR/ConstantRangeList.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"
33 #include "llvm/Support/Compiler.h"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Support/ModRef.h"
36 #include "llvm/Support/raw_ostream.h"
49 //===----------------------------------------------------------------------===//
50 // Attribute Construction Methods
51 //===----------------------------------------------------------------------===//
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
57 // In order to do this, we need to reserve one value of the second (optional)
58 // allocsize argument to signify "not present."
59 static const unsigned AllocSizeNumElemsNotPresent
= -1;
61 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg
,
62 const std::optional
<unsigned> &NumElemsArg
) {
63 assert((!NumElemsArg
|| *NumElemsArg
!= AllocSizeNumElemsNotPresent
) &&
64 "Attempting to pack a reserved value");
66 return uint64_t(ElemSizeArg
) << 32 |
67 NumElemsArg
.value_or(AllocSizeNumElemsNotPresent
);
70 static std::pair
<unsigned, std::optional
<unsigned>>
71 unpackAllocSizeArgs(uint64_t Num
) {
72 unsigned NumElems
= Num
& std::numeric_limits
<unsigned>::max();
73 unsigned ElemSizeArg
= Num
>> 32;
75 std::optional
<unsigned> NumElemsArg
;
76 if (NumElems
!= AllocSizeNumElemsNotPresent
)
77 NumElemsArg
= NumElems
;
78 return std::make_pair(ElemSizeArg
, NumElemsArg
);
81 static uint64_t packVScaleRangeArgs(unsigned MinValue
,
82 std::optional
<unsigned> MaxValue
) {
83 return uint64_t(MinValue
) << 32 | MaxValue
.value_or(0);
86 static std::pair
<unsigned, std::optional
<unsigned>>
87 unpackVScaleRangeArgs(uint64_t Value
) {
88 unsigned MaxValue
= Value
& std::numeric_limits
<unsigned>::max();
89 unsigned MinValue
= Value
>> 32;
91 return std::make_pair(MinValue
,
92 MaxValue
> 0 ? MaxValue
: std::optional
<unsigned>());
95 Attribute
Attribute::get(LLVMContext
&Context
, Attribute::AttrKind Kind
,
97 bool IsIntAttr
= Attribute::isIntAttrKind(Kind
);
98 assert((IsIntAttr
|| Attribute::isEnumAttrKind(Kind
)) &&
99 "Not an enum or int attribute");
101 LLVMContextImpl
*pImpl
= Context
.pImpl
;
107 assert(Val
== 0 && "Value must be zero for enum attributes");
110 AttributeImpl
*PA
= pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, InsertPoint
);
113 // If we didn't find any existing attributes of the same shape then create a
114 // new one and insert it.
116 PA
= new (pImpl
->Alloc
) EnumAttributeImpl(Kind
);
118 PA
= new (pImpl
->Alloc
) IntAttributeImpl(Kind
, Val
);
119 pImpl
->AttrsSet
.InsertNode(PA
, InsertPoint
);
122 // Return the Attribute that we found or created.
123 return Attribute(PA
);
126 Attribute
Attribute::get(LLVMContext
&Context
, StringRef Kind
, StringRef Val
) {
127 LLVMContextImpl
*pImpl
= Context
.pImpl
;
130 if (!Val
.empty()) ID
.AddString(Val
);
133 AttributeImpl
*PA
= pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, InsertPoint
);
136 // If we didn't find any existing attributes of the same shape then create a
137 // new one and insert it.
139 pImpl
->Alloc
.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind
, Val
),
140 alignof(StringAttributeImpl
));
141 PA
= new (Mem
) StringAttributeImpl(Kind
, Val
);
142 pImpl
->AttrsSet
.InsertNode(PA
, InsertPoint
);
145 // Return the Attribute that we found or created.
146 return Attribute(PA
);
149 Attribute
Attribute::get(LLVMContext
&Context
, Attribute::AttrKind Kind
,
151 assert(Attribute::isTypeAttrKind(Kind
) && "Not a type attribute");
152 LLVMContextImpl
*pImpl
= Context
.pImpl
;
158 AttributeImpl
*PA
= pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, InsertPoint
);
161 // If we didn't find any existing attributes of the same shape then create a
162 // new one and insert it.
163 PA
= new (pImpl
->Alloc
) TypeAttributeImpl(Kind
, Ty
);
164 pImpl
->AttrsSet
.InsertNode(PA
, InsertPoint
);
167 // Return the Attribute that we found or created.
168 return Attribute(PA
);
171 Attribute
Attribute::get(LLVMContext
&Context
, Attribute::AttrKind Kind
,
172 const ConstantRange
&CR
) {
173 assert(Attribute::isConstantRangeAttrKind(Kind
) &&
174 "Not a ConstantRange attribute");
175 assert(!CR
.isFullSet() && "ConstantRange attribute must not be full");
176 LLVMContextImpl
*pImpl
= Context
.pImpl
;
179 CR
.getLower().Profile(ID
);
180 CR
.getUpper().Profile(ID
);
183 AttributeImpl
*PA
= pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, InsertPoint
);
186 // If we didn't find any existing attributes of the same shape then create a
187 // new one and insert it.
188 PA
= new (pImpl
->ConstantRangeAttributeAlloc
.Allocate())
189 ConstantRangeAttributeImpl(Kind
, CR
);
190 pImpl
->AttrsSet
.InsertNode(PA
, InsertPoint
);
193 // Return the Attribute that we found or created.
194 return Attribute(PA
);
197 Attribute
Attribute::get(LLVMContext
&Context
, Attribute::AttrKind Kind
,
198 ArrayRef
<ConstantRange
> Val
) {
199 assert(Attribute::isConstantRangeListAttrKind(Kind
) &&
200 "Not a ConstantRangeList attribute");
201 LLVMContextImpl
*pImpl
= Context
.pImpl
;
204 ID
.AddInteger(Val
.size());
205 for (auto &CR
: Val
) {
206 CR
.getLower().Profile(ID
);
207 CR
.getUpper().Profile(ID
);
211 AttributeImpl
*PA
= pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, InsertPoint
);
214 // If we didn't find any existing attributes of the same shape then create a
215 // new one and insert it.
216 // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
217 // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
218 // allocation and record the allocated pointer in
219 // `ConstantRangeListAttributes`. LLVMContext destructor will call the
220 // destructor of the allocated pointer explicitly.
221 void *Mem
= pImpl
->Alloc
.Allocate(
222 ConstantRangeListAttributeImpl::totalSizeToAlloc(Val
),
223 alignof(ConstantRangeListAttributeImpl
));
224 PA
= new (Mem
) ConstantRangeListAttributeImpl(Kind
, Val
);
225 pImpl
->AttrsSet
.InsertNode(PA
, InsertPoint
);
226 pImpl
->ConstantRangeListAttributes
.push_back(
227 reinterpret_cast<ConstantRangeListAttributeImpl
*>(PA
));
230 // Return the Attribute that we found or created.
231 return Attribute(PA
);
234 Attribute
Attribute::getWithAlignment(LLVMContext
&Context
, Align A
) {
235 assert(A
<= llvm::Value::MaximumAlignment
&& "Alignment too large.");
236 return get(Context
, Alignment
, A
.value());
239 Attribute
Attribute::getWithStackAlignment(LLVMContext
&Context
, Align A
) {
240 assert(A
<= 0x100 && "Alignment too large.");
241 return get(Context
, StackAlignment
, A
.value());
244 Attribute
Attribute::getWithDereferenceableBytes(LLVMContext
&Context
,
246 assert(Bytes
&& "Bytes must be non-zero.");
247 return get(Context
, Dereferenceable
, Bytes
);
250 Attribute
Attribute::getWithDereferenceableOrNullBytes(LLVMContext
&Context
,
252 assert(Bytes
&& "Bytes must be non-zero.");
253 return get(Context
, DereferenceableOrNull
, Bytes
);
256 Attribute
Attribute::getWithByValType(LLVMContext
&Context
, Type
*Ty
) {
257 return get(Context
, ByVal
, Ty
);
260 Attribute
Attribute::getWithStructRetType(LLVMContext
&Context
, Type
*Ty
) {
261 return get(Context
, StructRet
, Ty
);
264 Attribute
Attribute::getWithByRefType(LLVMContext
&Context
, Type
*Ty
) {
265 return get(Context
, ByRef
, Ty
);
268 Attribute
Attribute::getWithPreallocatedType(LLVMContext
&Context
, Type
*Ty
) {
269 return get(Context
, Preallocated
, Ty
);
272 Attribute
Attribute::getWithInAllocaType(LLVMContext
&Context
, Type
*Ty
) {
273 return get(Context
, InAlloca
, Ty
);
276 Attribute
Attribute::getWithUWTableKind(LLVMContext
&Context
,
278 return get(Context
, UWTable
, uint64_t(Kind
));
281 Attribute
Attribute::getWithMemoryEffects(LLVMContext
&Context
,
283 return get(Context
, Memory
, ME
.toIntValue());
286 Attribute
Attribute::getWithNoFPClass(LLVMContext
&Context
,
287 FPClassTest ClassMask
) {
288 return get(Context
, NoFPClass
, ClassMask
);
292 Attribute::getWithAllocSizeArgs(LLVMContext
&Context
, unsigned ElemSizeArg
,
293 const std::optional
<unsigned> &NumElemsArg
) {
294 assert(!(ElemSizeArg
== 0 && NumElemsArg
&& *NumElemsArg
== 0) &&
295 "Invalid allocsize arguments -- given allocsize(0, 0)");
296 return get(Context
, AllocSize
, packAllocSizeArgs(ElemSizeArg
, NumElemsArg
));
299 Attribute
Attribute::getWithVScaleRangeArgs(LLVMContext
&Context
,
302 return get(Context
, VScaleRange
, packVScaleRangeArgs(MinValue
, MaxValue
));
305 Attribute::AttrKind
Attribute::getAttrKindFromName(StringRef AttrName
) {
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"
311 .Default(Attribute::None
);
314 StringRef
Attribute::getNameFromAttrKind(Attribute::AttrKind 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
:
324 llvm_unreachable("invalid Kind");
328 bool Attribute::isExistingAttribute(StringRef Name
) {
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"
336 //===----------------------------------------------------------------------===//
337 // Attribute Accessor Methods
338 //===----------------------------------------------------------------------===//
340 bool Attribute::isEnumAttribute() const {
341 return pImpl
&& pImpl
->isEnumAttribute();
344 bool Attribute::isIntAttribute() const {
345 return pImpl
&& pImpl
->isIntAttribute();
348 bool Attribute::isStringAttribute() const {
349 return pImpl
&& pImpl
->isStringAttribute();
352 bool Attribute::isTypeAttribute() const {
353 return pImpl
&& pImpl
->isTypeAttribute();
356 bool Attribute::isConstantRangeAttribute() const {
357 return pImpl
&& pImpl
->isConstantRangeAttribute();
360 bool Attribute::isConstantRangeListAttribute() const {
361 return pImpl
&& pImpl
->isConstantRangeListAttribute();
364 Attribute::AttrKind
Attribute::getKindAsEnum() const {
365 if (!pImpl
) return None
;
366 assert(hasKindAsEnum() &&
367 "Invalid attribute type to get the kind as an enum!");
368 return pImpl
->getKindAsEnum();
371 uint64_t Attribute::getValueAsInt() const {
372 if (!pImpl
) return 0;
373 assert(isIntAttribute() &&
374 "Expected the attribute to be an integer attribute!");
375 return pImpl
->getValueAsInt();
378 bool Attribute::getValueAsBool() const {
379 if (!pImpl
) return false;
380 assert(isStringAttribute() &&
381 "Expected the attribute to be a string attribute!");
382 return pImpl
->getValueAsBool();
385 StringRef
Attribute::getKindAsString() const {
386 if (!pImpl
) return {};
387 assert(isStringAttribute() &&
388 "Invalid attribute type to get the kind as a string!");
389 return pImpl
->getKindAsString();
392 StringRef
Attribute::getValueAsString() const {
393 if (!pImpl
) return {};
394 assert(isStringAttribute() &&
395 "Invalid attribute type to get the value as a string!");
396 return pImpl
->getValueAsString();
399 Type
*Attribute::getValueAsType() const {
400 if (!pImpl
) return {};
401 assert(isTypeAttribute() &&
402 "Invalid attribute type to get the value as a type!");
403 return pImpl
->getValueAsType();
406 const ConstantRange
&Attribute::getValueAsConstantRange() const {
407 assert(isConstantRangeAttribute() &&
408 "Invalid attribute type to get the value as a ConstantRange!");
409 return pImpl
->getValueAsConstantRange();
412 ArrayRef
<ConstantRange
> Attribute::getValueAsConstantRangeList() const {
413 assert(isConstantRangeListAttribute() &&
414 "Invalid attribute type to get the value as a ConstantRangeList!");
415 return pImpl
->getValueAsConstantRangeList();
418 bool Attribute::hasAttribute(AttrKind Kind
) const {
419 return (pImpl
&& pImpl
->hasAttribute(Kind
)) || (!pImpl
&& Kind
== None
);
422 bool Attribute::hasAttribute(StringRef Kind
) const {
423 if (!isStringAttribute()) return false;
424 return pImpl
&& pImpl
->hasAttribute(Kind
);
427 MaybeAlign
Attribute::getAlignment() const {
428 assert(hasAttribute(Attribute::Alignment
) &&
429 "Trying to get alignment from non-alignment attribute!");
430 return MaybeAlign(pImpl
->getValueAsInt());
433 MaybeAlign
Attribute::getStackAlignment() const {
434 assert(hasAttribute(Attribute::StackAlignment
) &&
435 "Trying to get alignment from non-alignment attribute!");
436 return MaybeAlign(pImpl
->getValueAsInt());
439 uint64_t Attribute::getDereferenceableBytes() const {
440 assert(hasAttribute(Attribute::Dereferenceable
) &&
441 "Trying to get dereferenceable bytes from "
442 "non-dereferenceable attribute!");
443 return pImpl
->getValueAsInt();
446 uint64_t Attribute::getDereferenceableOrNullBytes() const {
447 assert(hasAttribute(Attribute::DereferenceableOrNull
) &&
448 "Trying to get dereferenceable bytes from "
449 "non-dereferenceable attribute!");
450 return pImpl
->getValueAsInt();
453 std::pair
<unsigned, std::optional
<unsigned>>
454 Attribute::getAllocSizeArgs() const {
455 assert(hasAttribute(Attribute::AllocSize
) &&
456 "Trying to get allocsize args from non-allocsize attribute");
457 return unpackAllocSizeArgs(pImpl
->getValueAsInt());
460 unsigned Attribute::getVScaleRangeMin() const {
461 assert(hasAttribute(Attribute::VScaleRange
) &&
462 "Trying to get vscale args from non-vscale attribute");
463 return unpackVScaleRangeArgs(pImpl
->getValueAsInt()).first
;
466 std::optional
<unsigned> Attribute::getVScaleRangeMax() const {
467 assert(hasAttribute(Attribute::VScaleRange
) &&
468 "Trying to get vscale args from non-vscale attribute");
469 return unpackVScaleRangeArgs(pImpl
->getValueAsInt()).second
;
472 UWTableKind
Attribute::getUWTableKind() const {
473 assert(hasAttribute(Attribute::UWTable
) &&
474 "Trying to get unwind table kind from non-uwtable attribute");
475 return UWTableKind(pImpl
->getValueAsInt());
478 AllocFnKind
Attribute::getAllocKind() const {
479 assert(hasAttribute(Attribute::AllocKind
) &&
480 "Trying to get allockind value from non-allockind attribute");
481 return AllocFnKind(pImpl
->getValueAsInt());
484 MemoryEffects
Attribute::getMemoryEffects() const {
485 assert(hasAttribute(Attribute::Memory
) &&
486 "Can only call getMemoryEffects() on memory attribute");
487 return MemoryEffects::createFromIntValue(pImpl
->getValueAsInt());
490 FPClassTest
Attribute::getNoFPClass() const {
491 assert(hasAttribute(Attribute::NoFPClass
) &&
492 "Can only call getNoFPClass() on nofpclass attribute");
493 return static_cast<FPClassTest
>(pImpl
->getValueAsInt());
496 const ConstantRange
&Attribute::getRange() const {
497 assert(hasAttribute(Attribute::Range
) &&
498 "Trying to get range args from non-range attribute");
499 return pImpl
->getValueAsConstantRange();
502 ArrayRef
<ConstantRange
> Attribute::getInitializes() const {
503 assert(hasAttribute(Attribute::Initializes
) &&
504 "Trying to get initializes attr from non-ConstantRangeList attribute");
505 return pImpl
->getValueAsConstantRangeList();
508 static const char *getModRefStr(ModRefInfo MR
) {
510 case ModRefInfo::NoModRef
:
512 case ModRefInfo::Ref
:
514 case ModRefInfo::Mod
:
516 case ModRefInfo::ModRef
:
519 llvm_unreachable("Invalid ModRefInfo");
522 std::string
Attribute::getAsString(bool InAttrGrp
) const {
523 if (!pImpl
) return {};
525 if (isEnumAttribute())
526 return getNameFromAttrKind(getKindAsEnum()).str();
528 if (isTypeAttribute()) {
529 std::string Result
= getNameFromAttrKind(getKindAsEnum()).str();
531 raw_string_ostream
OS(Result
);
532 getValueAsType()->print(OS
, false, true);
538 // FIXME: These should be output like this:
543 if (hasAttribute(Attribute::Alignment
))
544 return (InAttrGrp
? "align=" + Twine(getValueAsInt())
545 : "align " + Twine(getValueAsInt()))
548 auto AttrWithBytesToString
= [&](const char *Name
) {
549 return (InAttrGrp
? Name
+ ("=" + Twine(getValueAsInt()))
550 : Name
+ ("(" + Twine(getValueAsInt())) + ")")
554 if (hasAttribute(Attribute::StackAlignment
))
555 return AttrWithBytesToString("alignstack");
557 if (hasAttribute(Attribute::Dereferenceable
))
558 return AttrWithBytesToString("dereferenceable");
560 if (hasAttribute(Attribute::DereferenceableOrNull
))
561 return AttrWithBytesToString("dereferenceable_or_null");
563 if (hasAttribute(Attribute::AllocSize
)) {
565 std::optional
<unsigned> NumElems
;
566 std::tie(ElemSize
, NumElems
) = getAllocSizeArgs();
569 ? "allocsize(" + Twine(ElemSize
) + "," + Twine(*NumElems
) + ")"
570 : "allocsize(" + Twine(ElemSize
) + ")")
574 if (hasAttribute(Attribute::VScaleRange
)) {
575 unsigned MinValue
= getVScaleRangeMin();
576 std::optional
<unsigned> MaxValue
= getVScaleRangeMax();
577 return ("vscale_range(" + Twine(MinValue
) + "," +
578 Twine(MaxValue
.value_or(0)) + ")")
582 if (hasAttribute(Attribute::UWTable
)) {
583 UWTableKind Kind
= getUWTableKind();
584 assert(Kind
!= UWTableKind::None
&& "uwtable attribute should not be none");
585 return Kind
== UWTableKind::Default
? "uwtable" : "uwtable(sync)";
588 if (hasAttribute(Attribute::AllocKind
)) {
589 AllocFnKind Kind
= getAllocKind();
590 SmallVector
<StringRef
> parts
;
591 if ((Kind
& AllocFnKind::Alloc
) != AllocFnKind::Unknown
)
592 parts
.push_back("alloc");
593 if ((Kind
& AllocFnKind::Realloc
) != AllocFnKind::Unknown
)
594 parts
.push_back("realloc");
595 if ((Kind
& AllocFnKind::Free
) != AllocFnKind::Unknown
)
596 parts
.push_back("free");
597 if ((Kind
& AllocFnKind::Uninitialized
) != AllocFnKind::Unknown
)
598 parts
.push_back("uninitialized");
599 if ((Kind
& AllocFnKind::Zeroed
) != AllocFnKind::Unknown
)
600 parts
.push_back("zeroed");
601 if ((Kind
& AllocFnKind::Aligned
) != AllocFnKind::Unknown
)
602 parts
.push_back("aligned");
603 return ("allockind(\"" +
604 Twine(llvm::join(parts
.begin(), parts
.end(), ",")) + "\")")
608 if (hasAttribute(Attribute::Memory
)) {
610 raw_string_ostream
OS(Result
);
614 MemoryEffects ME
= getMemoryEffects();
616 // Print access kind for "other" as the default access kind. This way it
617 // will apply to any new location kinds that get split out of "other".
618 ModRefInfo OtherMR
= ME
.getModRef(IRMemLocation::Other
);
619 if (OtherMR
!= ModRefInfo::NoModRef
|| ME
.getModRef() == OtherMR
) {
621 OS
<< getModRefStr(OtherMR
);
624 for (auto Loc
: MemoryEffects::locations()) {
625 ModRefInfo MR
= ME
.getModRef(Loc
);
634 case IRMemLocation::ArgMem
:
637 case IRMemLocation::InaccessibleMem
:
638 OS
<< "inaccessiblemem: ";
640 case IRMemLocation::Other
:
641 llvm_unreachable("This is represented as the default access kind");
643 OS
<< getModRefStr(MR
);
650 if (hasAttribute(Attribute::NoFPClass
)) {
651 std::string Result
= "nofpclass";
652 raw_string_ostream
OS(Result
);
653 OS
<< getNoFPClass();
657 if (hasAttribute(Attribute::Range
)) {
659 raw_string_ostream
OS(Result
);
660 const ConstantRange
&CR
= getValueAsConstantRange();
662 OS
<< "i" << CR
.getBitWidth() << " ";
663 OS
<< CR
.getLower() << ", " << CR
.getUpper();
669 if (hasAttribute(Attribute::Initializes
)) {
671 raw_string_ostream
OS(Result
);
672 ConstantRangeList CRL
= getInitializes();
673 OS
<< "initializes(";
680 // Convert target-dependent attributes to strings of the form:
685 if (isStringAttribute()) {
688 raw_string_ostream
OS(Result
);
689 OS
<< '"' << getKindAsString() << '"';
691 // Since some attribute strings contain special characters that cannot be
692 // printable, those have to be escaped to make the attribute value
693 // printable as is. e.g. "\01__gnu_mcount_nc"
694 const auto &AttrVal
= pImpl
->getValueAsString();
695 if (!AttrVal
.empty()) {
697 printEscapedString(AttrVal
, OS
);
704 llvm_unreachable("Unknown attribute");
707 bool Attribute::hasParentContext(LLVMContext
&C
) const {
708 assert(isValid() && "invalid Attribute doesn't refer to any context");
712 return C
.pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, Unused
) == pImpl
;
715 int Attribute::cmpKind(Attribute A
) const {
716 if (!pImpl
&& !A
.pImpl
)
722 return pImpl
->cmp(*A
.pImpl
, /*KindOnly=*/true);
725 bool Attribute::operator<(Attribute A
) const {
726 if (!pImpl
&& !A
.pImpl
) return false;
727 if (!pImpl
) return true;
728 if (!A
.pImpl
) return false;
729 return *pImpl
< *A
.pImpl
;
732 void Attribute::Profile(FoldingSetNodeID
&ID
) const {
733 ID
.AddPointer(pImpl
);
736 enum AttributeProperty
{
738 ParamAttr
= (1 << 1),
740 IntersectPreserve
= (0 << 3),
741 IntersectAnd
= (1 << 3),
742 IntersectMin
= (2 << 3),
743 IntersectCustom
= (3 << 3),
744 IntersectPropertyMask
= (3 << 3),
747 #define GET_ATTR_PROP_TABLE
748 #include "llvm/IR/Attributes.inc"
750 static unsigned getAttributeProperties(Attribute::AttrKind Kind
) {
751 unsigned Index
= Kind
- 1;
752 assert(Index
< std::size(AttrPropTable
) && "Invalid attribute kind");
753 return AttrPropTable
[Index
];
756 static bool hasAttributeProperty(Attribute::AttrKind Kind
,
757 AttributeProperty Prop
) {
758 return getAttributeProperties(Kind
) & Prop
;
761 bool Attribute::canUseAsFnAttr(AttrKind Kind
) {
762 return hasAttributeProperty(Kind
, AttributeProperty::FnAttr
);
765 bool Attribute::canUseAsParamAttr(AttrKind Kind
) {
766 return hasAttributeProperty(Kind
, AttributeProperty::ParamAttr
);
769 bool Attribute::canUseAsRetAttr(AttrKind Kind
) {
770 return hasAttributeProperty(Kind
, AttributeProperty::RetAttr
);
773 static bool hasIntersectProperty(Attribute::AttrKind Kind
,
774 AttributeProperty Prop
) {
775 assert((Prop
== AttributeProperty::IntersectPreserve
||
776 Prop
== AttributeProperty::IntersectAnd
||
777 Prop
== AttributeProperty::IntersectMin
||
778 Prop
== AttributeProperty::IntersectCustom
) &&
779 "Unknown intersect property");
780 return (getAttributeProperties(Kind
) &
781 AttributeProperty::IntersectPropertyMask
) == Prop
;
784 bool Attribute::intersectMustPreserve(AttrKind Kind
) {
785 return hasIntersectProperty(Kind
, AttributeProperty::IntersectPreserve
);
787 bool Attribute::intersectWithAnd(AttrKind Kind
) {
788 return hasIntersectProperty(Kind
, AttributeProperty::IntersectAnd
);
790 bool Attribute::intersectWithMin(AttrKind Kind
) {
791 return hasIntersectProperty(Kind
, AttributeProperty::IntersectMin
);
793 bool Attribute::intersectWithCustom(AttrKind Kind
) {
794 return hasIntersectProperty(Kind
, AttributeProperty::IntersectCustom
);
797 //===----------------------------------------------------------------------===//
798 // AttributeImpl Definition
799 //===----------------------------------------------------------------------===//
801 bool AttributeImpl::hasAttribute(Attribute::AttrKind A
) const {
802 if (isStringAttribute()) return false;
803 return getKindAsEnum() == A
;
806 bool AttributeImpl::hasAttribute(StringRef Kind
) const {
807 if (!isStringAttribute()) return false;
808 return getKindAsString() == Kind
;
811 Attribute::AttrKind
AttributeImpl::getKindAsEnum() const {
812 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
813 isConstantRangeAttribute() || isConstantRangeListAttribute());
814 return static_cast<const EnumAttributeImpl
*>(this)->getEnumKind();
817 uint64_t AttributeImpl::getValueAsInt() const {
818 assert(isIntAttribute());
819 return static_cast<const IntAttributeImpl
*>(this)->getValue();
822 bool AttributeImpl::getValueAsBool() const {
823 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
824 return getValueAsString() == "true";
827 StringRef
AttributeImpl::getKindAsString() const {
828 assert(isStringAttribute());
829 return static_cast<const StringAttributeImpl
*>(this)->getStringKind();
832 StringRef
AttributeImpl::getValueAsString() const {
833 assert(isStringAttribute());
834 return static_cast<const StringAttributeImpl
*>(this)->getStringValue();
837 Type
*AttributeImpl::getValueAsType() const {
838 assert(isTypeAttribute());
839 return static_cast<const TypeAttributeImpl
*>(this)->getTypeValue();
842 const ConstantRange
&AttributeImpl::getValueAsConstantRange() const {
843 assert(isConstantRangeAttribute());
844 return static_cast<const ConstantRangeAttributeImpl
*>(this)
845 ->getConstantRangeValue();
848 ArrayRef
<ConstantRange
> AttributeImpl::getValueAsConstantRangeList() const {
849 assert(isConstantRangeListAttribute());
850 return static_cast<const ConstantRangeListAttributeImpl
*>(this)
851 ->getConstantRangeListValue();
854 int AttributeImpl::cmp(const AttributeImpl
&AI
, bool KindOnly
) const {
858 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
859 // relative to their enum value) and then strings.
860 if (!isStringAttribute()) {
861 if (AI
.isStringAttribute())
864 if (getKindAsEnum() != AI
.getKindAsEnum())
865 return getKindAsEnum() < AI
.getKindAsEnum() ? -1 : 1;
869 assert(!AI
.isEnumAttribute() && "Non-unique attribute");
870 assert(!AI
.isTypeAttribute() && "Comparison of types would be unstable");
871 assert(!AI
.isConstantRangeAttribute() && "Unclear how to compare ranges");
872 assert(!AI
.isConstantRangeListAttribute() &&
873 "Unclear how to compare range list");
874 // TODO: Is this actually needed?
875 assert(AI
.isIntAttribute() && "Only possibility left");
876 if (getValueAsInt() < AI
.getValueAsInt())
878 return getValueAsInt() == AI
.getValueAsInt() ? 0 : 1;
880 if (!AI
.isStringAttribute())
883 return getKindAsString().compare(AI
.getKindAsString());
884 if (getKindAsString() == AI
.getKindAsString())
885 return getValueAsString().compare(AI
.getValueAsString());
886 return getKindAsString().compare(AI
.getKindAsString());
889 bool AttributeImpl::operator<(const AttributeImpl
&AI
) const {
890 return cmp(AI
, /*KindOnly=*/false) < 0;
893 //===----------------------------------------------------------------------===//
894 // AttributeSet Definition
895 //===----------------------------------------------------------------------===//
897 AttributeSet
AttributeSet::get(LLVMContext
&C
, const AttrBuilder
&B
) {
898 return AttributeSet(AttributeSetNode::get(C
, B
));
901 AttributeSet
AttributeSet::get(LLVMContext
&C
, ArrayRef
<Attribute
> Attrs
) {
902 return AttributeSet(AttributeSetNode::get(C
, Attrs
));
905 AttributeSet
AttributeSet::addAttribute(LLVMContext
&C
,
906 Attribute::AttrKind Kind
) const {
907 if (hasAttribute(Kind
)) return *this;
909 B
.addAttribute(Kind
);
910 return addAttributes(C
, AttributeSet::get(C
, B
));
913 AttributeSet
AttributeSet::addAttribute(LLVMContext
&C
, StringRef Kind
,
914 StringRef Value
) const {
916 B
.addAttribute(Kind
, Value
);
917 return addAttributes(C
, AttributeSet::get(C
, B
));
920 AttributeSet
AttributeSet::addAttributes(LLVMContext
&C
,
921 const AttributeSet AS
) const {
922 if (!hasAttributes())
925 if (!AS
.hasAttributes())
928 AttrBuilder
B(C
, *this);
929 B
.merge(AttrBuilder(C
, AS
));
933 AttributeSet
AttributeSet::removeAttribute(LLVMContext
&C
,
934 Attribute::AttrKind Kind
) const {
935 if (!hasAttribute(Kind
)) return *this;
936 AttrBuilder
B(C
, *this);
937 B
.removeAttribute(Kind
);
941 AttributeSet
AttributeSet::removeAttribute(LLVMContext
&C
,
942 StringRef Kind
) const {
943 if (!hasAttribute(Kind
)) return *this;
944 AttrBuilder
B(C
, *this);
945 B
.removeAttribute(Kind
);
949 AttributeSet
AttributeSet::removeAttributes(LLVMContext
&C
,
950 const AttributeMask
&Attrs
) const {
951 AttrBuilder
B(C
, *this);
952 // If there is nothing to remove, directly return the original set.
953 if (!B
.overlaps(Attrs
))
960 std::optional
<AttributeSet
>
961 AttributeSet::intersectWith(LLVMContext
&C
, AttributeSet Other
) const {
965 AttrBuilder
Intersected(C
);
966 // Iterate over both attr sets at once.
967 auto ItBegin0
= begin();
969 auto ItBegin1
= Other
.begin();
970 auto ItEnd1
= Other
.end();
972 while (ItBegin0
!= ItEnd0
|| ItBegin1
!= ItEnd1
) {
973 // Loop through all attributes in both this and Other in sorted order. If
974 // the attribute is only present in one of the sets, it will be set in
975 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
976 Attribute Attr0
, Attr1
;
977 if (ItBegin1
== ItEnd1
)
979 else if (ItBegin0
== ItEnd0
)
982 int Cmp
= ItBegin0
->cmpKind(*ItBegin1
);
991 assert(Attr0
.isValid() && "Iteration should always yield a valid attr");
993 auto IntersectEq
= [&]() {
994 if (!Attr1
.isValid())
998 Intersected
.addAttribute(Attr0
);
1002 // Non-enum assume we must preserve. Handle early so we can unconditionally
1004 if (!Attr0
.hasKindAsEnum()) {
1006 return std::nullopt
;
1010 Attribute::AttrKind Kind
= Attr0
.getKindAsEnum();
1011 // If we don't have both attributes, then fail if the attribute is
1012 // must-preserve or drop it otherwise.
1013 if (!Attr1
.isValid()) {
1014 if (Attribute::intersectMustPreserve(Kind
))
1015 return std::nullopt
;
1019 // We have both attributes so apply the intersection rule.
1020 assert(Attr1
.hasKindAsEnum() && Kind
== Attr1
.getKindAsEnum() &&
1021 "Iterator picked up two different attributes in the same iteration");
1023 // Attribute we can intersect with "and"
1024 if (Attribute::intersectWithAnd(Kind
)) {
1025 assert(Attribute::isEnumAttrKind(Kind
) &&
1026 "Invalid attr type of intersectAnd");
1027 Intersected
.addAttribute(Kind
);
1031 // Attribute we can intersect with "min"
1032 if (Attribute::intersectWithMin(Kind
)) {
1033 assert(Attribute::isIntAttrKind(Kind
) &&
1034 "Invalid attr type of intersectMin");
1035 uint64_t NewVal
= std::min(Attr0
.getValueAsInt(), Attr1
.getValueAsInt());
1036 Intersected
.addRawIntAttr(Kind
, NewVal
);
1039 // Attribute we can intersect but need a custom rule for.
1040 if (Attribute::intersectWithCustom(Kind
)) {
1042 case Attribute::Alignment
:
1043 // If `byval` is present, alignment become must-preserve. This is
1044 // handled below if we have `byval`.
1045 Intersected
.addAlignmentAttr(
1046 std::min(Attr0
.getAlignment().valueOrOne(),
1047 Attr1
.getAlignment().valueOrOne()));
1049 case Attribute::Memory
:
1050 Intersected
.addMemoryAttr(Attr0
.getMemoryEffects() |
1051 Attr1
.getMemoryEffects());
1053 case Attribute::NoFPClass
:
1054 Intersected
.addNoFPClassAttr(Attr0
.getNoFPClass() &
1055 Attr1
.getNoFPClass());
1057 case Attribute::Range
: {
1058 ConstantRange Range0
= Attr0
.getRange();
1059 ConstantRange Range1
= Attr1
.getRange();
1060 ConstantRange NewRange
= Range0
.unionWith(Range1
);
1061 if (!NewRange
.isFullSet())
1062 Intersected
.addRangeAttr(NewRange
);
1065 llvm_unreachable("Unknown attribute with custom intersection rule");
1070 // Attributes with no intersection rule. Only intersect if they are equal.
1073 return std::nullopt
;
1075 // Special handling of `byval`. `byval` essentially turns align attr into
1077 if (Kind
== Attribute::ByVal
&&
1078 getAttribute(Attribute::Alignment
) !=
1079 Other
.getAttribute(Attribute::Alignment
))
1080 return std::nullopt
;
1083 return get(C
, Intersected
);
1086 unsigned AttributeSet::getNumAttributes() const {
1087 return SetNode
? SetNode
->getNumAttributes() : 0;
1090 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind
) const {
1091 return SetNode
? SetNode
->hasAttribute(Kind
) : false;
1094 bool AttributeSet::hasAttribute(StringRef Kind
) const {
1095 return SetNode
? SetNode
->hasAttribute(Kind
) : false;
1098 Attribute
AttributeSet::getAttribute(Attribute::AttrKind Kind
) const {
1099 return SetNode
? SetNode
->getAttribute(Kind
) : Attribute();
1102 Attribute
AttributeSet::getAttribute(StringRef Kind
) const {
1103 return SetNode
? SetNode
->getAttribute(Kind
) : Attribute();
1106 MaybeAlign
AttributeSet::getAlignment() const {
1107 return SetNode
? SetNode
->getAlignment() : std::nullopt
;
1110 MaybeAlign
AttributeSet::getStackAlignment() const {
1111 return SetNode
? SetNode
->getStackAlignment() : std::nullopt
;
1114 uint64_t AttributeSet::getDereferenceableBytes() const {
1115 return SetNode
? SetNode
->getDereferenceableBytes() : 0;
1118 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
1119 return SetNode
? SetNode
->getDereferenceableOrNullBytes() : 0;
1122 Type
*AttributeSet::getByRefType() const {
1123 return SetNode
? SetNode
->getAttributeType(Attribute::ByRef
) : nullptr;
1126 Type
*AttributeSet::getByValType() const {
1127 return SetNode
? SetNode
->getAttributeType(Attribute::ByVal
) : nullptr;
1130 Type
*AttributeSet::getStructRetType() const {
1131 return SetNode
? SetNode
->getAttributeType(Attribute::StructRet
) : nullptr;
1134 Type
*AttributeSet::getPreallocatedType() const {
1135 return SetNode
? SetNode
->getAttributeType(Attribute::Preallocated
) : nullptr;
1138 Type
*AttributeSet::getInAllocaType() const {
1139 return SetNode
? SetNode
->getAttributeType(Attribute::InAlloca
) : nullptr;
1142 Type
*AttributeSet::getElementType() const {
1143 return SetNode
? SetNode
->getAttributeType(Attribute::ElementType
) : nullptr;
1146 std::optional
<std::pair
<unsigned, std::optional
<unsigned>>>
1147 AttributeSet::getAllocSizeArgs() const {
1149 return SetNode
->getAllocSizeArgs();
1150 return std::nullopt
;
1153 unsigned AttributeSet::getVScaleRangeMin() const {
1154 return SetNode
? SetNode
->getVScaleRangeMin() : 1;
1157 std::optional
<unsigned> AttributeSet::getVScaleRangeMax() const {
1158 return SetNode
? SetNode
->getVScaleRangeMax() : std::nullopt
;
1161 UWTableKind
AttributeSet::getUWTableKind() const {
1162 return SetNode
? SetNode
->getUWTableKind() : UWTableKind::None
;
1165 AllocFnKind
AttributeSet::getAllocKind() const {
1166 return SetNode
? SetNode
->getAllocKind() : AllocFnKind::Unknown
;
1169 MemoryEffects
AttributeSet::getMemoryEffects() const {
1170 return SetNode
? SetNode
->getMemoryEffects() : MemoryEffects::unknown();
1173 FPClassTest
AttributeSet::getNoFPClass() const {
1174 return SetNode
? SetNode
->getNoFPClass() : fcNone
;
1177 std::string
AttributeSet::getAsString(bool InAttrGrp
) const {
1178 return SetNode
? SetNode
->getAsString(InAttrGrp
) : "";
1181 bool AttributeSet::hasParentContext(LLVMContext
&C
) const {
1182 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1183 FoldingSetNodeID ID
;
1184 SetNode
->Profile(ID
);
1186 return C
.pImpl
->AttrsSetNodes
.FindNodeOrInsertPos(ID
, Unused
) == SetNode
;
1189 AttributeSet::iterator
AttributeSet::begin() const {
1190 return SetNode
? SetNode
->begin() : nullptr;
1193 AttributeSet::iterator
AttributeSet::end() const {
1194 return SetNode
? SetNode
->end() : nullptr;
1197 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1198 LLVM_DUMP_METHOD
void AttributeSet::dump() const {
1201 dbgs() << getAsString(true) << " }\n";
1205 //===----------------------------------------------------------------------===//
1206 // AttributeSetNode Definition
1207 //===----------------------------------------------------------------------===//
1209 AttributeSetNode::AttributeSetNode(ArrayRef
<Attribute
> Attrs
)
1210 : NumAttrs(Attrs
.size()) {
1211 // There's memory after the node where we can store the entries in.
1212 llvm::copy(Attrs
, getTrailingObjects
<Attribute
>());
1214 for (const auto &I
: *this) {
1215 if (I
.isStringAttribute())
1216 StringAttrs
.insert({ I
.getKindAsString(), I
});
1218 AvailableAttrs
.addAttribute(I
.getKindAsEnum());
1222 AttributeSetNode
*AttributeSetNode::get(LLVMContext
&C
,
1223 ArrayRef
<Attribute
> Attrs
) {
1224 SmallVector
<Attribute
, 8> SortedAttrs(Attrs
);
1225 llvm::sort(SortedAttrs
);
1226 return getSorted(C
, SortedAttrs
);
1229 AttributeSetNode
*AttributeSetNode::getSorted(LLVMContext
&C
,
1230 ArrayRef
<Attribute
> SortedAttrs
) {
1231 if (SortedAttrs
.empty())
1234 // Build a key to look up the existing attributes.
1235 LLVMContextImpl
*pImpl
= C
.pImpl
;
1236 FoldingSetNodeID ID
;
1238 assert(llvm::is_sorted(SortedAttrs
) && "Expected sorted attributes!");
1239 for (const auto &Attr
: SortedAttrs
)
1243 AttributeSetNode
*PA
=
1244 pImpl
->AttrsSetNodes
.FindNodeOrInsertPos(ID
, InsertPoint
);
1246 // If we didn't find any existing attributes of the same shape then create a
1247 // new one and insert it.
1249 // Coallocate entries after the AttributeSetNode itself.
1250 void *Mem
= ::operator new(totalSizeToAlloc
<Attribute
>(SortedAttrs
.size()));
1251 PA
= new (Mem
) AttributeSetNode(SortedAttrs
);
1252 pImpl
->AttrsSetNodes
.InsertNode(PA
, InsertPoint
);
1255 // Return the AttributeSetNode that we found or created.
1259 AttributeSetNode
*AttributeSetNode::get(LLVMContext
&C
, const AttrBuilder
&B
) {
1260 return getSorted(C
, B
.attrs());
1263 bool AttributeSetNode::hasAttribute(StringRef Kind
) const {
1264 return StringAttrs
.count(Kind
);
1267 std::optional
<Attribute
>
1268 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind
) const {
1269 // Do a quick presence check.
1270 if (!hasAttribute(Kind
))
1271 return std::nullopt
;
1273 // Attributes in a set are sorted by enum value, followed by string
1274 // attributes. Binary search the one we want.
1275 const Attribute
*I
=
1276 std::lower_bound(begin(), end() - StringAttrs
.size(), Kind
,
1277 [](Attribute A
, Attribute::AttrKind Kind
) {
1278 return A
.getKindAsEnum() < Kind
;
1280 assert(I
!= end() && I
->hasAttribute(Kind
) && "Presence check failed?");
1284 Attribute
AttributeSetNode::getAttribute(Attribute::AttrKind Kind
) const {
1285 if (auto A
= findEnumAttribute(Kind
))
1290 Attribute
AttributeSetNode::getAttribute(StringRef Kind
) const {
1291 return StringAttrs
.lookup(Kind
);
1294 MaybeAlign
AttributeSetNode::getAlignment() const {
1295 if (auto A
= findEnumAttribute(Attribute::Alignment
))
1296 return A
->getAlignment();
1297 return std::nullopt
;
1300 MaybeAlign
AttributeSetNode::getStackAlignment() const {
1301 if (auto A
= findEnumAttribute(Attribute::StackAlignment
))
1302 return A
->getStackAlignment();
1303 return std::nullopt
;
1306 Type
*AttributeSetNode::getAttributeType(Attribute::AttrKind Kind
) const {
1307 if (auto A
= findEnumAttribute(Kind
))
1308 return A
->getValueAsType();
1312 uint64_t AttributeSetNode::getDereferenceableBytes() const {
1313 if (auto A
= findEnumAttribute(Attribute::Dereferenceable
))
1314 return A
->getDereferenceableBytes();
1318 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
1319 if (auto A
= findEnumAttribute(Attribute::DereferenceableOrNull
))
1320 return A
->getDereferenceableOrNullBytes();
1324 std::optional
<std::pair
<unsigned, std::optional
<unsigned>>>
1325 AttributeSetNode::getAllocSizeArgs() const {
1326 if (auto A
= findEnumAttribute(Attribute::AllocSize
))
1327 return A
->getAllocSizeArgs();
1328 return std::nullopt
;
1331 unsigned AttributeSetNode::getVScaleRangeMin() const {
1332 if (auto A
= findEnumAttribute(Attribute::VScaleRange
))
1333 return A
->getVScaleRangeMin();
1337 std::optional
<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1338 if (auto A
= findEnumAttribute(Attribute::VScaleRange
))
1339 return A
->getVScaleRangeMax();
1340 return std::nullopt
;
1343 UWTableKind
AttributeSetNode::getUWTableKind() const {
1344 if (auto A
= findEnumAttribute(Attribute::UWTable
))
1345 return A
->getUWTableKind();
1346 return UWTableKind::None
;
1349 AllocFnKind
AttributeSetNode::getAllocKind() const {
1350 if (auto A
= findEnumAttribute(Attribute::AllocKind
))
1351 return A
->getAllocKind();
1352 return AllocFnKind::Unknown
;
1355 MemoryEffects
AttributeSetNode::getMemoryEffects() const {
1356 if (auto A
= findEnumAttribute(Attribute::Memory
))
1357 return A
->getMemoryEffects();
1358 return MemoryEffects::unknown();
1361 FPClassTest
AttributeSetNode::getNoFPClass() const {
1362 if (auto A
= findEnumAttribute(Attribute::NoFPClass
))
1363 return A
->getNoFPClass();
1367 std::string
AttributeSetNode::getAsString(bool InAttrGrp
) const {
1369 for (iterator I
= begin(), E
= end(); I
!= E
; ++I
) {
1372 Str
+= I
->getAsString(InAttrGrp
);
1377 //===----------------------------------------------------------------------===//
1378 // AttributeListImpl Definition
1379 //===----------------------------------------------------------------------===//
1381 /// Map from AttributeList index to the internal array index. Adding one happens
1382 /// to work, because -1 wraps around to 0.
1383 static unsigned attrIdxToArrayIdx(unsigned Index
) {
1387 AttributeListImpl::AttributeListImpl(ArrayRef
<AttributeSet
> Sets
)
1388 : NumAttrSets(Sets
.size()) {
1389 assert(!Sets
.empty() && "pointless AttributeListImpl");
1391 // There's memory after the node where we can store the entries in.
1392 llvm::copy(Sets
, getTrailingObjects
<AttributeSet
>());
1394 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1396 for (const auto &I
: Sets
[attrIdxToArrayIdx(AttributeList::FunctionIndex
)])
1397 if (!I
.isStringAttribute())
1398 AvailableFunctionAttrs
.addAttribute(I
.getKindAsEnum());
1400 for (const auto &Set
: Sets
)
1401 for (const auto &I
: Set
)
1402 if (!I
.isStringAttribute())
1403 AvailableSomewhereAttrs
.addAttribute(I
.getKindAsEnum());
1406 void AttributeListImpl::Profile(FoldingSetNodeID
&ID
) const {
1407 Profile(ID
, ArrayRef(begin(), end()));
1410 void AttributeListImpl::Profile(FoldingSetNodeID
&ID
,
1411 ArrayRef
<AttributeSet
> Sets
) {
1412 for (const auto &Set
: Sets
)
1413 ID
.AddPointer(Set
.SetNode
);
1416 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind
,
1417 unsigned *Index
) const {
1418 if (!AvailableSomewhereAttrs
.hasAttribute(Kind
))
1422 for (unsigned I
= 0, E
= NumAttrSets
; I
!= E
; ++I
) {
1423 if (begin()[I
].hasAttribute(Kind
)) {
1434 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1435 LLVM_DUMP_METHOD
void AttributeListImpl::dump() const {
1436 AttributeList(const_cast<AttributeListImpl
*>(this)).dump();
1440 //===----------------------------------------------------------------------===//
1441 // AttributeList Construction and Mutation Methods
1442 //===----------------------------------------------------------------------===//
1444 AttributeList
AttributeList::getImpl(LLVMContext
&C
,
1445 ArrayRef
<AttributeSet
> AttrSets
) {
1446 assert(!AttrSets
.empty() && "pointless AttributeListImpl");
1448 LLVMContextImpl
*pImpl
= C
.pImpl
;
1449 FoldingSetNodeID ID
;
1450 AttributeListImpl::Profile(ID
, AttrSets
);
1453 AttributeListImpl
*PA
=
1454 pImpl
->AttrsLists
.FindNodeOrInsertPos(ID
, InsertPoint
);
1456 // If we didn't find any existing attributes of the same shape then
1457 // create a new one and insert it.
1459 // Coallocate entries after the AttributeListImpl itself.
1460 void *Mem
= pImpl
->Alloc
.Allocate(
1461 AttributeListImpl::totalSizeToAlloc
<AttributeSet
>(AttrSets
.size()),
1462 alignof(AttributeListImpl
));
1463 PA
= new (Mem
) AttributeListImpl(AttrSets
);
1464 pImpl
->AttrsLists
.InsertNode(PA
, InsertPoint
);
1467 // Return the AttributesList that we found or created.
1468 return AttributeList(PA
);
1472 AttributeList::get(LLVMContext
&C
,
1473 ArrayRef
<std::pair
<unsigned, Attribute
>> Attrs
) {
1474 // If there are no attributes then return a null AttributesList pointer.
1478 assert(llvm::is_sorted(Attrs
, llvm::less_first()) &&
1479 "Misordered Attributes list!");
1480 assert(llvm::all_of(Attrs
,
1481 [](const std::pair
<unsigned, Attribute
> &Pair
) {
1482 return Pair
.second
.isValid();
1484 "Pointless attribute!");
1486 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1488 SmallVector
<std::pair
<unsigned, AttributeSet
>, 8> AttrPairVec
;
1489 for (ArrayRef
<std::pair
<unsigned, Attribute
>>::iterator I
= Attrs
.begin(),
1490 E
= Attrs
.end(); I
!= E
; ) {
1491 unsigned Index
= I
->first
;
1492 SmallVector
<Attribute
, 4> AttrVec
;
1493 while (I
!= E
&& I
->first
== Index
) {
1494 AttrVec
.push_back(I
->second
);
1498 AttrPairVec
.emplace_back(Index
, AttributeSet::get(C
, AttrVec
));
1501 return get(C
, AttrPairVec
);
1505 AttributeList::get(LLVMContext
&C
,
1506 ArrayRef
<std::pair
<unsigned, AttributeSet
>> Attrs
) {
1507 // If there are no attributes then return a null AttributesList pointer.
1511 assert(llvm::is_sorted(Attrs
, llvm::less_first()) &&
1512 "Misordered Attributes list!");
1513 assert(llvm::none_of(Attrs
,
1514 [](const std::pair
<unsigned, AttributeSet
> &Pair
) {
1515 return !Pair
.second
.hasAttributes();
1517 "Pointless attribute!");
1519 unsigned MaxIndex
= Attrs
.back().first
;
1520 // If the MaxIndex is FunctionIndex and there are other indices in front
1521 // of it, we need to use the largest of those to get the right size.
1522 if (MaxIndex
== FunctionIndex
&& Attrs
.size() > 1)
1523 MaxIndex
= Attrs
[Attrs
.size() - 2].first
;
1525 SmallVector
<AttributeSet
, 4> AttrVec(attrIdxToArrayIdx(MaxIndex
) + 1);
1526 for (const auto &Pair
: Attrs
)
1527 AttrVec
[attrIdxToArrayIdx(Pair
.first
)] = Pair
.second
;
1529 return getImpl(C
, AttrVec
);
1532 AttributeList
AttributeList::get(LLVMContext
&C
, AttributeSet FnAttrs
,
1533 AttributeSet RetAttrs
,
1534 ArrayRef
<AttributeSet
> ArgAttrs
) {
1535 // Scan from the end to find the last argument with attributes. Most
1536 // arguments don't have attributes, so it's nice if we can have fewer unique
1537 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1538 unsigned NumSets
= 0;
1539 for (size_t I
= ArgAttrs
.size(); I
!= 0; --I
) {
1540 if (ArgAttrs
[I
- 1].hasAttributes()) {
1546 // Check function and return attributes if we didn't have argument
1548 if (RetAttrs
.hasAttributes())
1550 else if (FnAttrs
.hasAttributes())
1554 // If all attribute sets were empty, we can use the empty attribute list.
1558 SmallVector
<AttributeSet
, 8> AttrSets
;
1559 AttrSets
.reserve(NumSets
);
1560 // If we have any attributes, we always have function attributes.
1561 AttrSets
.push_back(FnAttrs
);
1563 AttrSets
.push_back(RetAttrs
);
1565 // Drop the empty argument attribute sets at the end.
1566 ArgAttrs
= ArgAttrs
.take_front(NumSets
- 2);
1567 llvm::append_range(AttrSets
, ArgAttrs
);
1570 return getImpl(C
, AttrSets
);
1573 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1574 AttributeSet Attrs
) {
1575 if (!Attrs
.hasAttributes())
1577 Index
= attrIdxToArrayIdx(Index
);
1578 SmallVector
<AttributeSet
, 8> AttrSets(Index
+ 1);
1579 AttrSets
[Index
] = Attrs
;
1580 return getImpl(C
, AttrSets
);
1583 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1584 const AttrBuilder
&B
) {
1585 return get(C
, Index
, AttributeSet::get(C
, B
));
1588 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1589 ArrayRef
<Attribute::AttrKind
> Kinds
) {
1590 SmallVector
<std::pair
<unsigned, Attribute
>, 8> Attrs
;
1591 for (const auto K
: Kinds
)
1592 Attrs
.emplace_back(Index
, Attribute::get(C
, K
));
1593 return get(C
, Attrs
);
1596 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1597 ArrayRef
<Attribute::AttrKind
> Kinds
,
1598 ArrayRef
<uint64_t> Values
) {
1599 assert(Kinds
.size() == Values
.size() && "Mismatched attribute values.");
1600 SmallVector
<std::pair
<unsigned, Attribute
>, 8> Attrs
;
1601 auto VI
= Values
.begin();
1602 for (const auto K
: Kinds
)
1603 Attrs
.emplace_back(Index
, Attribute::get(C
, K
, *VI
++));
1604 return get(C
, Attrs
);
1607 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1608 ArrayRef
<StringRef
> Kinds
) {
1609 SmallVector
<std::pair
<unsigned, Attribute
>, 8> Attrs
;
1610 for (const auto &K
: Kinds
)
1611 Attrs
.emplace_back(Index
, Attribute::get(C
, K
));
1612 return get(C
, Attrs
);
1615 AttributeList
AttributeList::get(LLVMContext
&C
,
1616 ArrayRef
<AttributeList
> Attrs
) {
1619 if (Attrs
.size() == 1)
1622 unsigned MaxSize
= 0;
1623 for (const auto &List
: Attrs
)
1624 MaxSize
= std::max(MaxSize
, List
.getNumAttrSets());
1626 // If every list was empty, there is no point in merging the lists.
1630 SmallVector
<AttributeSet
, 8> NewAttrSets(MaxSize
);
1631 for (unsigned I
= 0; I
< MaxSize
; ++I
) {
1632 AttrBuilder
CurBuilder(C
);
1633 for (const auto &List
: Attrs
)
1634 CurBuilder
.merge(AttrBuilder(C
, List
.getAttributes(I
- 1)));
1635 NewAttrSets
[I
] = AttributeSet::get(C
, CurBuilder
);
1638 return getImpl(C
, NewAttrSets
);
1642 AttributeList::addAttributeAtIndex(LLVMContext
&C
, unsigned Index
,
1643 Attribute::AttrKind Kind
) const {
1644 AttributeSet Attrs
= getAttributes(Index
);
1645 if (Attrs
.hasAttribute(Kind
))
1647 // TODO: Insert at correct position and avoid sort.
1648 SmallVector
<Attribute
, 8> NewAttrs(Attrs
.begin(), Attrs
.end());
1649 NewAttrs
.push_back(Attribute::get(C
, Kind
));
1650 return setAttributesAtIndex(C
, Index
, AttributeSet::get(C
, NewAttrs
));
1653 AttributeList
AttributeList::addAttributeAtIndex(LLVMContext
&C
, unsigned Index
,
1655 StringRef Value
) const {
1657 B
.addAttribute(Kind
, Value
);
1658 return addAttributesAtIndex(C
, Index
, B
);
1661 AttributeList
AttributeList::addAttributeAtIndex(LLVMContext
&C
, unsigned Index
,
1662 Attribute A
) const {
1665 return addAttributesAtIndex(C
, Index
, B
);
1668 AttributeList
AttributeList::setAttributesAtIndex(LLVMContext
&C
,
1670 AttributeSet Attrs
) const {
1671 Index
= attrIdxToArrayIdx(Index
);
1672 SmallVector
<AttributeSet
, 4> AttrSets(this->begin(), this->end());
1673 if (Index
>= AttrSets
.size())
1674 AttrSets
.resize(Index
+ 1);
1675 AttrSets
[Index
] = Attrs
;
1677 // Remove trailing empty attribute sets.
1678 while (!AttrSets
.empty() && !AttrSets
.back().hasAttributes())
1679 AttrSets
.pop_back();
1680 if (AttrSets
.empty())
1682 return AttributeList::getImpl(C
, AttrSets
);
1685 AttributeList
AttributeList::addAttributesAtIndex(LLVMContext
&C
,
1687 const AttrBuilder
&B
) const {
1688 if (!B
.hasAttributes())
1692 return AttributeList::get(C
, {{Index
, AttributeSet::get(C
, B
)}});
1694 AttrBuilder
Merged(C
, getAttributes(Index
));
1696 return setAttributesAtIndex(C
, Index
, AttributeSet::get(C
, Merged
));
1699 AttributeList
AttributeList::addParamAttribute(LLVMContext
&C
,
1700 ArrayRef
<unsigned> ArgNos
,
1701 Attribute A
) const {
1702 assert(llvm::is_sorted(ArgNos
));
1704 SmallVector
<AttributeSet
, 4> AttrSets(this->begin(), this->end());
1705 unsigned MaxIndex
= attrIdxToArrayIdx(ArgNos
.back() + FirstArgIndex
);
1706 if (MaxIndex
>= AttrSets
.size())
1707 AttrSets
.resize(MaxIndex
+ 1);
1709 for (unsigned ArgNo
: ArgNos
) {
1710 unsigned Index
= attrIdxToArrayIdx(ArgNo
+ FirstArgIndex
);
1711 AttrBuilder
B(C
, AttrSets
[Index
]);
1713 AttrSets
[Index
] = AttributeSet::get(C
, B
);
1716 return getImpl(C
, AttrSets
);
1720 AttributeList::removeAttributeAtIndex(LLVMContext
&C
, unsigned Index
,
1721 Attribute::AttrKind Kind
) const {
1722 AttributeSet Attrs
= getAttributes(Index
);
1723 AttributeSet NewAttrs
= Attrs
.removeAttribute(C
, Kind
);
1724 if (Attrs
== NewAttrs
)
1726 return setAttributesAtIndex(C
, Index
, NewAttrs
);
1729 AttributeList
AttributeList::removeAttributeAtIndex(LLVMContext
&C
,
1731 StringRef Kind
) const {
1732 AttributeSet Attrs
= getAttributes(Index
);
1733 AttributeSet NewAttrs
= Attrs
.removeAttribute(C
, Kind
);
1734 if (Attrs
== NewAttrs
)
1736 return setAttributesAtIndex(C
, Index
, NewAttrs
);
1739 AttributeList
AttributeList::removeAttributesAtIndex(
1740 LLVMContext
&C
, unsigned Index
, const AttributeMask
&AttrsToRemove
) const {
1741 AttributeSet Attrs
= getAttributes(Index
);
1742 AttributeSet NewAttrs
= Attrs
.removeAttributes(C
, AttrsToRemove
);
1743 // If nothing was removed, return the original list.
1744 if (Attrs
== NewAttrs
)
1746 return setAttributesAtIndex(C
, Index
, NewAttrs
);
1750 AttributeList::removeAttributesAtIndex(LLVMContext
&C
,
1751 unsigned WithoutIndex
) const {
1754 if (attrIdxToArrayIdx(WithoutIndex
) >= getNumAttrSets())
1756 return setAttributesAtIndex(C
, WithoutIndex
, AttributeSet());
1759 AttributeList
AttributeList::addDereferenceableRetAttr(LLVMContext
&C
,
1760 uint64_t Bytes
) const {
1762 B
.addDereferenceableAttr(Bytes
);
1763 return addRetAttributes(C
, B
);
1766 AttributeList
AttributeList::addDereferenceableParamAttr(LLVMContext
&C
,
1768 uint64_t Bytes
) const {
1770 B
.addDereferenceableAttr(Bytes
);
1771 return addParamAttributes(C
, Index
, B
);
1775 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext
&C
, unsigned Index
,
1776 uint64_t Bytes
) const {
1778 B
.addDereferenceableOrNullAttr(Bytes
);
1779 return addParamAttributes(C
, Index
, B
);
1782 AttributeList
AttributeList::addRangeRetAttr(LLVMContext
&C
,
1783 const ConstantRange
&CR
) const {
1786 return addRetAttributes(C
, B
);
1789 AttributeList
AttributeList::addAllocSizeParamAttr(
1790 LLVMContext
&C
, unsigned Index
, unsigned ElemSizeArg
,
1791 const std::optional
<unsigned> &NumElemsArg
) const {
1793 B
.addAllocSizeAttr(ElemSizeArg
, NumElemsArg
);
1794 return addParamAttributes(C
, Index
, B
);
1797 std::optional
<AttributeList
>
1798 AttributeList::intersectWith(LLVMContext
&C
, AttributeList Other
) const {
1799 // Trivial case, the two lists are equal.
1803 SmallVector
<std::pair
<unsigned, AttributeSet
>> IntersectedAttrs
;
1805 index_iterator(std::max(getNumAttrSets(), Other
.getNumAttrSets()));
1806 for (unsigned Idx
: IndexIt
) {
1807 auto IntersectedAS
=
1808 getAttributes(Idx
).intersectWith(C
, Other
.getAttributes(Idx
));
1809 // If any index fails to intersect, fail.
1811 return std::nullopt
;
1812 if (!IntersectedAS
->hasAttributes())
1814 IntersectedAttrs
.push_back(std::make_pair(Idx
, *IntersectedAS
));
1817 llvm::sort(IntersectedAttrs
, llvm::less_first());
1818 return AttributeList::get(C
, IntersectedAttrs
);
1821 //===----------------------------------------------------------------------===//
1822 // AttributeList Accessor Methods
1823 //===----------------------------------------------------------------------===//
1825 AttributeSet
AttributeList::getParamAttrs(unsigned ArgNo
) const {
1826 return getAttributes(ArgNo
+ FirstArgIndex
);
1829 AttributeSet
AttributeList::getRetAttrs() const {
1830 return getAttributes(ReturnIndex
);
1833 AttributeSet
AttributeList::getFnAttrs() const {
1834 return getAttributes(FunctionIndex
);
1837 bool AttributeList::hasAttributeAtIndex(unsigned Index
,
1838 Attribute::AttrKind Kind
) const {
1839 return getAttributes(Index
).hasAttribute(Kind
);
1842 bool AttributeList::hasAttributeAtIndex(unsigned Index
, StringRef Kind
) const {
1843 return getAttributes(Index
).hasAttribute(Kind
);
1846 bool AttributeList::hasAttributesAtIndex(unsigned Index
) const {
1847 return getAttributes(Index
).hasAttributes();
1850 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind
) const {
1851 return pImpl
&& pImpl
->hasFnAttribute(Kind
);
1854 bool AttributeList::hasFnAttr(StringRef Kind
) const {
1855 return hasAttributeAtIndex(AttributeList::FunctionIndex
, Kind
);
1858 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr
,
1859 unsigned *Index
) const {
1860 return pImpl
&& pImpl
->hasAttrSomewhere(Attr
, Index
);
1863 Attribute
AttributeList::getAttributeAtIndex(unsigned Index
,
1864 Attribute::AttrKind Kind
) const {
1865 return getAttributes(Index
).getAttribute(Kind
);
1868 Attribute
AttributeList::getAttributeAtIndex(unsigned Index
,
1869 StringRef Kind
) const {
1870 return getAttributes(Index
).getAttribute(Kind
);
1873 MaybeAlign
AttributeList::getRetAlignment() const {
1874 return getAttributes(ReturnIndex
).getAlignment();
1877 MaybeAlign
AttributeList::getParamAlignment(unsigned ArgNo
) const {
1878 return getAttributes(ArgNo
+ FirstArgIndex
).getAlignment();
1881 MaybeAlign
AttributeList::getParamStackAlignment(unsigned ArgNo
) const {
1882 return getAttributes(ArgNo
+ FirstArgIndex
).getStackAlignment();
1885 Type
*AttributeList::getParamByValType(unsigned Index
) const {
1886 return getAttributes(Index
+FirstArgIndex
).getByValType();
1889 Type
*AttributeList::getParamStructRetType(unsigned Index
) const {
1890 return getAttributes(Index
+ FirstArgIndex
).getStructRetType();
1893 Type
*AttributeList::getParamByRefType(unsigned Index
) const {
1894 return getAttributes(Index
+ FirstArgIndex
).getByRefType();
1897 Type
*AttributeList::getParamPreallocatedType(unsigned Index
) const {
1898 return getAttributes(Index
+ FirstArgIndex
).getPreallocatedType();
1901 Type
*AttributeList::getParamInAllocaType(unsigned Index
) const {
1902 return getAttributes(Index
+ FirstArgIndex
).getInAllocaType();
1905 Type
*AttributeList::getParamElementType(unsigned Index
) const {
1906 return getAttributes(Index
+ FirstArgIndex
).getElementType();
1909 MaybeAlign
AttributeList::getFnStackAlignment() const {
1910 return getFnAttrs().getStackAlignment();
1913 MaybeAlign
AttributeList::getRetStackAlignment() const {
1914 return getRetAttrs().getStackAlignment();
1917 uint64_t AttributeList::getRetDereferenceableBytes() const {
1918 return getRetAttrs().getDereferenceableBytes();
1921 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index
) const {
1922 return getParamAttrs(Index
).getDereferenceableBytes();
1925 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1926 return getRetAttrs().getDereferenceableOrNullBytes();
1930 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index
) const {
1931 return getParamAttrs(Index
).getDereferenceableOrNullBytes();
1934 std::optional
<ConstantRange
>
1935 AttributeList::getParamRange(unsigned ArgNo
) const {
1936 auto RangeAttr
= getParamAttrs(ArgNo
).getAttribute(Attribute::Range
);
1937 if (RangeAttr
.isValid())
1938 return RangeAttr
.getRange();
1939 return std::nullopt
;
1942 FPClassTest
AttributeList::getRetNoFPClass() const {
1943 return getRetAttrs().getNoFPClass();
1946 FPClassTest
AttributeList::getParamNoFPClass(unsigned Index
) const {
1947 return getParamAttrs(Index
).getNoFPClass();
1950 UWTableKind
AttributeList::getUWTableKind() const {
1951 return getFnAttrs().getUWTableKind();
1954 AllocFnKind
AttributeList::getAllocKind() const {
1955 return getFnAttrs().getAllocKind();
1958 MemoryEffects
AttributeList::getMemoryEffects() const {
1959 return getFnAttrs().getMemoryEffects();
1962 std::string
AttributeList::getAsString(unsigned Index
, bool InAttrGrp
) const {
1963 return getAttributes(Index
).getAsString(InAttrGrp
);
1966 AttributeSet
AttributeList::getAttributes(unsigned Index
) const {
1967 Index
= attrIdxToArrayIdx(Index
);
1968 if (!pImpl
|| Index
>= getNumAttrSets())
1970 return pImpl
->begin()[Index
];
1973 bool AttributeList::hasParentContext(LLVMContext
&C
) const {
1974 assert(!isEmpty() && "an empty attribute list has no parent context");
1975 FoldingSetNodeID ID
;
1978 return C
.pImpl
->AttrsLists
.FindNodeOrInsertPos(ID
, Unused
) == pImpl
;
1981 AttributeList::iterator
AttributeList::begin() const {
1982 return pImpl
? pImpl
->begin() : nullptr;
1985 AttributeList::iterator
AttributeList::end() const {
1986 return pImpl
? pImpl
->end() : nullptr;
1989 //===----------------------------------------------------------------------===//
1990 // AttributeList Introspection Methods
1991 //===----------------------------------------------------------------------===//
1993 unsigned AttributeList::getNumAttrSets() const {
1994 return pImpl
? pImpl
->NumAttrSets
: 0;
1997 void AttributeList::print(raw_ostream
&O
) const {
1998 O
<< "AttributeList[\n";
2000 for (unsigned i
: indexes()) {
2001 if (!getAttributes(i
).hasAttributes())
2005 case AttrIndex::ReturnIndex
:
2008 case AttrIndex::FunctionIndex
:
2012 O
<< "arg(" << i
- AttrIndex::FirstArgIndex
<< ")";
2014 O
<< " => " << getAsString(i
) << " }\n";
2020 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2021 LLVM_DUMP_METHOD
void AttributeList::dump() const { print(dbgs()); }
2024 //===----------------------------------------------------------------------===//
2025 // AttrBuilder Method Implementations
2026 //===----------------------------------------------------------------------===//
2028 AttrBuilder::AttrBuilder(LLVMContext
&Ctx
, AttributeSet AS
) : Ctx(Ctx
) {
2029 append_range(Attrs
, AS
);
2030 assert(is_sorted(Attrs
) && "AttributeSet should be sorted");
2033 void AttrBuilder::clear() { Attrs
.clear(); }
2035 /// Attribute comparator that only compares attribute keys. Enum attributes are
2036 /// sorted before string attributes.
2037 struct AttributeComparator
{
2038 bool operator()(Attribute A0
, Attribute A1
) const {
2039 bool A0IsString
= A0
.isStringAttribute();
2040 bool A1IsString
= A1
.isStringAttribute();
2043 return A0
.getKindAsString() < A1
.getKindAsString();
2049 return A0
.getKindAsEnum() < A1
.getKindAsEnum();
2051 bool operator()(Attribute A0
, Attribute::AttrKind Kind
) const {
2052 if (A0
.isStringAttribute())
2054 return A0
.getKindAsEnum() < Kind
;
2056 bool operator()(Attribute A0
, StringRef Kind
) const {
2057 if (A0
.isStringAttribute())
2058 return A0
.getKindAsString() < Kind
;
2063 template <typename K
>
2064 static void addAttributeImpl(SmallVectorImpl
<Attribute
> &Attrs
, K Kind
,
2066 auto It
= lower_bound(Attrs
, Kind
, AttributeComparator());
2067 if (It
!= Attrs
.end() && It
->hasAttribute(Kind
))
2068 std::swap(*It
, Attr
);
2070 Attrs
.insert(It
, Attr
);
2073 AttrBuilder
&AttrBuilder::addAttribute(Attribute Attr
) {
2074 if (Attr
.isStringAttribute())
2075 addAttributeImpl(Attrs
, Attr
.getKindAsString(), Attr
);
2077 addAttributeImpl(Attrs
, Attr
.getKindAsEnum(), Attr
);
2081 AttrBuilder
&AttrBuilder::addAttribute(Attribute::AttrKind Kind
) {
2082 addAttributeImpl(Attrs
, Kind
, Attribute::get(Ctx
, Kind
));
2086 AttrBuilder
&AttrBuilder::addAttribute(StringRef A
, StringRef V
) {
2087 addAttributeImpl(Attrs
, A
, Attribute::get(Ctx
, A
, V
));
2091 AttrBuilder
&AttrBuilder::removeAttribute(Attribute::AttrKind Val
) {
2092 assert((unsigned)Val
< Attribute::EndAttrKinds
&& "Attribute out of range!");
2093 auto It
= lower_bound(Attrs
, Val
, AttributeComparator());
2094 if (It
!= Attrs
.end() && It
->hasAttribute(Val
))
2099 AttrBuilder
&AttrBuilder::removeAttribute(StringRef A
) {
2100 auto It
= lower_bound(Attrs
, A
, AttributeComparator());
2101 if (It
!= Attrs
.end() && It
->hasAttribute(A
))
2106 std::optional
<uint64_t>
2107 AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind
) const {
2108 assert(Attribute::isIntAttrKind(Kind
) && "Not an int attribute");
2109 Attribute A
= getAttribute(Kind
);
2111 return A
.getValueAsInt();
2112 return std::nullopt
;
2115 AttrBuilder
&AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind
,
2117 return addAttribute(Attribute::get(Ctx
, Kind
, Value
));
2120 std::optional
<std::pair
<unsigned, std::optional
<unsigned>>>
2121 AttrBuilder::getAllocSizeArgs() const {
2122 Attribute A
= getAttribute(Attribute::AllocSize
);
2124 return A
.getAllocSizeArgs();
2125 return std::nullopt
;
2128 AttrBuilder
&AttrBuilder::addAlignmentAttr(MaybeAlign Align
) {
2132 assert(*Align
<= llvm::Value::MaximumAlignment
&& "Alignment too large.");
2133 return addRawIntAttr(Attribute::Alignment
, Align
->value());
2136 AttrBuilder
&AttrBuilder::addStackAlignmentAttr(MaybeAlign Align
) {
2137 // Default alignment, allow the target to define how to align it.
2141 assert(*Align
<= 0x100 && "Alignment too large.");
2142 return addRawIntAttr(Attribute::StackAlignment
, Align
->value());
2145 AttrBuilder
&AttrBuilder::addDereferenceableAttr(uint64_t Bytes
) {
2146 if (Bytes
== 0) return *this;
2148 return addRawIntAttr(Attribute::Dereferenceable
, Bytes
);
2151 AttrBuilder
&AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes
) {
2155 return addRawIntAttr(Attribute::DereferenceableOrNull
, Bytes
);
2159 AttrBuilder::addAllocSizeAttr(unsigned ElemSize
,
2160 const std::optional
<unsigned> &NumElems
) {
2161 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize
, NumElems
));
2164 AttrBuilder
&AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs
) {
2165 // (0, 0) is our "not present" value, so we need to check for it here.
2166 assert(RawArgs
&& "Invalid allocsize arguments -- given allocsize(0, 0)");
2167 return addRawIntAttr(Attribute::AllocSize
, RawArgs
);
2170 AttrBuilder
&AttrBuilder::addVScaleRangeAttr(unsigned MinValue
,
2171 std::optional
<unsigned> MaxValue
) {
2172 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue
, MaxValue
));
2175 AttrBuilder
&AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs
) {
2176 // (0, 0) is not present hence ignore this case
2180 return addRawIntAttr(Attribute::VScaleRange
, RawArgs
);
2183 AttrBuilder
&AttrBuilder::addUWTableAttr(UWTableKind Kind
) {
2184 if (Kind
== UWTableKind::None
)
2186 return addRawIntAttr(Attribute::UWTable
, uint64_t(Kind
));
2189 AttrBuilder
&AttrBuilder::addMemoryAttr(MemoryEffects ME
) {
2190 return addRawIntAttr(Attribute::Memory
, ME
.toIntValue());
2193 AttrBuilder
&AttrBuilder::addNoFPClassAttr(FPClassTest Mask
) {
2197 return addRawIntAttr(Attribute::NoFPClass
, Mask
);
2200 AttrBuilder
&AttrBuilder::addAllocKindAttr(AllocFnKind Kind
) {
2201 return addRawIntAttr(Attribute::AllocKind
, static_cast<uint64_t>(Kind
));
2204 Type
*AttrBuilder::getTypeAttr(Attribute::AttrKind Kind
) const {
2205 assert(Attribute::isTypeAttrKind(Kind
) && "Not a type attribute");
2206 Attribute A
= getAttribute(Kind
);
2207 return A
.isValid() ? A
.getValueAsType() : nullptr;
2210 AttrBuilder
&AttrBuilder::addTypeAttr(Attribute::AttrKind Kind
, Type
*Ty
) {
2211 return addAttribute(Attribute::get(Ctx
, Kind
, Ty
));
2214 AttrBuilder
&AttrBuilder::addByValAttr(Type
*Ty
) {
2215 return addTypeAttr(Attribute::ByVal
, Ty
);
2218 AttrBuilder
&AttrBuilder::addStructRetAttr(Type
*Ty
) {
2219 return addTypeAttr(Attribute::StructRet
, Ty
);
2222 AttrBuilder
&AttrBuilder::addByRefAttr(Type
*Ty
) {
2223 return addTypeAttr(Attribute::ByRef
, Ty
);
2226 AttrBuilder
&AttrBuilder::addPreallocatedAttr(Type
*Ty
) {
2227 return addTypeAttr(Attribute::Preallocated
, Ty
);
2230 AttrBuilder
&AttrBuilder::addInAllocaAttr(Type
*Ty
) {
2231 return addTypeAttr(Attribute::InAlloca
, Ty
);
2234 AttrBuilder
&AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind
,
2235 const ConstantRange
&CR
) {
2239 return addAttribute(Attribute::get(Ctx
, Kind
, CR
));
2242 AttrBuilder
&AttrBuilder::addRangeAttr(const ConstantRange
&CR
) {
2243 return addConstantRangeAttr(Attribute::Range
, CR
);
2247 AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind
,
2248 ArrayRef
<ConstantRange
> Val
) {
2249 return addAttribute(Attribute::get(Ctx
, Kind
, Val
));
2252 AttrBuilder
&AttrBuilder::addInitializesAttr(const ConstantRangeList
&CRL
) {
2253 return addConstantRangeListAttr(Attribute::Initializes
, CRL
.rangesRef());
2256 AttrBuilder
&AttrBuilder::merge(const AttrBuilder
&B
) {
2257 // TODO: Could make this O(n) as we're merging two sorted lists.
2258 for (const auto &I
: B
.attrs())
2264 AttrBuilder
&AttrBuilder::remove(const AttributeMask
&AM
) {
2265 erase_if(Attrs
, [&](Attribute A
) { return AM
.contains(A
); });
2269 bool AttrBuilder::overlaps(const AttributeMask
&AM
) const {
2270 return any_of(Attrs
, [&](Attribute A
) { return AM
.contains(A
); });
2273 Attribute
AttrBuilder::getAttribute(Attribute::AttrKind A
) const {
2274 assert((unsigned)A
< Attribute::EndAttrKinds
&& "Attribute out of range!");
2275 auto It
= lower_bound(Attrs
, A
, AttributeComparator());
2276 if (It
!= Attrs
.end() && It
->hasAttribute(A
))
2281 Attribute
AttrBuilder::getAttribute(StringRef A
) const {
2282 auto It
= lower_bound(Attrs
, A
, AttributeComparator());
2283 if (It
!= Attrs
.end() && It
->hasAttribute(A
))
2288 std::optional
<ConstantRange
> AttrBuilder::getRange() const {
2289 const Attribute RangeAttr
= getAttribute(Attribute::Range
);
2290 if (RangeAttr
.isValid())
2291 return RangeAttr
.getRange();
2292 return std::nullopt
;
2295 bool AttrBuilder::contains(Attribute::AttrKind A
) const {
2296 return getAttribute(A
).isValid();
2299 bool AttrBuilder::contains(StringRef A
) const {
2300 return getAttribute(A
).isValid();
2303 bool AttrBuilder::operator==(const AttrBuilder
&B
) const {
2304 return Attrs
== B
.Attrs
;
2307 //===----------------------------------------------------------------------===//
2308 // AttributeFuncs Function Defintions
2309 //===----------------------------------------------------------------------===//
2311 /// Returns true if this is a type legal for the 'nofpclass' attribute. This
2312 /// follows the same type rules as FPMathOperator.
2313 bool AttributeFuncs::isNoFPClassCompatibleType(Type
*Ty
) {
2314 return FPMathOperator::isSupportedFloatingPointType(Ty
);
2317 /// Which attributes cannot be applied to a type.
2318 AttributeMask
AttributeFuncs::typeIncompatible(Type
*Ty
, AttributeSet AS
,
2319 AttributeSafetyKind ASK
) {
2320 AttributeMask Incompatible
;
2322 if (!Ty
->isIntegerTy()) {
2323 // Attributes that only apply to integers.
2324 if (ASK
& ASK_SAFE_TO_DROP
)
2325 Incompatible
.addAttribute(Attribute::AllocAlign
);
2326 if (ASK
& ASK_UNSAFE_TO_DROP
)
2327 Incompatible
.addAttribute(Attribute::SExt
).addAttribute(Attribute::ZExt
);
2330 if (!Ty
->isIntOrIntVectorTy()) {
2331 // Attributes that only apply to integers or vector of integers.
2332 if (ASK
& ASK_SAFE_TO_DROP
)
2333 Incompatible
.addAttribute(Attribute::Range
);
2335 Attribute RangeAttr
= AS
.getAttribute(Attribute::Range
);
2336 if (RangeAttr
.isValid() &&
2337 RangeAttr
.getRange().getBitWidth() != Ty
->getScalarSizeInBits())
2338 Incompatible
.addAttribute(Attribute::Range
);
2341 if (!Ty
->isPointerTy()) {
2342 // Attributes that only apply to pointers.
2343 if (ASK
& ASK_SAFE_TO_DROP
)
2344 Incompatible
.addAttribute(Attribute::NoAlias
)
2345 .addAttribute(Attribute::NoCapture
)
2346 .addAttribute(Attribute::NonNull
)
2347 .addAttribute(Attribute::ReadNone
)
2348 .addAttribute(Attribute::ReadOnly
)
2349 .addAttribute(Attribute::Dereferenceable
)
2350 .addAttribute(Attribute::DereferenceableOrNull
)
2351 .addAttribute(Attribute::Writable
)
2352 .addAttribute(Attribute::DeadOnUnwind
)
2353 .addAttribute(Attribute::Initializes
);
2354 if (ASK
& ASK_UNSAFE_TO_DROP
)
2355 Incompatible
.addAttribute(Attribute::Nest
)
2356 .addAttribute(Attribute::SwiftError
)
2357 .addAttribute(Attribute::Preallocated
)
2358 .addAttribute(Attribute::InAlloca
)
2359 .addAttribute(Attribute::ByVal
)
2360 .addAttribute(Attribute::StructRet
)
2361 .addAttribute(Attribute::ByRef
)
2362 .addAttribute(Attribute::ElementType
)
2363 .addAttribute(Attribute::AllocatedPointer
);
2366 // Attributes that only apply to pointers or vectors of pointers.
2367 if (!Ty
->isPtrOrPtrVectorTy()) {
2368 if (ASK
& ASK_SAFE_TO_DROP
)
2369 Incompatible
.addAttribute(Attribute::Alignment
);
2372 if (ASK
& ASK_SAFE_TO_DROP
) {
2373 if (!isNoFPClassCompatibleType(Ty
))
2374 Incompatible
.addAttribute(Attribute::NoFPClass
);
2377 // Some attributes can apply to all "values" but there are no `void` values.
2378 if (Ty
->isVoidTy()) {
2379 if (ASK
& ASK_SAFE_TO_DROP
)
2380 Incompatible
.addAttribute(Attribute::NoUndef
);
2383 return Incompatible
;
2386 AttributeMask
AttributeFuncs::getUBImplyingAttributes() {
2388 AM
.addAttribute(Attribute::NoUndef
);
2389 AM
.addAttribute(Attribute::Dereferenceable
);
2390 AM
.addAttribute(Attribute::DereferenceableOrNull
);
2394 /// Callees with dynamic denormal modes are compatible with any caller mode.
2395 static bool denormModeCompatible(DenormalMode CallerMode
,
2396 DenormalMode CalleeMode
) {
2397 if (CallerMode
== CalleeMode
|| CalleeMode
== DenormalMode::getDynamic())
2400 // If they don't exactly match, it's OK if the mismatched component is
2402 if (CalleeMode
.Input
== CallerMode
.Input
&&
2403 CalleeMode
.Output
== DenormalMode::Dynamic
)
2406 if (CalleeMode
.Output
== CallerMode
.Output
&&
2407 CalleeMode
.Input
== DenormalMode::Dynamic
)
2412 static bool checkDenormMode(const Function
&Caller
, const Function
&Callee
) {
2413 DenormalMode CallerMode
= Caller
.getDenormalModeRaw();
2414 DenormalMode CalleeMode
= Callee
.getDenormalModeRaw();
2416 if (denormModeCompatible(CallerMode
, CalleeMode
)) {
2417 DenormalMode CallerModeF32
= Caller
.getDenormalModeF32Raw();
2418 DenormalMode CalleeModeF32
= Callee
.getDenormalModeF32Raw();
2419 if (CallerModeF32
== DenormalMode::getInvalid())
2420 CallerModeF32
= CallerMode
;
2421 if (CalleeModeF32
== DenormalMode::getInvalid())
2422 CalleeModeF32
= CalleeMode
;
2423 return denormModeCompatible(CallerModeF32
, CalleeModeF32
);
2429 static bool checkStrictFP(const Function
&Caller
, const Function
&Callee
) {
2430 // Do not inline strictfp function into non-strictfp one. It would require
2431 // conversion of all FP operations in host function to constrained intrinsics.
2432 return !Callee
.getAttributes().hasFnAttr(Attribute::StrictFP
) ||
2433 Caller
.getAttributes().hasFnAttr(Attribute::StrictFP
);
2436 template<typename AttrClass
>
2437 static bool isEqual(const Function
&Caller
, const Function
&Callee
) {
2438 return Caller
.getFnAttribute(AttrClass::getKind()) ==
2439 Callee
.getFnAttribute(AttrClass::getKind());
2442 static bool isEqual(const Function
&Caller
, const Function
&Callee
,
2443 const StringRef
&AttrName
) {
2444 return Caller
.getFnAttribute(AttrName
) == Callee
.getFnAttribute(AttrName
);
2447 /// Compute the logical AND of the attributes of the caller and the
2450 /// This function sets the caller's attribute to false if the callee's attribute
2452 template<typename AttrClass
>
2453 static void setAND(Function
&Caller
, const Function
&Callee
) {
2454 if (AttrClass::isSet(Caller
, AttrClass::getKind()) &&
2455 !AttrClass::isSet(Callee
, AttrClass::getKind()))
2456 AttrClass::set(Caller
, AttrClass::getKind(), false);
2459 /// Compute the logical OR of the attributes of the caller and the
2462 /// This function sets the caller's attribute to true if the callee's attribute
2464 template<typename AttrClass
>
2465 static void setOR(Function
&Caller
, const Function
&Callee
) {
2466 if (!AttrClass::isSet(Caller
, AttrClass::getKind()) &&
2467 AttrClass::isSet(Callee
, AttrClass::getKind()))
2468 AttrClass::set(Caller
, AttrClass::getKind(), true);
2471 /// If the inlined function had a higher stack protection level than the
2472 /// calling function, then bump up the caller's stack protection level.
2473 static void adjustCallerSSPLevel(Function
&Caller
, const Function
&Callee
) {
2474 // If the calling function has *no* stack protection level (e.g. it was built
2475 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2476 // change it as that could change the program's semantics.
2477 if (!Caller
.hasStackProtectorFnAttr())
2480 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2481 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2482 // clutter to the IR.
2483 AttributeMask OldSSPAttr
;
2484 OldSSPAttr
.addAttribute(Attribute::StackProtect
)
2485 .addAttribute(Attribute::StackProtectStrong
)
2486 .addAttribute(Attribute::StackProtectReq
);
2488 if (Callee
.hasFnAttribute(Attribute::StackProtectReq
)) {
2489 Caller
.removeFnAttrs(OldSSPAttr
);
2490 Caller
.addFnAttr(Attribute::StackProtectReq
);
2491 } else if (Callee
.hasFnAttribute(Attribute::StackProtectStrong
) &&
2492 !Caller
.hasFnAttribute(Attribute::StackProtectReq
)) {
2493 Caller
.removeFnAttrs(OldSSPAttr
);
2494 Caller
.addFnAttr(Attribute::StackProtectStrong
);
2495 } else if (Callee
.hasFnAttribute(Attribute::StackProtect
) &&
2496 !Caller
.hasFnAttribute(Attribute::StackProtectReq
) &&
2497 !Caller
.hasFnAttribute(Attribute::StackProtectStrong
))
2498 Caller
.addFnAttr(Attribute::StackProtect
);
2501 /// If the inlined function required stack probes, then ensure that
2502 /// the calling function has those too.
2503 static void adjustCallerStackProbes(Function
&Caller
, const Function
&Callee
) {
2504 if (!Caller
.hasFnAttribute("probe-stack") &&
2505 Callee
.hasFnAttribute("probe-stack")) {
2506 Caller
.addFnAttr(Callee
.getFnAttribute("probe-stack"));
2510 /// If the inlined function defines the size of guard region
2511 /// on the stack, then ensure that the calling function defines a guard region
2512 /// that is no larger.
2514 adjustCallerStackProbeSize(Function
&Caller
, const Function
&Callee
) {
2515 Attribute CalleeAttr
= Callee
.getFnAttribute("stack-probe-size");
2516 if (CalleeAttr
.isValid()) {
2517 Attribute CallerAttr
= Caller
.getFnAttribute("stack-probe-size");
2518 if (CallerAttr
.isValid()) {
2519 uint64_t CallerStackProbeSize
, CalleeStackProbeSize
;
2520 CallerAttr
.getValueAsString().getAsInteger(0, CallerStackProbeSize
);
2521 CalleeAttr
.getValueAsString().getAsInteger(0, CalleeStackProbeSize
);
2523 if (CallerStackProbeSize
> CalleeStackProbeSize
) {
2524 Caller
.addFnAttr(CalleeAttr
);
2527 Caller
.addFnAttr(CalleeAttr
);
2532 /// If the inlined function defines a min legal vector width, then ensure
2533 /// the calling function has the same or larger min legal vector width. If the
2534 /// caller has the attribute, but the callee doesn't, we need to remove the
2535 /// attribute from the caller since we can't make any guarantees about the
2536 /// caller's requirements.
2537 /// This function is called after the inlining decision has been made so we have
2538 /// to merge the attribute this way. Heuristics that would use
2539 /// min-legal-vector-width to determine inline compatibility would need to be
2540 /// handled as part of inline cost analysis.
2542 adjustMinLegalVectorWidth(Function
&Caller
, const Function
&Callee
) {
2543 Attribute CallerAttr
= Caller
.getFnAttribute("min-legal-vector-width");
2544 if (CallerAttr
.isValid()) {
2545 Attribute CalleeAttr
= Callee
.getFnAttribute("min-legal-vector-width");
2546 if (CalleeAttr
.isValid()) {
2547 uint64_t CallerVectorWidth
, CalleeVectorWidth
;
2548 CallerAttr
.getValueAsString().getAsInteger(0, CallerVectorWidth
);
2549 CalleeAttr
.getValueAsString().getAsInteger(0, CalleeVectorWidth
);
2550 if (CallerVectorWidth
< CalleeVectorWidth
)
2551 Caller
.addFnAttr(CalleeAttr
);
2553 // If the callee doesn't have the attribute then we don't know anything
2554 // and must drop the attribute from the caller.
2555 Caller
.removeFnAttr("min-legal-vector-width");
2560 /// If the inlined function has null_pointer_is_valid attribute,
2561 /// set this attribute in the caller post inlining.
2563 adjustNullPointerValidAttr(Function
&Caller
, const Function
&Callee
) {
2564 if (Callee
.nullPointerIsDefined() && !Caller
.nullPointerIsDefined()) {
2565 Caller
.addFnAttr(Attribute::NullPointerIsValid
);
2570 static bool isSet(const Function
&Fn
,
2571 Attribute::AttrKind Kind
) {
2572 return Fn
.hasFnAttribute(Kind
);
2575 static void set(Function
&Fn
,
2576 Attribute::AttrKind Kind
, bool Val
) {
2580 Fn
.removeFnAttr(Kind
);
2584 struct StrBoolAttr
{
2585 static bool isSet(const Function
&Fn
,
2587 auto A
= Fn
.getFnAttribute(Kind
);
2588 return A
.getValueAsString() == "true";
2591 static void set(Function
&Fn
,
2592 StringRef Kind
, bool Val
) {
2593 Fn
.addFnAttr(Kind
, Val
? "true" : "false");
2597 #define GET_ATTR_NAMES
2598 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2599 struct ENUM_NAME##Attr : EnumAttr { \
2600 static enum Attribute::AttrKind getKind() { \
2601 return llvm::Attribute::ENUM_NAME; \
2604 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2605 struct ENUM_NAME##Attr : StrBoolAttr { \
2606 static StringRef getKind() { return #DISPLAY_NAME; } \
2608 #include "llvm/IR/Attributes.inc"
2610 #define GET_ATTR_COMPAT_FUNC
2611 #include "llvm/IR/Attributes.inc"
2613 bool AttributeFuncs::areInlineCompatible(const Function
&Caller
,
2614 const Function
&Callee
) {
2615 return hasCompatibleFnAttrs(Caller
, Callee
);
2618 bool AttributeFuncs::areOutlineCompatible(const Function
&A
,
2619 const Function
&B
) {
2620 return hasCompatibleFnAttrs(A
, B
);
2623 void AttributeFuncs::mergeAttributesForInlining(Function
&Caller
,
2624 const Function
&Callee
) {
2625 mergeFnAttrs(Caller
, Callee
);
2628 void AttributeFuncs::mergeAttributesForOutlining(Function
&Base
,
2629 const Function
&ToMerge
) {
2631 // We merge functions so that they meet the most general case.
2632 // For example, if the NoNansFPMathAttr is set in one function, but not in
2633 // the other, in the merged function we can say that the NoNansFPMathAttr
2635 // However if we have the SpeculativeLoadHardeningAttr set true in one
2636 // function, but not the other, we make sure that the function retains
2637 // that aspect in the merged function.
2638 mergeFnAttrs(Base
, ToMerge
);
2641 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function
&Fn
,
2643 Attribute Attr
= Fn
.getFnAttribute("min-legal-vector-width");
2644 if (Attr
.isValid()) {
2646 Attr
.getValueAsString().getAsInteger(0, OldWidth
);
2647 if (Width
> OldWidth
)
2648 Fn
.addFnAttr("min-legal-vector-width", llvm::utostr(Width
));