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/Function.h"
28 #include "llvm/IR/LLVMContext.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/ModRef.h"
33 #include "llvm/Support/raw_ostream.h"
46 //===----------------------------------------------------------------------===//
47 // Attribute Construction Methods
48 //===----------------------------------------------------------------------===//
50 // allocsize has two integer arguments, but because they're both 32 bits, we can
51 // pack them into one 64-bit value, at the cost of making said value
54 // In order to do this, we need to reserve one value of the second (optional)
55 // allocsize argument to signify "not present."
56 static const unsigned AllocSizeNumElemsNotPresent
= -1;
58 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg
,
59 const std::optional
<unsigned> &NumElemsArg
) {
60 assert((!NumElemsArg
|| *NumElemsArg
!= AllocSizeNumElemsNotPresent
) &&
61 "Attempting to pack a reserved value");
63 return uint64_t(ElemSizeArg
) << 32 |
64 NumElemsArg
.value_or(AllocSizeNumElemsNotPresent
);
67 static std::pair
<unsigned, std::optional
<unsigned>>
68 unpackAllocSizeArgs(uint64_t Num
) {
69 unsigned NumElems
= Num
& std::numeric_limits
<unsigned>::max();
70 unsigned ElemSizeArg
= Num
>> 32;
72 std::optional
<unsigned> NumElemsArg
;
73 if (NumElems
!= AllocSizeNumElemsNotPresent
)
74 NumElemsArg
= NumElems
;
75 return std::make_pair(ElemSizeArg
, NumElemsArg
);
78 static uint64_t packVScaleRangeArgs(unsigned MinValue
,
79 std::optional
<unsigned> MaxValue
) {
80 return uint64_t(MinValue
) << 32 | MaxValue
.value_or(0);
83 static std::pair
<unsigned, std::optional
<unsigned>>
84 unpackVScaleRangeArgs(uint64_t Value
) {
85 unsigned MaxValue
= Value
& std::numeric_limits
<unsigned>::max();
86 unsigned MinValue
= Value
>> 32;
88 return std::make_pair(MinValue
,
89 MaxValue
> 0 ? MaxValue
: std::optional
<unsigned>());
92 Attribute
Attribute::get(LLVMContext
&Context
, Attribute::AttrKind Kind
,
94 bool IsIntAttr
= Attribute::isIntAttrKind(Kind
);
95 assert((IsIntAttr
|| Attribute::isEnumAttrKind(Kind
)) &&
96 "Not an enum or int attribute");
98 LLVMContextImpl
*pImpl
= Context
.pImpl
;
104 assert(Val
== 0 && "Value must be zero for enum attributes");
107 AttributeImpl
*PA
= pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, InsertPoint
);
110 // If we didn't find any existing attributes of the same shape then create a
111 // new one and insert it.
113 PA
= new (pImpl
->Alloc
) EnumAttributeImpl(Kind
);
115 PA
= new (pImpl
->Alloc
) IntAttributeImpl(Kind
, Val
);
116 pImpl
->AttrsSet
.InsertNode(PA
, InsertPoint
);
119 // Return the Attribute that we found or created.
120 return Attribute(PA
);
123 Attribute
Attribute::get(LLVMContext
&Context
, StringRef Kind
, StringRef Val
) {
124 LLVMContextImpl
*pImpl
= Context
.pImpl
;
127 if (!Val
.empty()) ID
.AddString(Val
);
130 AttributeImpl
*PA
= pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, InsertPoint
);
133 // If we didn't find any existing attributes of the same shape then create a
134 // new one and insert it.
136 pImpl
->Alloc
.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind
, Val
),
137 alignof(StringAttributeImpl
));
138 PA
= new (Mem
) StringAttributeImpl(Kind
, Val
);
139 pImpl
->AttrsSet
.InsertNode(PA
, InsertPoint
);
142 // Return the Attribute that we found or created.
143 return Attribute(PA
);
146 Attribute
Attribute::get(LLVMContext
&Context
, Attribute::AttrKind Kind
,
148 assert(Attribute::isTypeAttrKind(Kind
) && "Not a type attribute");
149 LLVMContextImpl
*pImpl
= Context
.pImpl
;
155 AttributeImpl
*PA
= pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, InsertPoint
);
158 // If we didn't find any existing attributes of the same shape then create a
159 // new one and insert it.
160 PA
= new (pImpl
->Alloc
) TypeAttributeImpl(Kind
, Ty
);
161 pImpl
->AttrsSet
.InsertNode(PA
, InsertPoint
);
164 // Return the Attribute that we found or created.
165 return Attribute(PA
);
168 Attribute
Attribute::getWithAlignment(LLVMContext
&Context
, Align A
) {
169 assert(A
<= llvm::Value::MaximumAlignment
&& "Alignment too large.");
170 return get(Context
, Alignment
, A
.value());
173 Attribute
Attribute::getWithStackAlignment(LLVMContext
&Context
, Align A
) {
174 assert(A
<= 0x100 && "Alignment too large.");
175 return get(Context
, StackAlignment
, A
.value());
178 Attribute
Attribute::getWithDereferenceableBytes(LLVMContext
&Context
,
180 assert(Bytes
&& "Bytes must be non-zero.");
181 return get(Context
, Dereferenceable
, Bytes
);
184 Attribute
Attribute::getWithDereferenceableOrNullBytes(LLVMContext
&Context
,
186 assert(Bytes
&& "Bytes must be non-zero.");
187 return get(Context
, DereferenceableOrNull
, Bytes
);
190 Attribute
Attribute::getWithByValType(LLVMContext
&Context
, Type
*Ty
) {
191 return get(Context
, ByVal
, Ty
);
194 Attribute
Attribute::getWithStructRetType(LLVMContext
&Context
, Type
*Ty
) {
195 return get(Context
, StructRet
, Ty
);
198 Attribute
Attribute::getWithByRefType(LLVMContext
&Context
, Type
*Ty
) {
199 return get(Context
, ByRef
, Ty
);
202 Attribute
Attribute::getWithPreallocatedType(LLVMContext
&Context
, Type
*Ty
) {
203 return get(Context
, Preallocated
, Ty
);
206 Attribute
Attribute::getWithInAllocaType(LLVMContext
&Context
, Type
*Ty
) {
207 return get(Context
, InAlloca
, Ty
);
210 Attribute
Attribute::getWithUWTableKind(LLVMContext
&Context
,
212 return get(Context
, UWTable
, uint64_t(Kind
));
215 Attribute
Attribute::getWithMemoryEffects(LLVMContext
&Context
,
217 return get(Context
, Memory
, ME
.toIntValue());
220 Attribute
Attribute::getWithNoFPClass(LLVMContext
&Context
,
221 FPClassTest ClassMask
) {
222 return get(Context
, NoFPClass
, ClassMask
);
226 Attribute::getWithAllocSizeArgs(LLVMContext
&Context
, unsigned ElemSizeArg
,
227 const std::optional
<unsigned> &NumElemsArg
) {
228 assert(!(ElemSizeArg
== 0 && NumElemsArg
&& *NumElemsArg
== 0) &&
229 "Invalid allocsize arguments -- given allocsize(0, 0)");
230 return get(Context
, AllocSize
, packAllocSizeArgs(ElemSizeArg
, NumElemsArg
));
233 Attribute
Attribute::getWithVScaleRangeArgs(LLVMContext
&Context
,
236 return get(Context
, VScaleRange
, packVScaleRangeArgs(MinValue
, MaxValue
));
239 Attribute::AttrKind
Attribute::getAttrKindFromName(StringRef AttrName
) {
240 return StringSwitch
<Attribute::AttrKind
>(AttrName
)
241 #define GET_ATTR_NAMES
242 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
243 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
244 #include "llvm/IR/Attributes.inc"
245 .Default(Attribute::None
);
248 StringRef
Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind
) {
250 #define GET_ATTR_NAMES
251 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
252 case Attribute::ENUM_NAME: \
253 return #DISPLAY_NAME;
254 #include "llvm/IR/Attributes.inc"
255 case Attribute::None
:
258 llvm_unreachable("invalid Kind");
262 bool Attribute::isExistingAttribute(StringRef Name
) {
263 return StringSwitch
<bool>(Name
)
264 #define GET_ATTR_NAMES
265 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
266 #include "llvm/IR/Attributes.inc"
270 //===----------------------------------------------------------------------===//
271 // Attribute Accessor Methods
272 //===----------------------------------------------------------------------===//
274 bool Attribute::isEnumAttribute() const {
275 return pImpl
&& pImpl
->isEnumAttribute();
278 bool Attribute::isIntAttribute() const {
279 return pImpl
&& pImpl
->isIntAttribute();
282 bool Attribute::isStringAttribute() const {
283 return pImpl
&& pImpl
->isStringAttribute();
286 bool Attribute::isTypeAttribute() const {
287 return pImpl
&& pImpl
->isTypeAttribute();
290 Attribute::AttrKind
Attribute::getKindAsEnum() const {
291 if (!pImpl
) return None
;
292 assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
293 "Invalid attribute type to get the kind as an enum!");
294 return pImpl
->getKindAsEnum();
297 uint64_t Attribute::getValueAsInt() const {
298 if (!pImpl
) return 0;
299 assert(isIntAttribute() &&
300 "Expected the attribute to be an integer attribute!");
301 return pImpl
->getValueAsInt();
304 bool Attribute::getValueAsBool() const {
305 if (!pImpl
) return false;
306 assert(isStringAttribute() &&
307 "Expected the attribute to be a string attribute!");
308 return pImpl
->getValueAsBool();
311 StringRef
Attribute::getKindAsString() const {
312 if (!pImpl
) return {};
313 assert(isStringAttribute() &&
314 "Invalid attribute type to get the kind as a string!");
315 return pImpl
->getKindAsString();
318 StringRef
Attribute::getValueAsString() const {
319 if (!pImpl
) return {};
320 assert(isStringAttribute() &&
321 "Invalid attribute type to get the value as a string!");
322 return pImpl
->getValueAsString();
325 Type
*Attribute::getValueAsType() const {
326 if (!pImpl
) return {};
327 assert(isTypeAttribute() &&
328 "Invalid attribute type to get the value as a type!");
329 return pImpl
->getValueAsType();
333 bool Attribute::hasAttribute(AttrKind Kind
) const {
334 return (pImpl
&& pImpl
->hasAttribute(Kind
)) || (!pImpl
&& Kind
== None
);
337 bool Attribute::hasAttribute(StringRef Kind
) const {
338 if (!isStringAttribute()) return false;
339 return pImpl
&& pImpl
->hasAttribute(Kind
);
342 MaybeAlign
Attribute::getAlignment() const {
343 assert(hasAttribute(Attribute::Alignment
) &&
344 "Trying to get alignment from non-alignment attribute!");
345 return MaybeAlign(pImpl
->getValueAsInt());
348 MaybeAlign
Attribute::getStackAlignment() const {
349 assert(hasAttribute(Attribute::StackAlignment
) &&
350 "Trying to get alignment from non-alignment attribute!");
351 return MaybeAlign(pImpl
->getValueAsInt());
354 uint64_t Attribute::getDereferenceableBytes() const {
355 assert(hasAttribute(Attribute::Dereferenceable
) &&
356 "Trying to get dereferenceable bytes from "
357 "non-dereferenceable attribute!");
358 return pImpl
->getValueAsInt();
361 uint64_t Attribute::getDereferenceableOrNullBytes() const {
362 assert(hasAttribute(Attribute::DereferenceableOrNull
) &&
363 "Trying to get dereferenceable bytes from "
364 "non-dereferenceable attribute!");
365 return pImpl
->getValueAsInt();
368 std::pair
<unsigned, std::optional
<unsigned>>
369 Attribute::getAllocSizeArgs() const {
370 assert(hasAttribute(Attribute::AllocSize
) &&
371 "Trying to get allocsize args from non-allocsize attribute");
372 return unpackAllocSizeArgs(pImpl
->getValueAsInt());
375 unsigned Attribute::getVScaleRangeMin() const {
376 assert(hasAttribute(Attribute::VScaleRange
) &&
377 "Trying to get vscale args from non-vscale attribute");
378 return unpackVScaleRangeArgs(pImpl
->getValueAsInt()).first
;
381 std::optional
<unsigned> Attribute::getVScaleRangeMax() const {
382 assert(hasAttribute(Attribute::VScaleRange
) &&
383 "Trying to get vscale args from non-vscale attribute");
384 return unpackVScaleRangeArgs(pImpl
->getValueAsInt()).second
;
387 UWTableKind
Attribute::getUWTableKind() const {
388 assert(hasAttribute(Attribute::UWTable
) &&
389 "Trying to get unwind table kind from non-uwtable attribute");
390 return UWTableKind(pImpl
->getValueAsInt());
393 AllocFnKind
Attribute::getAllocKind() const {
394 assert(hasAttribute(Attribute::AllocKind
) &&
395 "Trying to get allockind value from non-allockind attribute");
396 return AllocFnKind(pImpl
->getValueAsInt());
399 MemoryEffects
Attribute::getMemoryEffects() const {
400 assert(hasAttribute(Attribute::Memory
) &&
401 "Can only call getMemoryEffects() on memory attribute");
402 return MemoryEffects::createFromIntValue(pImpl
->getValueAsInt());
405 FPClassTest
Attribute::getNoFPClass() const {
406 assert(hasAttribute(Attribute::NoFPClass
) &&
407 "Can only call getNoFPClass() on nofpclass attribute");
408 return static_cast<FPClassTest
>(pImpl
->getValueAsInt());
411 static const char *getModRefStr(ModRefInfo MR
) {
413 case ModRefInfo::NoModRef
:
415 case ModRefInfo::Ref
:
417 case ModRefInfo::Mod
:
419 case ModRefInfo::ModRef
:
422 llvm_unreachable("Invalid ModRefInfo");
425 std::string
Attribute::getAsString(bool InAttrGrp
) const {
426 if (!pImpl
) return {};
428 if (isEnumAttribute())
429 return getNameFromAttrKind(getKindAsEnum()).str();
431 if (isTypeAttribute()) {
432 std::string Result
= getNameFromAttrKind(getKindAsEnum()).str();
434 raw_string_ostream
OS(Result
);
435 getValueAsType()->print(OS
, false, true);
441 // FIXME: These should be output like this:
446 if (hasAttribute(Attribute::Alignment
))
447 return (InAttrGrp
? "align=" + Twine(getValueAsInt())
448 : "align " + Twine(getValueAsInt()))
451 auto AttrWithBytesToString
= [&](const char *Name
) {
452 return (InAttrGrp
? Name
+ ("=" + Twine(getValueAsInt()))
453 : Name
+ ("(" + Twine(getValueAsInt())) + ")")
457 if (hasAttribute(Attribute::StackAlignment
))
458 return AttrWithBytesToString("alignstack");
460 if (hasAttribute(Attribute::Dereferenceable
))
461 return AttrWithBytesToString("dereferenceable");
463 if (hasAttribute(Attribute::DereferenceableOrNull
))
464 return AttrWithBytesToString("dereferenceable_or_null");
466 if (hasAttribute(Attribute::AllocSize
)) {
468 std::optional
<unsigned> NumElems
;
469 std::tie(ElemSize
, NumElems
) = getAllocSizeArgs();
472 ? "allocsize(" + Twine(ElemSize
) + "," + Twine(*NumElems
) + ")"
473 : "allocsize(" + Twine(ElemSize
) + ")")
477 if (hasAttribute(Attribute::VScaleRange
)) {
478 unsigned MinValue
= getVScaleRangeMin();
479 std::optional
<unsigned> MaxValue
= getVScaleRangeMax();
480 return ("vscale_range(" + Twine(MinValue
) + "," +
481 Twine(MaxValue
.value_or(0)) + ")")
485 if (hasAttribute(Attribute::UWTable
)) {
486 UWTableKind Kind
= getUWTableKind();
487 if (Kind
!= UWTableKind::None
) {
488 return Kind
== UWTableKind::Default
491 Twine(Kind
== UWTableKind::Sync
? "sync" : "async") + ")")
496 if (hasAttribute(Attribute::AllocKind
)) {
497 AllocFnKind Kind
= getAllocKind();
498 SmallVector
<StringRef
> parts
;
499 if ((Kind
& AllocFnKind::Alloc
) != AllocFnKind::Unknown
)
500 parts
.push_back("alloc");
501 if ((Kind
& AllocFnKind::Realloc
) != AllocFnKind::Unknown
)
502 parts
.push_back("realloc");
503 if ((Kind
& AllocFnKind::Free
) != AllocFnKind::Unknown
)
504 parts
.push_back("free");
505 if ((Kind
& AllocFnKind::Uninitialized
) != AllocFnKind::Unknown
)
506 parts
.push_back("uninitialized");
507 if ((Kind
& AllocFnKind::Zeroed
) != AllocFnKind::Unknown
)
508 parts
.push_back("zeroed");
509 if ((Kind
& AllocFnKind::Aligned
) != AllocFnKind::Unknown
)
510 parts
.push_back("aligned");
511 return ("allockind(\"" +
512 Twine(llvm::join(parts
.begin(), parts
.end(), ",")) + "\")")
516 if (hasAttribute(Attribute::Memory
)) {
518 raw_string_ostream
OS(Result
);
522 MemoryEffects ME
= getMemoryEffects();
524 // Print access kind for "other" as the default access kind. This way it
525 // will apply to any new location kinds that get split out of "other".
526 ModRefInfo OtherMR
= ME
.getModRef(IRMemLocation::Other
);
527 if (OtherMR
!= ModRefInfo::NoModRef
|| ME
.getModRef() == OtherMR
) {
529 OS
<< getModRefStr(OtherMR
);
532 for (auto Loc
: MemoryEffects::locations()) {
533 ModRefInfo MR
= ME
.getModRef(Loc
);
542 case IRMemLocation::ArgMem
:
545 case IRMemLocation::InaccessibleMem
:
546 OS
<< "inaccessiblemem: ";
548 case IRMemLocation::Other
:
549 llvm_unreachable("This is represented as the default access kind");
551 OS
<< getModRefStr(MR
);
558 if (hasAttribute(Attribute::NoFPClass
)) {
559 std::string Result
= "nofpclass";
560 raw_string_ostream
OS(Result
);
561 OS
<< getNoFPClass();
565 // Convert target-dependent attributes to strings of the form:
570 if (isStringAttribute()) {
573 raw_string_ostream
OS(Result
);
574 OS
<< '"' << getKindAsString() << '"';
576 // Since some attribute strings contain special characters that cannot be
577 // printable, those have to be escaped to make the attribute value
578 // printable as is. e.g. "\01__gnu_mcount_nc"
579 const auto &AttrVal
= pImpl
->getValueAsString();
580 if (!AttrVal
.empty()) {
582 printEscapedString(AttrVal
, OS
);
589 llvm_unreachable("Unknown attribute");
592 bool Attribute::hasParentContext(LLVMContext
&C
) const {
593 assert(isValid() && "invalid Attribute doesn't refer to any context");
597 return C
.pImpl
->AttrsSet
.FindNodeOrInsertPos(ID
, Unused
) == pImpl
;
600 bool Attribute::operator<(Attribute A
) const {
601 if (!pImpl
&& !A
.pImpl
) return false;
602 if (!pImpl
) return true;
603 if (!A
.pImpl
) return false;
604 return *pImpl
< *A
.pImpl
;
607 void Attribute::Profile(FoldingSetNodeID
&ID
) const {
608 ID
.AddPointer(pImpl
);
611 enum AttributeProperty
{
613 ParamAttr
= (1 << 1),
617 #define GET_ATTR_PROP_TABLE
618 #include "llvm/IR/Attributes.inc"
620 static bool hasAttributeProperty(Attribute::AttrKind Kind
,
621 AttributeProperty Prop
) {
622 unsigned Index
= Kind
- 1;
623 assert(Index
< std::size(AttrPropTable
) && "Invalid attribute kind");
624 return AttrPropTable
[Index
] & Prop
;
627 bool Attribute::canUseAsFnAttr(AttrKind Kind
) {
628 return hasAttributeProperty(Kind
, AttributeProperty::FnAttr
);
631 bool Attribute::canUseAsParamAttr(AttrKind Kind
) {
632 return hasAttributeProperty(Kind
, AttributeProperty::ParamAttr
);
635 bool Attribute::canUseAsRetAttr(AttrKind Kind
) {
636 return hasAttributeProperty(Kind
, AttributeProperty::RetAttr
);
639 //===----------------------------------------------------------------------===//
640 // AttributeImpl Definition
641 //===----------------------------------------------------------------------===//
643 bool AttributeImpl::hasAttribute(Attribute::AttrKind A
) const {
644 if (isStringAttribute()) return false;
645 return getKindAsEnum() == A
;
648 bool AttributeImpl::hasAttribute(StringRef Kind
) const {
649 if (!isStringAttribute()) return false;
650 return getKindAsString() == Kind
;
653 Attribute::AttrKind
AttributeImpl::getKindAsEnum() const {
654 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
655 return static_cast<const EnumAttributeImpl
*>(this)->getEnumKind();
658 uint64_t AttributeImpl::getValueAsInt() const {
659 assert(isIntAttribute());
660 return static_cast<const IntAttributeImpl
*>(this)->getValue();
663 bool AttributeImpl::getValueAsBool() const {
664 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
665 return getValueAsString() == "true";
668 StringRef
AttributeImpl::getKindAsString() const {
669 assert(isStringAttribute());
670 return static_cast<const StringAttributeImpl
*>(this)->getStringKind();
673 StringRef
AttributeImpl::getValueAsString() const {
674 assert(isStringAttribute());
675 return static_cast<const StringAttributeImpl
*>(this)->getStringValue();
678 Type
*AttributeImpl::getValueAsType() const {
679 assert(isTypeAttribute());
680 return static_cast<const TypeAttributeImpl
*>(this)->getTypeValue();
683 bool AttributeImpl::operator<(const AttributeImpl
&AI
) const {
687 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
688 // relative to their enum value) and then strings.
689 if (!isStringAttribute()) {
690 if (AI
.isStringAttribute())
692 if (getKindAsEnum() != AI
.getKindAsEnum())
693 return getKindAsEnum() < AI
.getKindAsEnum();
694 assert(!AI
.isEnumAttribute() && "Non-unique attribute");
695 assert(!AI
.isTypeAttribute() && "Comparison of types would be unstable");
696 // TODO: Is this actually needed?
697 assert(AI
.isIntAttribute() && "Only possibility left");
698 return getValueAsInt() < AI
.getValueAsInt();
701 if (!AI
.isStringAttribute())
703 if (getKindAsString() == AI
.getKindAsString())
704 return getValueAsString() < AI
.getValueAsString();
705 return getKindAsString() < AI
.getKindAsString();
708 //===----------------------------------------------------------------------===//
709 // AttributeSet Definition
710 //===----------------------------------------------------------------------===//
712 AttributeSet
AttributeSet::get(LLVMContext
&C
, const AttrBuilder
&B
) {
713 return AttributeSet(AttributeSetNode::get(C
, B
));
716 AttributeSet
AttributeSet::get(LLVMContext
&C
, ArrayRef
<Attribute
> Attrs
) {
717 return AttributeSet(AttributeSetNode::get(C
, Attrs
));
720 AttributeSet
AttributeSet::addAttribute(LLVMContext
&C
,
721 Attribute::AttrKind Kind
) const {
722 if (hasAttribute(Kind
)) return *this;
724 B
.addAttribute(Kind
);
725 return addAttributes(C
, AttributeSet::get(C
, B
));
728 AttributeSet
AttributeSet::addAttribute(LLVMContext
&C
, StringRef Kind
,
729 StringRef Value
) const {
731 B
.addAttribute(Kind
, Value
);
732 return addAttributes(C
, AttributeSet::get(C
, B
));
735 AttributeSet
AttributeSet::addAttributes(LLVMContext
&C
,
736 const AttributeSet AS
) const {
737 if (!hasAttributes())
740 if (!AS
.hasAttributes())
743 AttrBuilder
B(C
, *this);
744 B
.merge(AttrBuilder(C
, AS
));
748 AttributeSet
AttributeSet::removeAttribute(LLVMContext
&C
,
749 Attribute::AttrKind Kind
) const {
750 if (!hasAttribute(Kind
)) return *this;
751 AttrBuilder
B(C
, *this);
752 B
.removeAttribute(Kind
);
756 AttributeSet
AttributeSet::removeAttribute(LLVMContext
&C
,
757 StringRef Kind
) const {
758 if (!hasAttribute(Kind
)) return *this;
759 AttrBuilder
B(C
, *this);
760 B
.removeAttribute(Kind
);
764 AttributeSet
AttributeSet::removeAttributes(LLVMContext
&C
,
765 const AttributeMask
&Attrs
) const {
766 AttrBuilder
B(C
, *this);
767 // If there is nothing to remove, directly return the original set.
768 if (!B
.overlaps(Attrs
))
775 unsigned AttributeSet::getNumAttributes() const {
776 return SetNode
? SetNode
->getNumAttributes() : 0;
779 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind
) const {
780 return SetNode
? SetNode
->hasAttribute(Kind
) : false;
783 bool AttributeSet::hasAttribute(StringRef Kind
) const {
784 return SetNode
? SetNode
->hasAttribute(Kind
) : false;
787 Attribute
AttributeSet::getAttribute(Attribute::AttrKind Kind
) const {
788 return SetNode
? SetNode
->getAttribute(Kind
) : Attribute();
791 Attribute
AttributeSet::getAttribute(StringRef Kind
) const {
792 return SetNode
? SetNode
->getAttribute(Kind
) : Attribute();
795 MaybeAlign
AttributeSet::getAlignment() const {
796 return SetNode
? SetNode
->getAlignment() : std::nullopt
;
799 MaybeAlign
AttributeSet::getStackAlignment() const {
800 return SetNode
? SetNode
->getStackAlignment() : std::nullopt
;
803 uint64_t AttributeSet::getDereferenceableBytes() const {
804 return SetNode
? SetNode
->getDereferenceableBytes() : 0;
807 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
808 return SetNode
? SetNode
->getDereferenceableOrNullBytes() : 0;
811 Type
*AttributeSet::getByRefType() const {
812 return SetNode
? SetNode
->getAttributeType(Attribute::ByRef
) : nullptr;
815 Type
*AttributeSet::getByValType() const {
816 return SetNode
? SetNode
->getAttributeType(Attribute::ByVal
) : nullptr;
819 Type
*AttributeSet::getStructRetType() const {
820 return SetNode
? SetNode
->getAttributeType(Attribute::StructRet
) : nullptr;
823 Type
*AttributeSet::getPreallocatedType() const {
824 return SetNode
? SetNode
->getAttributeType(Attribute::Preallocated
) : nullptr;
827 Type
*AttributeSet::getInAllocaType() const {
828 return SetNode
? SetNode
->getAttributeType(Attribute::InAlloca
) : nullptr;
831 Type
*AttributeSet::getElementType() const {
832 return SetNode
? SetNode
->getAttributeType(Attribute::ElementType
) : nullptr;
835 std::optional
<std::pair
<unsigned, std::optional
<unsigned>>>
836 AttributeSet::getAllocSizeArgs() const {
838 return SetNode
->getAllocSizeArgs();
842 unsigned AttributeSet::getVScaleRangeMin() const {
843 return SetNode
? SetNode
->getVScaleRangeMin() : 1;
846 std::optional
<unsigned> AttributeSet::getVScaleRangeMax() const {
847 return SetNode
? SetNode
->getVScaleRangeMax() : std::nullopt
;
850 UWTableKind
AttributeSet::getUWTableKind() const {
851 return SetNode
? SetNode
->getUWTableKind() : UWTableKind::None
;
854 AllocFnKind
AttributeSet::getAllocKind() const {
855 return SetNode
? SetNode
->getAllocKind() : AllocFnKind::Unknown
;
858 MemoryEffects
AttributeSet::getMemoryEffects() const {
859 return SetNode
? SetNode
->getMemoryEffects() : MemoryEffects::unknown();
862 FPClassTest
AttributeSet::getNoFPClass() const {
863 return SetNode
? SetNode
->getNoFPClass() : fcNone
;
866 std::string
AttributeSet::getAsString(bool InAttrGrp
) const {
867 return SetNode
? SetNode
->getAsString(InAttrGrp
) : "";
870 bool AttributeSet::hasParentContext(LLVMContext
&C
) const {
871 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
873 SetNode
->Profile(ID
);
875 return C
.pImpl
->AttrsSetNodes
.FindNodeOrInsertPos(ID
, Unused
) == SetNode
;
878 AttributeSet::iterator
AttributeSet::begin() const {
879 return SetNode
? SetNode
->begin() : nullptr;
882 AttributeSet::iterator
AttributeSet::end() const {
883 return SetNode
? SetNode
->end() : nullptr;
886 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
887 LLVM_DUMP_METHOD
void AttributeSet::dump() const {
890 dbgs() << getAsString(true) << " }\n";
894 //===----------------------------------------------------------------------===//
895 // AttributeSetNode Definition
896 //===----------------------------------------------------------------------===//
898 AttributeSetNode::AttributeSetNode(ArrayRef
<Attribute
> Attrs
)
899 : NumAttrs(Attrs
.size()) {
900 // There's memory after the node where we can store the entries in.
901 llvm::copy(Attrs
, getTrailingObjects
<Attribute
>());
903 for (const auto &I
: *this) {
904 if (I
.isStringAttribute())
905 StringAttrs
.insert({ I
.getKindAsString(), I
});
907 AvailableAttrs
.addAttribute(I
.getKindAsEnum());
911 AttributeSetNode
*AttributeSetNode::get(LLVMContext
&C
,
912 ArrayRef
<Attribute
> Attrs
) {
913 SmallVector
<Attribute
, 8> SortedAttrs(Attrs
.begin(), Attrs
.end());
914 llvm::sort(SortedAttrs
);
915 return getSorted(C
, SortedAttrs
);
918 AttributeSetNode
*AttributeSetNode::getSorted(LLVMContext
&C
,
919 ArrayRef
<Attribute
> SortedAttrs
) {
920 if (SortedAttrs
.empty())
923 // Build a key to look up the existing attributes.
924 LLVMContextImpl
*pImpl
= C
.pImpl
;
927 assert(llvm::is_sorted(SortedAttrs
) && "Expected sorted attributes!");
928 for (const auto &Attr
: SortedAttrs
)
932 AttributeSetNode
*PA
=
933 pImpl
->AttrsSetNodes
.FindNodeOrInsertPos(ID
, InsertPoint
);
935 // If we didn't find any existing attributes of the same shape then create a
936 // new one and insert it.
938 // Coallocate entries after the AttributeSetNode itself.
939 void *Mem
= ::operator new(totalSizeToAlloc
<Attribute
>(SortedAttrs
.size()));
940 PA
= new (Mem
) AttributeSetNode(SortedAttrs
);
941 pImpl
->AttrsSetNodes
.InsertNode(PA
, InsertPoint
);
944 // Return the AttributeSetNode that we found or created.
948 AttributeSetNode
*AttributeSetNode::get(LLVMContext
&C
, const AttrBuilder
&B
) {
949 return getSorted(C
, B
.attrs());
952 bool AttributeSetNode::hasAttribute(StringRef Kind
) const {
953 return StringAttrs
.count(Kind
);
956 std::optional
<Attribute
>
957 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind
) const {
958 // Do a quick presence check.
959 if (!hasAttribute(Kind
))
962 // Attributes in a set are sorted by enum value, followed by string
963 // attributes. Binary search the one we want.
965 std::lower_bound(begin(), end() - StringAttrs
.size(), Kind
,
966 [](Attribute A
, Attribute::AttrKind Kind
) {
967 return A
.getKindAsEnum() < Kind
;
969 assert(I
!= end() && I
->hasAttribute(Kind
) && "Presence check failed?");
973 Attribute
AttributeSetNode::getAttribute(Attribute::AttrKind Kind
) const {
974 if (auto A
= findEnumAttribute(Kind
))
979 Attribute
AttributeSetNode::getAttribute(StringRef Kind
) const {
980 return StringAttrs
.lookup(Kind
);
983 MaybeAlign
AttributeSetNode::getAlignment() const {
984 if (auto A
= findEnumAttribute(Attribute::Alignment
))
985 return A
->getAlignment();
989 MaybeAlign
AttributeSetNode::getStackAlignment() const {
990 if (auto A
= findEnumAttribute(Attribute::StackAlignment
))
991 return A
->getStackAlignment();
995 Type
*AttributeSetNode::getAttributeType(Attribute::AttrKind Kind
) const {
996 if (auto A
= findEnumAttribute(Kind
))
997 return A
->getValueAsType();
1001 uint64_t AttributeSetNode::getDereferenceableBytes() const {
1002 if (auto A
= findEnumAttribute(Attribute::Dereferenceable
))
1003 return A
->getDereferenceableBytes();
1007 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
1008 if (auto A
= findEnumAttribute(Attribute::DereferenceableOrNull
))
1009 return A
->getDereferenceableOrNullBytes();
1013 std::optional
<std::pair
<unsigned, std::optional
<unsigned>>>
1014 AttributeSetNode::getAllocSizeArgs() const {
1015 if (auto A
= findEnumAttribute(Attribute::AllocSize
))
1016 return A
->getAllocSizeArgs();
1017 return std::nullopt
;
1020 unsigned AttributeSetNode::getVScaleRangeMin() const {
1021 if (auto A
= findEnumAttribute(Attribute::VScaleRange
))
1022 return A
->getVScaleRangeMin();
1026 std::optional
<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1027 if (auto A
= findEnumAttribute(Attribute::VScaleRange
))
1028 return A
->getVScaleRangeMax();
1029 return std::nullopt
;
1032 UWTableKind
AttributeSetNode::getUWTableKind() const {
1033 if (auto A
= findEnumAttribute(Attribute::UWTable
))
1034 return A
->getUWTableKind();
1035 return UWTableKind::None
;
1038 AllocFnKind
AttributeSetNode::getAllocKind() const {
1039 if (auto A
= findEnumAttribute(Attribute::AllocKind
))
1040 return A
->getAllocKind();
1041 return AllocFnKind::Unknown
;
1044 MemoryEffects
AttributeSetNode::getMemoryEffects() const {
1045 if (auto A
= findEnumAttribute(Attribute::Memory
))
1046 return A
->getMemoryEffects();
1047 return MemoryEffects::unknown();
1050 FPClassTest
AttributeSetNode::getNoFPClass() const {
1051 if (auto A
= findEnumAttribute(Attribute::NoFPClass
))
1052 return A
->getNoFPClass();
1056 std::string
AttributeSetNode::getAsString(bool InAttrGrp
) const {
1058 for (iterator I
= begin(), E
= end(); I
!= E
; ++I
) {
1061 Str
+= I
->getAsString(InAttrGrp
);
1066 //===----------------------------------------------------------------------===//
1067 // AttributeListImpl Definition
1068 //===----------------------------------------------------------------------===//
1070 /// Map from AttributeList index to the internal array index. Adding one happens
1071 /// to work, because -1 wraps around to 0.
1072 static unsigned attrIdxToArrayIdx(unsigned Index
) {
1076 AttributeListImpl::AttributeListImpl(ArrayRef
<AttributeSet
> Sets
)
1077 : NumAttrSets(Sets
.size()) {
1078 assert(!Sets
.empty() && "pointless AttributeListImpl");
1080 // There's memory after the node where we can store the entries in.
1081 llvm::copy(Sets
, getTrailingObjects
<AttributeSet
>());
1083 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1085 for (const auto &I
: Sets
[attrIdxToArrayIdx(AttributeList::FunctionIndex
)])
1086 if (!I
.isStringAttribute())
1087 AvailableFunctionAttrs
.addAttribute(I
.getKindAsEnum());
1089 for (const auto &Set
: Sets
)
1090 for (const auto &I
: Set
)
1091 if (!I
.isStringAttribute())
1092 AvailableSomewhereAttrs
.addAttribute(I
.getKindAsEnum());
1095 void AttributeListImpl::Profile(FoldingSetNodeID
&ID
) const {
1096 Profile(ID
, ArrayRef(begin(), end()));
1099 void AttributeListImpl::Profile(FoldingSetNodeID
&ID
,
1100 ArrayRef
<AttributeSet
> Sets
) {
1101 for (const auto &Set
: Sets
)
1102 ID
.AddPointer(Set
.SetNode
);
1105 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind
,
1106 unsigned *Index
) const {
1107 if (!AvailableSomewhereAttrs
.hasAttribute(Kind
))
1111 for (unsigned I
= 0, E
= NumAttrSets
; I
!= E
; ++I
) {
1112 if (begin()[I
].hasAttribute(Kind
)) {
1123 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1124 LLVM_DUMP_METHOD
void AttributeListImpl::dump() const {
1125 AttributeList(const_cast<AttributeListImpl
*>(this)).dump();
1129 //===----------------------------------------------------------------------===//
1130 // AttributeList Construction and Mutation Methods
1131 //===----------------------------------------------------------------------===//
1133 AttributeList
AttributeList::getImpl(LLVMContext
&C
,
1134 ArrayRef
<AttributeSet
> AttrSets
) {
1135 assert(!AttrSets
.empty() && "pointless AttributeListImpl");
1137 LLVMContextImpl
*pImpl
= C
.pImpl
;
1138 FoldingSetNodeID ID
;
1139 AttributeListImpl::Profile(ID
, AttrSets
);
1142 AttributeListImpl
*PA
=
1143 pImpl
->AttrsLists
.FindNodeOrInsertPos(ID
, InsertPoint
);
1145 // If we didn't find any existing attributes of the same shape then
1146 // create a new one and insert it.
1148 // Coallocate entries after the AttributeListImpl itself.
1149 void *Mem
= pImpl
->Alloc
.Allocate(
1150 AttributeListImpl::totalSizeToAlloc
<AttributeSet
>(AttrSets
.size()),
1151 alignof(AttributeListImpl
));
1152 PA
= new (Mem
) AttributeListImpl(AttrSets
);
1153 pImpl
->AttrsLists
.InsertNode(PA
, InsertPoint
);
1156 // Return the AttributesList that we found or created.
1157 return AttributeList(PA
);
1161 AttributeList::get(LLVMContext
&C
,
1162 ArrayRef
<std::pair
<unsigned, Attribute
>> Attrs
) {
1163 // If there are no attributes then return a null AttributesList pointer.
1167 assert(llvm::is_sorted(Attrs
, llvm::less_first()) &&
1168 "Misordered Attributes list!");
1169 assert(llvm::all_of(Attrs
,
1170 [](const std::pair
<unsigned, Attribute
> &Pair
) {
1171 return Pair
.second
.isValid();
1173 "Pointless attribute!");
1175 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1177 SmallVector
<std::pair
<unsigned, AttributeSet
>, 8> AttrPairVec
;
1178 for (ArrayRef
<std::pair
<unsigned, Attribute
>>::iterator I
= Attrs
.begin(),
1179 E
= Attrs
.end(); I
!= E
; ) {
1180 unsigned Index
= I
->first
;
1181 SmallVector
<Attribute
, 4> AttrVec
;
1182 while (I
!= E
&& I
->first
== Index
) {
1183 AttrVec
.push_back(I
->second
);
1187 AttrPairVec
.emplace_back(Index
, AttributeSet::get(C
, AttrVec
));
1190 return get(C
, AttrPairVec
);
1194 AttributeList::get(LLVMContext
&C
,
1195 ArrayRef
<std::pair
<unsigned, AttributeSet
>> Attrs
) {
1196 // If there are no attributes then return a null AttributesList pointer.
1200 assert(llvm::is_sorted(Attrs
, llvm::less_first()) &&
1201 "Misordered Attributes list!");
1202 assert(llvm::none_of(Attrs
,
1203 [](const std::pair
<unsigned, AttributeSet
> &Pair
) {
1204 return !Pair
.second
.hasAttributes();
1206 "Pointless attribute!");
1208 unsigned MaxIndex
= Attrs
.back().first
;
1209 // If the MaxIndex is FunctionIndex and there are other indices in front
1210 // of it, we need to use the largest of those to get the right size.
1211 if (MaxIndex
== FunctionIndex
&& Attrs
.size() > 1)
1212 MaxIndex
= Attrs
[Attrs
.size() - 2].first
;
1214 SmallVector
<AttributeSet
, 4> AttrVec(attrIdxToArrayIdx(MaxIndex
) + 1);
1215 for (const auto &Pair
: Attrs
)
1216 AttrVec
[attrIdxToArrayIdx(Pair
.first
)] = Pair
.second
;
1218 return getImpl(C
, AttrVec
);
1221 AttributeList
AttributeList::get(LLVMContext
&C
, AttributeSet FnAttrs
,
1222 AttributeSet RetAttrs
,
1223 ArrayRef
<AttributeSet
> ArgAttrs
) {
1224 // Scan from the end to find the last argument with attributes. Most
1225 // arguments don't have attributes, so it's nice if we can have fewer unique
1226 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1227 unsigned NumSets
= 0;
1228 for (size_t I
= ArgAttrs
.size(); I
!= 0; --I
) {
1229 if (ArgAttrs
[I
- 1].hasAttributes()) {
1235 // Check function and return attributes if we didn't have argument
1237 if (RetAttrs
.hasAttributes())
1239 else if (FnAttrs
.hasAttributes())
1243 // If all attribute sets were empty, we can use the empty attribute list.
1247 SmallVector
<AttributeSet
, 8> AttrSets
;
1248 AttrSets
.reserve(NumSets
);
1249 // If we have any attributes, we always have function attributes.
1250 AttrSets
.push_back(FnAttrs
);
1252 AttrSets
.push_back(RetAttrs
);
1254 // Drop the empty argument attribute sets at the end.
1255 ArgAttrs
= ArgAttrs
.take_front(NumSets
- 2);
1256 llvm::append_range(AttrSets
, ArgAttrs
);
1259 return getImpl(C
, AttrSets
);
1262 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1263 AttributeSet Attrs
) {
1264 if (!Attrs
.hasAttributes())
1266 Index
= attrIdxToArrayIdx(Index
);
1267 SmallVector
<AttributeSet
, 8> AttrSets(Index
+ 1);
1268 AttrSets
[Index
] = Attrs
;
1269 return getImpl(C
, AttrSets
);
1272 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1273 const AttrBuilder
&B
) {
1274 return get(C
, Index
, AttributeSet::get(C
, B
));
1277 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1278 ArrayRef
<Attribute::AttrKind
> Kinds
) {
1279 SmallVector
<std::pair
<unsigned, Attribute
>, 8> Attrs
;
1280 for (const auto K
: Kinds
)
1281 Attrs
.emplace_back(Index
, Attribute::get(C
, K
));
1282 return get(C
, Attrs
);
1285 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1286 ArrayRef
<Attribute::AttrKind
> Kinds
,
1287 ArrayRef
<uint64_t> Values
) {
1288 assert(Kinds
.size() == Values
.size() && "Mismatched attribute values.");
1289 SmallVector
<std::pair
<unsigned, Attribute
>, 8> Attrs
;
1290 auto VI
= Values
.begin();
1291 for (const auto K
: Kinds
)
1292 Attrs
.emplace_back(Index
, Attribute::get(C
, K
, *VI
++));
1293 return get(C
, Attrs
);
1296 AttributeList
AttributeList::get(LLVMContext
&C
, unsigned Index
,
1297 ArrayRef
<StringRef
> Kinds
) {
1298 SmallVector
<std::pair
<unsigned, Attribute
>, 8> Attrs
;
1299 for (const auto &K
: Kinds
)
1300 Attrs
.emplace_back(Index
, Attribute::get(C
, K
));
1301 return get(C
, Attrs
);
1304 AttributeList
AttributeList::get(LLVMContext
&C
,
1305 ArrayRef
<AttributeList
> Attrs
) {
1308 if (Attrs
.size() == 1)
1311 unsigned MaxSize
= 0;
1312 for (const auto &List
: Attrs
)
1313 MaxSize
= std::max(MaxSize
, List
.getNumAttrSets());
1315 // If every list was empty, there is no point in merging the lists.
1319 SmallVector
<AttributeSet
, 8> NewAttrSets(MaxSize
);
1320 for (unsigned I
= 0; I
< MaxSize
; ++I
) {
1321 AttrBuilder
CurBuilder(C
);
1322 for (const auto &List
: Attrs
)
1323 CurBuilder
.merge(AttrBuilder(C
, List
.getAttributes(I
- 1)));
1324 NewAttrSets
[I
] = AttributeSet::get(C
, CurBuilder
);
1327 return getImpl(C
, NewAttrSets
);
1331 AttributeList::addAttributeAtIndex(LLVMContext
&C
, unsigned Index
,
1332 Attribute::AttrKind Kind
) const {
1333 AttributeSet Attrs
= getAttributes(Index
);
1334 if (Attrs
.hasAttribute(Kind
))
1336 // TODO: Insert at correct position and avoid sort.
1337 SmallVector
<Attribute
, 8> NewAttrs(Attrs
.begin(), Attrs
.end());
1338 NewAttrs
.push_back(Attribute::get(C
, Kind
));
1339 return setAttributesAtIndex(C
, Index
, AttributeSet::get(C
, NewAttrs
));
1342 AttributeList
AttributeList::addAttributeAtIndex(LLVMContext
&C
, unsigned Index
,
1344 StringRef Value
) const {
1346 B
.addAttribute(Kind
, Value
);
1347 return addAttributesAtIndex(C
, Index
, B
);
1350 AttributeList
AttributeList::addAttributeAtIndex(LLVMContext
&C
, unsigned Index
,
1351 Attribute A
) const {
1354 return addAttributesAtIndex(C
, Index
, B
);
1357 AttributeList
AttributeList::setAttributesAtIndex(LLVMContext
&C
,
1359 AttributeSet Attrs
) const {
1360 Index
= attrIdxToArrayIdx(Index
);
1361 SmallVector
<AttributeSet
, 4> AttrSets(this->begin(), this->end());
1362 if (Index
>= AttrSets
.size())
1363 AttrSets
.resize(Index
+ 1);
1364 AttrSets
[Index
] = Attrs
;
1366 // Remove trailing empty attribute sets.
1367 while (!AttrSets
.empty() && !AttrSets
.back().hasAttributes())
1368 AttrSets
.pop_back();
1369 if (AttrSets
.empty())
1371 return AttributeList::getImpl(C
, AttrSets
);
1374 AttributeList
AttributeList::addAttributesAtIndex(LLVMContext
&C
,
1376 const AttrBuilder
&B
) const {
1377 if (!B
.hasAttributes())
1381 return AttributeList::get(C
, {{Index
, AttributeSet::get(C
, B
)}});
1383 AttrBuilder
Merged(C
, getAttributes(Index
));
1385 return setAttributesAtIndex(C
, Index
, AttributeSet::get(C
, Merged
));
1388 AttributeList
AttributeList::addParamAttribute(LLVMContext
&C
,
1389 ArrayRef
<unsigned> ArgNos
,
1390 Attribute A
) const {
1391 assert(llvm::is_sorted(ArgNos
));
1393 SmallVector
<AttributeSet
, 4> AttrSets(this->begin(), this->end());
1394 unsigned MaxIndex
= attrIdxToArrayIdx(ArgNos
.back() + FirstArgIndex
);
1395 if (MaxIndex
>= AttrSets
.size())
1396 AttrSets
.resize(MaxIndex
+ 1);
1398 for (unsigned ArgNo
: ArgNos
) {
1399 unsigned Index
= attrIdxToArrayIdx(ArgNo
+ FirstArgIndex
);
1400 AttrBuilder
B(C
, AttrSets
[Index
]);
1402 AttrSets
[Index
] = AttributeSet::get(C
, B
);
1405 return getImpl(C
, AttrSets
);
1409 AttributeList::removeAttributeAtIndex(LLVMContext
&C
, unsigned Index
,
1410 Attribute::AttrKind Kind
) const {
1411 AttributeSet Attrs
= getAttributes(Index
);
1412 AttributeSet NewAttrs
= Attrs
.removeAttribute(C
, Kind
);
1413 if (Attrs
== NewAttrs
)
1415 return setAttributesAtIndex(C
, Index
, NewAttrs
);
1418 AttributeList
AttributeList::removeAttributeAtIndex(LLVMContext
&C
,
1420 StringRef Kind
) const {
1421 AttributeSet Attrs
= getAttributes(Index
);
1422 AttributeSet NewAttrs
= Attrs
.removeAttribute(C
, Kind
);
1423 if (Attrs
== NewAttrs
)
1425 return setAttributesAtIndex(C
, Index
, NewAttrs
);
1428 AttributeList
AttributeList::removeAttributesAtIndex(
1429 LLVMContext
&C
, unsigned Index
, const AttributeMask
&AttrsToRemove
) const {
1430 AttributeSet Attrs
= getAttributes(Index
);
1431 AttributeSet NewAttrs
= Attrs
.removeAttributes(C
, AttrsToRemove
);
1432 // If nothing was removed, return the original list.
1433 if (Attrs
== NewAttrs
)
1435 return setAttributesAtIndex(C
, Index
, NewAttrs
);
1439 AttributeList::removeAttributesAtIndex(LLVMContext
&C
,
1440 unsigned WithoutIndex
) const {
1443 if (attrIdxToArrayIdx(WithoutIndex
) >= getNumAttrSets())
1445 return setAttributesAtIndex(C
, WithoutIndex
, AttributeSet());
1448 AttributeList
AttributeList::addDereferenceableRetAttr(LLVMContext
&C
,
1449 uint64_t Bytes
) const {
1451 B
.addDereferenceableAttr(Bytes
);
1452 return addRetAttributes(C
, B
);
1455 AttributeList
AttributeList::addDereferenceableParamAttr(LLVMContext
&C
,
1457 uint64_t Bytes
) const {
1459 B
.addDereferenceableAttr(Bytes
);
1460 return addParamAttributes(C
, Index
, B
);
1464 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext
&C
, unsigned Index
,
1465 uint64_t Bytes
) const {
1467 B
.addDereferenceableOrNullAttr(Bytes
);
1468 return addParamAttributes(C
, Index
, B
);
1471 AttributeList
AttributeList::addAllocSizeParamAttr(
1472 LLVMContext
&C
, unsigned Index
, unsigned ElemSizeArg
,
1473 const std::optional
<unsigned> &NumElemsArg
) {
1475 B
.addAllocSizeAttr(ElemSizeArg
, NumElemsArg
);
1476 return addParamAttributes(C
, Index
, B
);
1479 //===----------------------------------------------------------------------===//
1480 // AttributeList Accessor Methods
1481 //===----------------------------------------------------------------------===//
1483 AttributeSet
AttributeList::getParamAttrs(unsigned ArgNo
) const {
1484 return getAttributes(ArgNo
+ FirstArgIndex
);
1487 AttributeSet
AttributeList::getRetAttrs() const {
1488 return getAttributes(ReturnIndex
);
1491 AttributeSet
AttributeList::getFnAttrs() const {
1492 return getAttributes(FunctionIndex
);
1495 bool AttributeList::hasAttributeAtIndex(unsigned Index
,
1496 Attribute::AttrKind Kind
) const {
1497 return getAttributes(Index
).hasAttribute(Kind
);
1500 bool AttributeList::hasAttributeAtIndex(unsigned Index
, StringRef Kind
) const {
1501 return getAttributes(Index
).hasAttribute(Kind
);
1504 bool AttributeList::hasAttributesAtIndex(unsigned Index
) const {
1505 return getAttributes(Index
).hasAttributes();
1508 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind
) const {
1509 return pImpl
&& pImpl
->hasFnAttribute(Kind
);
1512 bool AttributeList::hasFnAttr(StringRef Kind
) const {
1513 return hasAttributeAtIndex(AttributeList::FunctionIndex
, Kind
);
1516 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr
,
1517 unsigned *Index
) const {
1518 return pImpl
&& pImpl
->hasAttrSomewhere(Attr
, Index
);
1521 Attribute
AttributeList::getAttributeAtIndex(unsigned Index
,
1522 Attribute::AttrKind Kind
) const {
1523 return getAttributes(Index
).getAttribute(Kind
);
1526 Attribute
AttributeList::getAttributeAtIndex(unsigned Index
,
1527 StringRef Kind
) const {
1528 return getAttributes(Index
).getAttribute(Kind
);
1531 MaybeAlign
AttributeList::getRetAlignment() const {
1532 return getAttributes(ReturnIndex
).getAlignment();
1535 MaybeAlign
AttributeList::getParamAlignment(unsigned ArgNo
) const {
1536 return getAttributes(ArgNo
+ FirstArgIndex
).getAlignment();
1539 MaybeAlign
AttributeList::getParamStackAlignment(unsigned ArgNo
) const {
1540 return getAttributes(ArgNo
+ FirstArgIndex
).getStackAlignment();
1543 Type
*AttributeList::getParamByValType(unsigned Index
) const {
1544 return getAttributes(Index
+FirstArgIndex
).getByValType();
1547 Type
*AttributeList::getParamStructRetType(unsigned Index
) const {
1548 return getAttributes(Index
+ FirstArgIndex
).getStructRetType();
1551 Type
*AttributeList::getParamByRefType(unsigned Index
) const {
1552 return getAttributes(Index
+ FirstArgIndex
).getByRefType();
1555 Type
*AttributeList::getParamPreallocatedType(unsigned Index
) const {
1556 return getAttributes(Index
+ FirstArgIndex
).getPreallocatedType();
1559 Type
*AttributeList::getParamInAllocaType(unsigned Index
) const {
1560 return getAttributes(Index
+ FirstArgIndex
).getInAllocaType();
1563 Type
*AttributeList::getParamElementType(unsigned Index
) const {
1564 return getAttributes(Index
+ FirstArgIndex
).getElementType();
1567 MaybeAlign
AttributeList::getFnStackAlignment() const {
1568 return getFnAttrs().getStackAlignment();
1571 MaybeAlign
AttributeList::getRetStackAlignment() const {
1572 return getRetAttrs().getStackAlignment();
1575 uint64_t AttributeList::getRetDereferenceableBytes() const {
1576 return getRetAttrs().getDereferenceableBytes();
1579 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index
) const {
1580 return getParamAttrs(Index
).getDereferenceableBytes();
1583 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1584 return getRetAttrs().getDereferenceableOrNullBytes();
1588 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index
) const {
1589 return getParamAttrs(Index
).getDereferenceableOrNullBytes();
1592 FPClassTest
AttributeList::getRetNoFPClass() const {
1593 return getRetAttrs().getNoFPClass();
1596 FPClassTest
AttributeList::getParamNoFPClass(unsigned Index
) const {
1597 return getParamAttrs(Index
).getNoFPClass();
1600 UWTableKind
AttributeList::getUWTableKind() const {
1601 return getFnAttrs().getUWTableKind();
1604 AllocFnKind
AttributeList::getAllocKind() const {
1605 return getFnAttrs().getAllocKind();
1608 MemoryEffects
AttributeList::getMemoryEffects() const {
1609 return getFnAttrs().getMemoryEffects();
1612 std::string
AttributeList::getAsString(unsigned Index
, bool InAttrGrp
) const {
1613 return getAttributes(Index
).getAsString(InAttrGrp
);
1616 AttributeSet
AttributeList::getAttributes(unsigned Index
) const {
1617 Index
= attrIdxToArrayIdx(Index
);
1618 if (!pImpl
|| Index
>= getNumAttrSets())
1620 return pImpl
->begin()[Index
];
1623 bool AttributeList::hasParentContext(LLVMContext
&C
) const {
1624 assert(!isEmpty() && "an empty attribute list has no parent context");
1625 FoldingSetNodeID ID
;
1628 return C
.pImpl
->AttrsLists
.FindNodeOrInsertPos(ID
, Unused
) == pImpl
;
1631 AttributeList::iterator
AttributeList::begin() const {
1632 return pImpl
? pImpl
->begin() : nullptr;
1635 AttributeList::iterator
AttributeList::end() const {
1636 return pImpl
? pImpl
->end() : nullptr;
1639 //===----------------------------------------------------------------------===//
1640 // AttributeList Introspection Methods
1641 //===----------------------------------------------------------------------===//
1643 unsigned AttributeList::getNumAttrSets() const {
1644 return pImpl
? pImpl
->NumAttrSets
: 0;
1647 void AttributeList::print(raw_ostream
&O
) const {
1648 O
<< "AttributeList[\n";
1650 for (unsigned i
: indexes()) {
1651 if (!getAttributes(i
).hasAttributes())
1655 case AttrIndex::ReturnIndex
:
1658 case AttrIndex::FunctionIndex
:
1662 O
<< "arg(" << i
- AttrIndex::FirstArgIndex
<< ")";
1664 O
<< " => " << getAsString(i
) << " }\n";
1670 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1671 LLVM_DUMP_METHOD
void AttributeList::dump() const { print(dbgs()); }
1674 //===----------------------------------------------------------------------===//
1675 // AttrBuilder Method Implementations
1676 //===----------------------------------------------------------------------===//
1678 AttrBuilder::AttrBuilder(LLVMContext
&Ctx
, AttributeSet AS
) : Ctx(Ctx
) {
1679 append_range(Attrs
, AS
);
1680 assert(is_sorted(Attrs
) && "AttributeSet should be sorted");
1683 void AttrBuilder::clear() { Attrs
.clear(); }
1685 /// Attribute comparator that only compares attribute keys. Enum attributes are
1686 /// sorted before string attributes.
1687 struct AttributeComparator
{
1688 bool operator()(Attribute A0
, Attribute A1
) const {
1689 bool A0IsString
= A0
.isStringAttribute();
1690 bool A1IsString
= A1
.isStringAttribute();
1693 return A0
.getKindAsString() < A1
.getKindAsString();
1699 return A0
.getKindAsEnum() < A1
.getKindAsEnum();
1701 bool operator()(Attribute A0
, Attribute::AttrKind Kind
) const {
1702 if (A0
.isStringAttribute())
1704 return A0
.getKindAsEnum() < Kind
;
1706 bool operator()(Attribute A0
, StringRef Kind
) const {
1707 if (A0
.isStringAttribute())
1708 return A0
.getKindAsString() < Kind
;
1713 template <typename K
>
1714 static void addAttributeImpl(SmallVectorImpl
<Attribute
> &Attrs
, K Kind
,
1716 auto It
= lower_bound(Attrs
, Kind
, AttributeComparator());
1717 if (It
!= Attrs
.end() && It
->hasAttribute(Kind
))
1718 std::swap(*It
, Attr
);
1720 Attrs
.insert(It
, Attr
);
1723 AttrBuilder
&AttrBuilder::addAttribute(Attribute Attr
) {
1724 if (Attr
.isStringAttribute())
1725 addAttributeImpl(Attrs
, Attr
.getKindAsString(), Attr
);
1727 addAttributeImpl(Attrs
, Attr
.getKindAsEnum(), Attr
);
1731 AttrBuilder
&AttrBuilder::addAttribute(Attribute::AttrKind Kind
) {
1732 addAttributeImpl(Attrs
, Kind
, Attribute::get(Ctx
, Kind
));
1736 AttrBuilder
&AttrBuilder::addAttribute(StringRef A
, StringRef V
) {
1737 addAttributeImpl(Attrs
, A
, Attribute::get(Ctx
, A
, V
));
1741 AttrBuilder
&AttrBuilder::removeAttribute(Attribute::AttrKind Val
) {
1742 assert((unsigned)Val
< Attribute::EndAttrKinds
&& "Attribute out of range!");
1743 auto It
= lower_bound(Attrs
, Val
, AttributeComparator());
1744 if (It
!= Attrs
.end() && It
->hasAttribute(Val
))
1749 AttrBuilder
&AttrBuilder::removeAttribute(StringRef A
) {
1750 auto It
= lower_bound(Attrs
, A
, AttributeComparator());
1751 if (It
!= Attrs
.end() && It
->hasAttribute(A
))
1756 std::optional
<uint64_t>
1757 AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind
) const {
1758 assert(Attribute::isIntAttrKind(Kind
) && "Not an int attribute");
1759 Attribute A
= getAttribute(Kind
);
1761 return A
.getValueAsInt();
1762 return std::nullopt
;
1765 AttrBuilder
&AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind
,
1767 return addAttribute(Attribute::get(Ctx
, Kind
, Value
));
1770 std::optional
<std::pair
<unsigned, std::optional
<unsigned>>>
1771 AttrBuilder::getAllocSizeArgs() const {
1772 Attribute A
= getAttribute(Attribute::AllocSize
);
1774 return A
.getAllocSizeArgs();
1775 return std::nullopt
;
1778 AttrBuilder
&AttrBuilder::addAlignmentAttr(MaybeAlign Align
) {
1782 assert(*Align
<= llvm::Value::MaximumAlignment
&& "Alignment too large.");
1783 return addRawIntAttr(Attribute::Alignment
, Align
->value());
1786 AttrBuilder
&AttrBuilder::addStackAlignmentAttr(MaybeAlign Align
) {
1787 // Default alignment, allow the target to define how to align it.
1791 assert(*Align
<= 0x100 && "Alignment too large.");
1792 return addRawIntAttr(Attribute::StackAlignment
, Align
->value());
1795 AttrBuilder
&AttrBuilder::addDereferenceableAttr(uint64_t Bytes
) {
1796 if (Bytes
== 0) return *this;
1798 return addRawIntAttr(Attribute::Dereferenceable
, Bytes
);
1801 AttrBuilder
&AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes
) {
1805 return addRawIntAttr(Attribute::DereferenceableOrNull
, Bytes
);
1809 AttrBuilder::addAllocSizeAttr(unsigned ElemSize
,
1810 const std::optional
<unsigned> &NumElems
) {
1811 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize
, NumElems
));
1814 AttrBuilder
&AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs
) {
1815 // (0, 0) is our "not present" value, so we need to check for it here.
1816 assert(RawArgs
&& "Invalid allocsize arguments -- given allocsize(0, 0)");
1817 return addRawIntAttr(Attribute::AllocSize
, RawArgs
);
1820 AttrBuilder
&AttrBuilder::addVScaleRangeAttr(unsigned MinValue
,
1821 std::optional
<unsigned> MaxValue
) {
1822 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue
, MaxValue
));
1825 AttrBuilder
&AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs
) {
1826 // (0, 0) is not present hence ignore this case
1830 return addRawIntAttr(Attribute::VScaleRange
, RawArgs
);
1833 AttrBuilder
&AttrBuilder::addUWTableAttr(UWTableKind Kind
) {
1834 if (Kind
== UWTableKind::None
)
1836 return addRawIntAttr(Attribute::UWTable
, uint64_t(Kind
));
1839 AttrBuilder
&AttrBuilder::addMemoryAttr(MemoryEffects ME
) {
1840 return addRawIntAttr(Attribute::Memory
, ME
.toIntValue());
1843 AttrBuilder
&AttrBuilder::addNoFPClassAttr(FPClassTest Mask
) {
1847 return addRawIntAttr(Attribute::NoFPClass
, Mask
);
1850 AttrBuilder
&AttrBuilder::addAllocKindAttr(AllocFnKind Kind
) {
1851 return addRawIntAttr(Attribute::AllocKind
, static_cast<uint64_t>(Kind
));
1854 Type
*AttrBuilder::getTypeAttr(Attribute::AttrKind Kind
) const {
1855 assert(Attribute::isTypeAttrKind(Kind
) && "Not a type attribute");
1856 Attribute A
= getAttribute(Kind
);
1857 return A
.isValid() ? A
.getValueAsType() : nullptr;
1860 AttrBuilder
&AttrBuilder::addTypeAttr(Attribute::AttrKind Kind
, Type
*Ty
) {
1861 return addAttribute(Attribute::get(Ctx
, Kind
, Ty
));
1864 AttrBuilder
&AttrBuilder::addByValAttr(Type
*Ty
) {
1865 return addTypeAttr(Attribute::ByVal
, Ty
);
1868 AttrBuilder
&AttrBuilder::addStructRetAttr(Type
*Ty
) {
1869 return addTypeAttr(Attribute::StructRet
, Ty
);
1872 AttrBuilder
&AttrBuilder::addByRefAttr(Type
*Ty
) {
1873 return addTypeAttr(Attribute::ByRef
, Ty
);
1876 AttrBuilder
&AttrBuilder::addPreallocatedAttr(Type
*Ty
) {
1877 return addTypeAttr(Attribute::Preallocated
, Ty
);
1880 AttrBuilder
&AttrBuilder::addInAllocaAttr(Type
*Ty
) {
1881 return addTypeAttr(Attribute::InAlloca
, Ty
);
1884 AttrBuilder
&AttrBuilder::merge(const AttrBuilder
&B
) {
1885 // TODO: Could make this O(n) as we're merging two sorted lists.
1886 for (const auto &I
: B
.attrs())
1892 AttrBuilder
&AttrBuilder::remove(const AttributeMask
&AM
) {
1893 erase_if(Attrs
, [&](Attribute A
) { return AM
.contains(A
); });
1897 bool AttrBuilder::overlaps(const AttributeMask
&AM
) const {
1898 return any_of(Attrs
, [&](Attribute A
) { return AM
.contains(A
); });
1901 Attribute
AttrBuilder::getAttribute(Attribute::AttrKind A
) const {
1902 assert((unsigned)A
< Attribute::EndAttrKinds
&& "Attribute out of range!");
1903 auto It
= lower_bound(Attrs
, A
, AttributeComparator());
1904 if (It
!= Attrs
.end() && It
->hasAttribute(A
))
1909 Attribute
AttrBuilder::getAttribute(StringRef A
) const {
1910 auto It
= lower_bound(Attrs
, A
, AttributeComparator());
1911 if (It
!= Attrs
.end() && It
->hasAttribute(A
))
1916 bool AttrBuilder::contains(Attribute::AttrKind A
) const {
1917 return getAttribute(A
).isValid();
1920 bool AttrBuilder::contains(StringRef A
) const {
1921 return getAttribute(A
).isValid();
1924 bool AttrBuilder::operator==(const AttrBuilder
&B
) const {
1925 return Attrs
== B
.Attrs
;
1928 //===----------------------------------------------------------------------===//
1929 // AttributeFuncs Function Defintions
1930 //===----------------------------------------------------------------------===//
1932 /// Returns true if this is a type legal for the 'nofpclass' attribute. This
1933 /// follows the same type rules as FPMathOperator.
1935 /// TODO: Consider relaxing to any FP type struct fields.
1936 bool AttributeFuncs::isNoFPClassCompatibleType(Type
*Ty
) {
1937 while (ArrayType
*ArrTy
= dyn_cast
<ArrayType
>(Ty
))
1938 Ty
= ArrTy
->getElementType();
1939 return Ty
->isFPOrFPVectorTy();
1942 /// Which attributes cannot be applied to a type.
1943 AttributeMask
AttributeFuncs::typeIncompatible(Type
*Ty
,
1944 AttributeSafetyKind ASK
) {
1945 AttributeMask Incompatible
;
1947 if (!Ty
->isIntegerTy()) {
1948 // Attributes that only apply to integers.
1949 if (ASK
& ASK_SAFE_TO_DROP
)
1950 Incompatible
.addAttribute(Attribute::AllocAlign
);
1951 if (ASK
& ASK_UNSAFE_TO_DROP
)
1952 Incompatible
.addAttribute(Attribute::SExt
).addAttribute(Attribute::ZExt
);
1955 if (!Ty
->isPointerTy()) {
1956 // Attributes that only apply to pointers.
1957 if (ASK
& ASK_SAFE_TO_DROP
)
1958 Incompatible
.addAttribute(Attribute::NoAlias
)
1959 .addAttribute(Attribute::NoCapture
)
1960 .addAttribute(Attribute::NonNull
)
1961 .addAttribute(Attribute::ReadNone
)
1962 .addAttribute(Attribute::ReadOnly
)
1963 .addAttribute(Attribute::Dereferenceable
)
1964 .addAttribute(Attribute::DereferenceableOrNull
)
1965 .addAttribute(Attribute::Writable
)
1966 .addAttribute(Attribute::DeadOnUnwind
);
1967 if (ASK
& ASK_UNSAFE_TO_DROP
)
1968 Incompatible
.addAttribute(Attribute::Nest
)
1969 .addAttribute(Attribute::SwiftError
)
1970 .addAttribute(Attribute::Preallocated
)
1971 .addAttribute(Attribute::InAlloca
)
1972 .addAttribute(Attribute::ByVal
)
1973 .addAttribute(Attribute::StructRet
)
1974 .addAttribute(Attribute::ByRef
)
1975 .addAttribute(Attribute::ElementType
)
1976 .addAttribute(Attribute::AllocatedPointer
);
1979 // Attributes that only apply to pointers or vectors of pointers.
1980 if (!Ty
->isPtrOrPtrVectorTy()) {
1981 if (ASK
& ASK_SAFE_TO_DROP
)
1982 Incompatible
.addAttribute(Attribute::Alignment
);
1985 if (ASK
& ASK_SAFE_TO_DROP
) {
1986 if (!isNoFPClassCompatibleType(Ty
))
1987 Incompatible
.addAttribute(Attribute::NoFPClass
);
1990 // Some attributes can apply to all "values" but there are no `void` values.
1991 if (Ty
->isVoidTy()) {
1992 if (ASK
& ASK_SAFE_TO_DROP
)
1993 Incompatible
.addAttribute(Attribute::NoUndef
);
1996 return Incompatible
;
1999 AttributeMask
AttributeFuncs::getUBImplyingAttributes() {
2001 AM
.addAttribute(Attribute::NoUndef
);
2002 AM
.addAttribute(Attribute::Dereferenceable
);
2003 AM
.addAttribute(Attribute::DereferenceableOrNull
);
2007 /// Callees with dynamic denormal modes are compatible with any caller mode.
2008 static bool denormModeCompatible(DenormalMode CallerMode
,
2009 DenormalMode CalleeMode
) {
2010 if (CallerMode
== CalleeMode
|| CalleeMode
== DenormalMode::getDynamic())
2013 // If they don't exactly match, it's OK if the mismatched component is
2015 if (CalleeMode
.Input
== CallerMode
.Input
&&
2016 CalleeMode
.Output
== DenormalMode::Dynamic
)
2019 if (CalleeMode
.Output
== CallerMode
.Output
&&
2020 CalleeMode
.Input
== DenormalMode::Dynamic
)
2025 static bool checkDenormMode(const Function
&Caller
, const Function
&Callee
) {
2026 DenormalMode CallerMode
= Caller
.getDenormalModeRaw();
2027 DenormalMode CalleeMode
= Callee
.getDenormalModeRaw();
2029 if (denormModeCompatible(CallerMode
, CalleeMode
)) {
2030 DenormalMode CallerModeF32
= Caller
.getDenormalModeF32Raw();
2031 DenormalMode CalleeModeF32
= Callee
.getDenormalModeF32Raw();
2032 if (CallerModeF32
== DenormalMode::getInvalid())
2033 CallerModeF32
= CallerMode
;
2034 if (CalleeModeF32
== DenormalMode::getInvalid())
2035 CalleeModeF32
= CalleeMode
;
2036 return denormModeCompatible(CallerModeF32
, CalleeModeF32
);
2042 template<typename AttrClass
>
2043 static bool isEqual(const Function
&Caller
, const Function
&Callee
) {
2044 return Caller
.getFnAttribute(AttrClass::getKind()) ==
2045 Callee
.getFnAttribute(AttrClass::getKind());
2048 static bool isEqual(const Function
&Caller
, const Function
&Callee
,
2049 const StringRef
&AttrName
) {
2050 return Caller
.getFnAttribute(AttrName
) == Callee
.getFnAttribute(AttrName
);
2053 /// Compute the logical AND of the attributes of the caller and the
2056 /// This function sets the caller's attribute to false if the callee's attribute
2058 template<typename AttrClass
>
2059 static void setAND(Function
&Caller
, const Function
&Callee
) {
2060 if (AttrClass::isSet(Caller
, AttrClass::getKind()) &&
2061 !AttrClass::isSet(Callee
, AttrClass::getKind()))
2062 AttrClass::set(Caller
, AttrClass::getKind(), false);
2065 /// Compute the logical OR of the attributes of the caller and the
2068 /// This function sets the caller's attribute to true if the callee's attribute
2070 template<typename AttrClass
>
2071 static void setOR(Function
&Caller
, const Function
&Callee
) {
2072 if (!AttrClass::isSet(Caller
, AttrClass::getKind()) &&
2073 AttrClass::isSet(Callee
, AttrClass::getKind()))
2074 AttrClass::set(Caller
, AttrClass::getKind(), true);
2077 /// If the inlined function had a higher stack protection level than the
2078 /// calling function, then bump up the caller's stack protection level.
2079 static void adjustCallerSSPLevel(Function
&Caller
, const Function
&Callee
) {
2080 // If the calling function has *no* stack protection level (e.g. it was built
2081 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2082 // change it as that could change the program's semantics.
2083 if (!Caller
.hasStackProtectorFnAttr())
2086 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2087 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2088 // clutter to the IR.
2089 AttributeMask OldSSPAttr
;
2090 OldSSPAttr
.addAttribute(Attribute::StackProtect
)
2091 .addAttribute(Attribute::StackProtectStrong
)
2092 .addAttribute(Attribute::StackProtectReq
);
2094 if (Callee
.hasFnAttribute(Attribute::StackProtectReq
)) {
2095 Caller
.removeFnAttrs(OldSSPAttr
);
2096 Caller
.addFnAttr(Attribute::StackProtectReq
);
2097 } else if (Callee
.hasFnAttribute(Attribute::StackProtectStrong
) &&
2098 !Caller
.hasFnAttribute(Attribute::StackProtectReq
)) {
2099 Caller
.removeFnAttrs(OldSSPAttr
);
2100 Caller
.addFnAttr(Attribute::StackProtectStrong
);
2101 } else if (Callee
.hasFnAttribute(Attribute::StackProtect
) &&
2102 !Caller
.hasFnAttribute(Attribute::StackProtectReq
) &&
2103 !Caller
.hasFnAttribute(Attribute::StackProtectStrong
))
2104 Caller
.addFnAttr(Attribute::StackProtect
);
2107 /// If the inlined function required stack probes, then ensure that
2108 /// the calling function has those too.
2109 static void adjustCallerStackProbes(Function
&Caller
, const Function
&Callee
) {
2110 if (!Caller
.hasFnAttribute("probe-stack") &&
2111 Callee
.hasFnAttribute("probe-stack")) {
2112 Caller
.addFnAttr(Callee
.getFnAttribute("probe-stack"));
2116 /// If the inlined function defines the size of guard region
2117 /// on the stack, then ensure that the calling function defines a guard region
2118 /// that is no larger.
2120 adjustCallerStackProbeSize(Function
&Caller
, const Function
&Callee
) {
2121 Attribute CalleeAttr
= Callee
.getFnAttribute("stack-probe-size");
2122 if (CalleeAttr
.isValid()) {
2123 Attribute CallerAttr
= Caller
.getFnAttribute("stack-probe-size");
2124 if (CallerAttr
.isValid()) {
2125 uint64_t CallerStackProbeSize
, CalleeStackProbeSize
;
2126 CallerAttr
.getValueAsString().getAsInteger(0, CallerStackProbeSize
);
2127 CalleeAttr
.getValueAsString().getAsInteger(0, CalleeStackProbeSize
);
2129 if (CallerStackProbeSize
> CalleeStackProbeSize
) {
2130 Caller
.addFnAttr(CalleeAttr
);
2133 Caller
.addFnAttr(CalleeAttr
);
2138 /// If the inlined function defines a min legal vector width, then ensure
2139 /// the calling function has the same or larger min legal vector width. If the
2140 /// caller has the attribute, but the callee doesn't, we need to remove the
2141 /// attribute from the caller since we can't make any guarantees about the
2142 /// caller's requirements.
2143 /// This function is called after the inlining decision has been made so we have
2144 /// to merge the attribute this way. Heuristics that would use
2145 /// min-legal-vector-width to determine inline compatibility would need to be
2146 /// handled as part of inline cost analysis.
2148 adjustMinLegalVectorWidth(Function
&Caller
, const Function
&Callee
) {
2149 Attribute CallerAttr
= Caller
.getFnAttribute("min-legal-vector-width");
2150 if (CallerAttr
.isValid()) {
2151 Attribute CalleeAttr
= Callee
.getFnAttribute("min-legal-vector-width");
2152 if (CalleeAttr
.isValid()) {
2153 uint64_t CallerVectorWidth
, CalleeVectorWidth
;
2154 CallerAttr
.getValueAsString().getAsInteger(0, CallerVectorWidth
);
2155 CalleeAttr
.getValueAsString().getAsInteger(0, CalleeVectorWidth
);
2156 if (CallerVectorWidth
< CalleeVectorWidth
)
2157 Caller
.addFnAttr(CalleeAttr
);
2159 // If the callee doesn't have the attribute then we don't know anything
2160 // and must drop the attribute from the caller.
2161 Caller
.removeFnAttr("min-legal-vector-width");
2166 /// If the inlined function has null_pointer_is_valid attribute,
2167 /// set this attribute in the caller post inlining.
2169 adjustNullPointerValidAttr(Function
&Caller
, const Function
&Callee
) {
2170 if (Callee
.nullPointerIsDefined() && !Caller
.nullPointerIsDefined()) {
2171 Caller
.addFnAttr(Attribute::NullPointerIsValid
);
2176 static bool isSet(const Function
&Fn
,
2177 Attribute::AttrKind Kind
) {
2178 return Fn
.hasFnAttribute(Kind
);
2181 static void set(Function
&Fn
,
2182 Attribute::AttrKind Kind
, bool Val
) {
2186 Fn
.removeFnAttr(Kind
);
2190 struct StrBoolAttr
{
2191 static bool isSet(const Function
&Fn
,
2193 auto A
= Fn
.getFnAttribute(Kind
);
2194 return A
.getValueAsString().equals("true");
2197 static void set(Function
&Fn
,
2198 StringRef Kind
, bool Val
) {
2199 Fn
.addFnAttr(Kind
, Val
? "true" : "false");
2203 #define GET_ATTR_NAMES
2204 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2205 struct ENUM_NAME##Attr : EnumAttr { \
2206 static enum Attribute::AttrKind getKind() { \
2207 return llvm::Attribute::ENUM_NAME; \
2210 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2211 struct ENUM_NAME##Attr : StrBoolAttr { \
2212 static StringRef getKind() { return #DISPLAY_NAME; } \
2214 #include "llvm/IR/Attributes.inc"
2216 #define GET_ATTR_COMPAT_FUNC
2217 #include "llvm/IR/Attributes.inc"
2219 bool AttributeFuncs::areInlineCompatible(const Function
&Caller
,
2220 const Function
&Callee
) {
2221 return hasCompatibleFnAttrs(Caller
, Callee
);
2224 bool AttributeFuncs::areOutlineCompatible(const Function
&A
,
2225 const Function
&B
) {
2226 return hasCompatibleFnAttrs(A
, B
);
2229 void AttributeFuncs::mergeAttributesForInlining(Function
&Caller
,
2230 const Function
&Callee
) {
2231 mergeFnAttrs(Caller
, Callee
);
2234 void AttributeFuncs::mergeAttributesForOutlining(Function
&Base
,
2235 const Function
&ToMerge
) {
2237 // We merge functions so that they meet the most general case.
2238 // For example, if the NoNansFPMathAttr is set in one function, but not in
2239 // the other, in the merged function we can say that the NoNansFPMathAttr
2241 // However if we have the SpeculativeLoadHardeningAttr set true in one
2242 // function, but not the other, we make sure that the function retains
2243 // that aspect in the merged function.
2244 mergeFnAttrs(Base
, ToMerge
);
2247 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function
&Fn
,
2249 Attribute Attr
= Fn
.getFnAttribute("min-legal-vector-width");
2250 if (Attr
.isValid()) {
2252 Attr
.getValueAsString().getAsInteger(0, OldWidth
);
2253 if (Width
> OldWidth
)
2254 Fn
.addFnAttr("min-legal-vector-width", llvm::utostr(Width
));