[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / llvm / lib / IR / Attributes.cpp
blob19076771ff2eaf78aea6472060fcb6bdbf942055
1 //===- Attributes.cpp - Implement AttributesList --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // \file
10 // This file implements the Attribute, AttributeImpl, AttrBuilder,
11 // AttributeListImpl, and AttributeList classes.
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"
34 #include <algorithm>
35 #include <cassert>
36 #include <cstddef>
37 #include <cstdint>
38 #include <limits>
39 #include <optional>
40 #include <string>
41 #include <tuple>
42 #include <utility>
44 using namespace llvm;
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
52 // nonsensical.
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,
93 uint64_t Val) {
94 bool IsIntAttr = Attribute::isIntAttrKind(Kind);
95 assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
96 "Not an enum or int attribute");
98 LLVMContextImpl *pImpl = Context.pImpl;
99 FoldingSetNodeID ID;
100 ID.AddInteger(Kind);
101 if (IsIntAttr)
102 ID.AddInteger(Val);
103 else
104 assert(Val == 0 && "Value must be zero for enum attributes");
106 void *InsertPoint;
107 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
109 if (!PA) {
110 // If we didn't find any existing attributes of the same shape then create a
111 // new one and insert it.
112 if (!IsIntAttr)
113 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
114 else
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;
125 FoldingSetNodeID ID;
126 ID.AddString(Kind);
127 if (!Val.empty()) ID.AddString(Val);
129 void *InsertPoint;
130 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
132 if (!PA) {
133 // If we didn't find any existing attributes of the same shape then create a
134 // new one and insert it.
135 void *Mem =
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,
147 Type *Ty) {
148 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
149 LLVMContextImpl *pImpl = Context.pImpl;
150 FoldingSetNodeID ID;
151 ID.AddInteger(Kind);
152 ID.AddPointer(Ty);
154 void *InsertPoint;
155 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
157 if (!PA) {
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,
179 uint64_t Bytes) {
180 assert(Bytes && "Bytes must be non-zero.");
181 return get(Context, Dereferenceable, Bytes);
184 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
185 uint64_t Bytes) {
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,
211 UWTableKind Kind) {
212 return get(Context, UWTable, uint64_t(Kind));
215 Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
216 MemoryEffects ME) {
217 return get(Context, Memory, ME.toIntValue());
220 Attribute Attribute::getWithNoFPClass(LLVMContext &Context,
221 FPClassTest ClassMask) {
222 return get(Context, NoFPClass, ClassMask);
225 Attribute
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,
234 unsigned MinValue,
235 unsigned MaxValue) {
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) {
249 switch (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:
256 return "none";
257 default:
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"
267 .Default(false);
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) {
412 switch (MR) {
413 case ModRefInfo::NoModRef:
414 return "none";
415 case ModRefInfo::Ref:
416 return "read";
417 case ModRefInfo::Mod:
418 return "write";
419 case ModRefInfo::ModRef:
420 return "readwrite";
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();
433 Result += '(';
434 raw_string_ostream OS(Result);
435 getValueAsType()->print(OS, false, true);
436 OS.flush();
437 Result += ')';
438 return Result;
441 // FIXME: These should be output like this:
443 // align=4
444 // alignstack=8
446 if (hasAttribute(Attribute::Alignment))
447 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
448 : "align " + Twine(getValueAsInt()))
449 .str();
451 auto AttrWithBytesToString = [&](const char *Name) {
452 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
453 : Name + ("(" + Twine(getValueAsInt())) + ")")
454 .str();
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)) {
467 unsigned ElemSize;
468 std::optional<unsigned> NumElems;
469 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
471 return (NumElems
472 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
473 : "allocsize(" + Twine(ElemSize) + ")")
474 .str();
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)) + ")")
482 .str();
485 if (hasAttribute(Attribute::UWTable)) {
486 UWTableKind Kind = getUWTableKind();
487 if (Kind != UWTableKind::None) {
488 return Kind == UWTableKind::Default
489 ? "uwtable"
490 : ("uwtable(" +
491 Twine(Kind == UWTableKind::Sync ? "sync" : "async") + ")")
492 .str();
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(), ",")) + "\")")
513 .str();
516 if (hasAttribute(Attribute::Memory)) {
517 std::string Result;
518 raw_string_ostream OS(Result);
519 bool First = true;
520 OS << "memory(";
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) {
528 First = false;
529 OS << getModRefStr(OtherMR);
532 for (auto Loc : MemoryEffects::locations()) {
533 ModRefInfo MR = ME.getModRef(Loc);
534 if (MR == OtherMR)
535 continue;
537 if (!First)
538 OS << ", ";
539 First = false;
541 switch (Loc) {
542 case IRMemLocation::ArgMem:
543 OS << "argmem: ";
544 break;
545 case IRMemLocation::InaccessibleMem:
546 OS << "inaccessiblemem: ";
547 break;
548 case IRMemLocation::Other:
549 llvm_unreachable("This is represented as the default access kind");
551 OS << getModRefStr(MR);
553 OS << ")";
554 OS.flush();
555 return Result;
558 if (hasAttribute(Attribute::NoFPClass)) {
559 std::string Result = "nofpclass";
560 raw_string_ostream OS(Result);
561 OS << getNoFPClass();
562 return Result;
565 // Convert target-dependent attributes to strings of the form:
567 // "kind"
568 // "kind" = "value"
570 if (isStringAttribute()) {
571 std::string Result;
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()) {
581 OS << "=\"";
582 printEscapedString(AttrVal, OS);
583 OS << "\"";
586 return Result;
589 llvm_unreachable("Unknown attribute");
592 bool Attribute::hasParentContext(LLVMContext &C) const {
593 assert(isValid() && "invalid Attribute doesn't refer to any context");
594 FoldingSetNodeID ID;
595 pImpl->Profile(ID);
596 void *Unused;
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 {
612 FnAttr = (1 << 0),
613 ParamAttr = (1 << 1),
614 RetAttr = (1 << 2),
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 {
684 if (this == &AI)
685 return false;
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())
691 return true;
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())
702 return false;
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;
723 AttrBuilder B(C);
724 B.addAttribute(Kind);
725 return addAttributes(C, AttributeSet::get(C, B));
728 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
729 StringRef Value) const {
730 AttrBuilder B(C);
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())
738 return AS;
740 if (!AS.hasAttributes())
741 return *this;
743 AttrBuilder B(C, *this);
744 B.merge(AttrBuilder(C, AS));
745 return get(C, B);
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);
753 return get(C, B);
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);
761 return get(C, B);
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))
769 return *this;
771 B.remove(Attrs);
772 return get(C, B);
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 {
837 if (SetNode)
838 return SetNode->getAllocSizeArgs();
839 return std::nullopt;
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");
872 FoldingSetNodeID ID;
873 SetNode->Profile(ID);
874 void *Unused;
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 {
888 dbgs() << "AS =\n";
889 dbgs() << " { ";
890 dbgs() << getAsString(true) << " }\n";
892 #endif
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 });
906 else
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())
921 return nullptr;
923 // Build a key to look up the existing attributes.
924 LLVMContextImpl *pImpl = C.pImpl;
925 FoldingSetNodeID ID;
927 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
928 for (const auto &Attr : SortedAttrs)
929 Attr.Profile(ID);
931 void *InsertPoint;
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.
937 if (!PA) {
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.
945 return PA;
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))
960 return std::nullopt;
962 // Attributes in a set are sorted by enum value, followed by string
963 // attributes. Binary search the one we want.
964 const Attribute *I =
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?");
970 return *I;
973 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
974 if (auto A = findEnumAttribute(Kind))
975 return *A;
976 return {};
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();
986 return std::nullopt;
989 MaybeAlign AttributeSetNode::getStackAlignment() const {
990 if (auto A = findEnumAttribute(Attribute::StackAlignment))
991 return A->getStackAlignment();
992 return std::nullopt;
995 Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
996 if (auto A = findEnumAttribute(Kind))
997 return A->getValueAsType();
998 return nullptr;
1001 uint64_t AttributeSetNode::getDereferenceableBytes() const {
1002 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1003 return A->getDereferenceableBytes();
1004 return 0;
1007 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
1008 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1009 return A->getDereferenceableOrNullBytes();
1010 return 0;
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();
1023 return 1;
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();
1053 return fcNone;
1056 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1057 std::string Str;
1058 for (iterator I = begin(), E = end(); I != E; ++I) {
1059 if (I != begin())
1060 Str += ' ';
1061 Str += I->getAsString(InAttrGrp);
1063 return Str;
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) {
1073 return Index + 1;
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
1084 // summary bitsets.
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))
1108 return false;
1110 if (Index) {
1111 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1112 if (begin()[I].hasAttribute(Kind)) {
1113 *Index = I - 1;
1114 break;
1119 return true;
1123 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1124 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1125 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1127 #endif
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);
1141 void *InsertPoint;
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.
1147 if (!PA) {
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);
1160 AttributeList
1161 AttributeList::get(LLVMContext &C,
1162 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1163 // If there are no attributes then return a null AttributesList pointer.
1164 if (Attrs.empty())
1165 return {};
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();
1172 }) &&
1173 "Pointless attribute!");
1175 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1176 // list.
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);
1184 ++I;
1187 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1190 return get(C, AttrPairVec);
1193 AttributeList
1194 AttributeList::get(LLVMContext &C,
1195 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1196 // If there are no attributes then return a null AttributesList pointer.
1197 if (Attrs.empty())
1198 return {};
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();
1205 }) &&
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()) {
1230 NumSets = I + 2;
1231 break;
1234 if (NumSets == 0) {
1235 // Check function and return attributes if we didn't have argument
1236 // attributes.
1237 if (RetAttrs.hasAttributes())
1238 NumSets = 2;
1239 else if (FnAttrs.hasAttributes())
1240 NumSets = 1;
1243 // If all attribute sets were empty, we can use the empty attribute list.
1244 if (NumSets == 0)
1245 return {};
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);
1251 if (NumSets > 1)
1252 AttrSets.push_back(RetAttrs);
1253 if (NumSets > 2) {
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())
1265 return {};
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) {
1306 if (Attrs.empty())
1307 return {};
1308 if (Attrs.size() == 1)
1309 return Attrs[0];
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.
1316 if (MaxSize == 0)
1317 return {};
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);
1330 AttributeList
1331 AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1332 Attribute::AttrKind Kind) const {
1333 AttributeSet Attrs = getAttributes(Index);
1334 if (Attrs.hasAttribute(Kind))
1335 return *this;
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,
1343 StringRef Kind,
1344 StringRef Value) const {
1345 AttrBuilder B(C);
1346 B.addAttribute(Kind, Value);
1347 return addAttributesAtIndex(C, Index, B);
1350 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1351 Attribute A) const {
1352 AttrBuilder B(C);
1353 B.addAttribute(A);
1354 return addAttributesAtIndex(C, Index, B);
1357 AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1358 unsigned Index,
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())
1370 return {};
1371 return AttributeList::getImpl(C, AttrSets);
1374 AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1375 unsigned Index,
1376 const AttrBuilder &B) const {
1377 if (!B.hasAttributes())
1378 return *this;
1380 if (!pImpl)
1381 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1383 AttrBuilder Merged(C, getAttributes(Index));
1384 Merged.merge(B);
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]);
1401 B.addAttribute(A);
1402 AttrSets[Index] = AttributeSet::get(C, B);
1405 return getImpl(C, AttrSets);
1408 AttributeList
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)
1414 return *this;
1415 return setAttributesAtIndex(C, Index, NewAttrs);
1418 AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1419 unsigned Index,
1420 StringRef Kind) const {
1421 AttributeSet Attrs = getAttributes(Index);
1422 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1423 if (Attrs == NewAttrs)
1424 return *this;
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)
1434 return *this;
1435 return setAttributesAtIndex(C, Index, NewAttrs);
1438 AttributeList
1439 AttributeList::removeAttributesAtIndex(LLVMContext &C,
1440 unsigned WithoutIndex) const {
1441 if (!pImpl)
1442 return {};
1443 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1444 return *this;
1445 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1448 AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1449 uint64_t Bytes) const {
1450 AttrBuilder B(C);
1451 B.addDereferenceableAttr(Bytes);
1452 return addRetAttributes(C, B);
1455 AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1456 unsigned Index,
1457 uint64_t Bytes) const {
1458 AttrBuilder B(C);
1459 B.addDereferenceableAttr(Bytes);
1460 return addParamAttributes(C, Index, B);
1463 AttributeList
1464 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1465 uint64_t Bytes) const {
1466 AttrBuilder B(C);
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) {
1474 AttrBuilder B(C);
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();
1587 uint64_t
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())
1619 return {};
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;
1626 pImpl->Profile(ID);
1627 void *Unused;
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())
1652 continue;
1653 O << " { ";
1654 switch (i) {
1655 case AttrIndex::ReturnIndex:
1656 O << "return";
1657 break;
1658 case AttrIndex::FunctionIndex:
1659 O << "function";
1660 break;
1661 default:
1662 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1664 O << " => " << getAsString(i) << " }\n";
1667 O << "]\n";
1670 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1671 LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
1672 #endif
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();
1691 if (A0IsString) {
1692 if (A1IsString)
1693 return A0.getKindAsString() < A1.getKindAsString();
1694 else
1695 return false;
1697 if (A1IsString)
1698 return true;
1699 return A0.getKindAsEnum() < A1.getKindAsEnum();
1701 bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
1702 if (A0.isStringAttribute())
1703 return false;
1704 return A0.getKindAsEnum() < Kind;
1706 bool operator()(Attribute A0, StringRef Kind) const {
1707 if (A0.isStringAttribute())
1708 return A0.getKindAsString() < Kind;
1709 return true;
1713 template <typename K>
1714 static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
1715 Attribute Attr) {
1716 auto It = lower_bound(Attrs, Kind, AttributeComparator());
1717 if (It != Attrs.end() && It->hasAttribute(Kind))
1718 std::swap(*It, Attr);
1719 else
1720 Attrs.insert(It, Attr);
1723 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1724 if (Attr.isStringAttribute())
1725 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1726 else
1727 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
1728 return *this;
1731 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
1732 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
1733 return *this;
1736 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1737 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
1738 return *this;
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))
1745 Attrs.erase(It);
1746 return *this;
1749 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1750 auto It = lower_bound(Attrs, A, AttributeComparator());
1751 if (It != Attrs.end() && It->hasAttribute(A))
1752 Attrs.erase(It);
1753 return *this;
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);
1760 if (A.isValid())
1761 return A.getValueAsInt();
1762 return std::nullopt;
1765 AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
1766 uint64_t Value) {
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);
1773 if (A.isValid())
1774 return A.getAllocSizeArgs();
1775 return std::nullopt;
1778 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1779 if (!Align)
1780 return *this;
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.
1788 if (!Align)
1789 return *this;
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) {
1802 if (Bytes == 0)
1803 return *this;
1805 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
1808 AttrBuilder &
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
1827 if (RawArgs == 0)
1828 return *this;
1830 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1833 AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
1834 if (Kind == UWTableKind::None)
1835 return *this;
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) {
1844 if (Mask == fcNone)
1845 return *this;
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())
1887 addAttribute(I);
1889 return *this;
1892 AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
1893 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
1894 return *this;
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))
1905 return *It;
1906 return {};
1909 Attribute AttrBuilder::getAttribute(StringRef A) const {
1910 auto It = lower_bound(Attrs, A, AttributeComparator());
1911 if (It != Attrs.end() && It->hasAttribute(A))
1912 return *It;
1913 return {};
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() {
2000 AttributeMask AM;
2001 AM.addAttribute(Attribute::NoUndef);
2002 AM.addAttribute(Attribute::Dereferenceable);
2003 AM.addAttribute(Attribute::DereferenceableOrNull);
2004 return AM;
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())
2011 return true;
2013 // If they don't exactly match, it's OK if the mismatched component is
2014 // dynamic.
2015 if (CalleeMode.Input == CallerMode.Input &&
2016 CalleeMode.Output == DenormalMode::Dynamic)
2017 return true;
2019 if (CalleeMode.Output == CallerMode.Output &&
2020 CalleeMode.Input == DenormalMode::Dynamic)
2021 return true;
2022 return false;
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);
2039 return false;
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
2054 /// callee.
2056 /// This function sets the caller's attribute to false if the callee's attribute
2057 /// is false.
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
2066 /// callee.
2068 /// This function sets the caller's attribute to true if the callee's attribute
2069 /// is true.
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())
2084 return;
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.
2119 static void
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);
2132 } else {
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.
2147 static void
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);
2158 } else {
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.
2168 static void
2169 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2170 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2171 Caller.addFnAttr(Attribute::NullPointerIsValid);
2175 struct EnumAttr {
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) {
2183 if (Val)
2184 Fn.addFnAttr(Kind);
2185 else
2186 Fn.removeFnAttr(Kind);
2190 struct StrBoolAttr {
2191 static bool isSet(const Function &Fn,
2192 StringRef Kind) {
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
2240 // is not set.
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,
2248 uint64_t Width) {
2249 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2250 if (Attr.isValid()) {
2251 uint64_t OldWidth;
2252 Attr.getValueAsString().getAsInteger(0, OldWidth);
2253 if (Width > OldWidth)
2254 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));