1 //===- Attributes.cpp - Implement AttributesList --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // \file
10 // This file implements the Attribute, AttributeImpl, AttrBuilder,
11 // AttributeListImpl, and AttributeList classes.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/IR/Attributes.h"
16 #include "AttributeImpl.h"
17 #include "LLVMContextImpl.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/FoldingSet.h"
20 #include "llvm/ADT/STLExtras.h"
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/Function.h"
27 #include "llvm/IR/LLVMContext.h"
28 #include "llvm/IR/Type.h"
29 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/ModRef.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include <algorithm>
34 #include <cassert>
35 #include <cstddef>
36 #include <cstdint>
37 #include <limits>
38 #include <optional>
39 #include <string>
40 #include <tuple>
41 #include <utility>
42
43 using namespace llvm;
44
45 //===----------------------------------------------------------------------===//
46 // Attribute Construction Methods
47 //===----------------------------------------------------------------------===//
48
49 // allocsize has two integer arguments, but because they're both 32 bits, we can
50 // pack them into one 64-bit value, at the cost of making said value
51 // nonsensical.
52 //
53 // In order to do this, we need to reserve one value of the second (optional)
54 // allocsize argument to signify "not present."
55 static const unsigned AllocSizeNumElemsNotPresent = -1;
56
packAllocSizeArgs(unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)57 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
58 const std::optional<unsigned> &NumElemsArg) {
59 assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
60 "Attempting to pack a reserved value");
61
62 return uint64_t(ElemSizeArg) << 32 |
63 NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
64 }
65
66 static std::pair<unsigned, std::optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)67 unpackAllocSizeArgs(uint64_t Num) {
68 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
69 unsigned ElemSizeArg = Num >> 32;
70
71 std::optional<unsigned> NumElemsArg;
72 if (NumElems != AllocSizeNumElemsNotPresent)
73 NumElemsArg = NumElems;
74 return std::make_pair(ElemSizeArg, NumElemsArg);
75 }
76
packVScaleRangeArgs(unsigned MinValue,std::optional<unsigned> MaxValue)77 static uint64_t packVScaleRangeArgs(unsigned MinValue,
78 std::optional<unsigned> MaxValue) {
79 return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
80 }
81
82 static std::pair<unsigned, std::optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value)83 unpackVScaleRangeArgs(uint64_t Value) {
84 unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
85 unsigned MinValue = Value >> 32;
86
87 return std::make_pair(MinValue,
88 MaxValue > 0 ? MaxValue : std::optional<unsigned>());
89 }
90
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)91 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
92 uint64_t Val) {
93 bool IsIntAttr = Attribute::isIntAttrKind(Kind);
94 assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
95 "Not an enum or int attribute");
96
97 LLVMContextImpl *pImpl = Context.pImpl;
98 FoldingSetNodeID ID;
99 ID.AddInteger(Kind);
100 if (IsIntAttr)
101 ID.AddInteger(Val);
102 else
103 assert(Val == 0 && "Value must be zero for enum attributes");
104
105 void *InsertPoint;
106 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
107
108 if (!PA) {
109 // If we didn't find any existing attributes of the same shape then create a
110 // new one and insert it.
111 if (!IsIntAttr)
112 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
113 else
114 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
115 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
116 }
117
118 // Return the Attribute that we found or created.
119 return Attribute(PA);
120 }
121
get(LLVMContext & Context,StringRef Kind,StringRef Val)122 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
123 LLVMContextImpl *pImpl = Context.pImpl;
124 FoldingSetNodeID ID;
125 ID.AddString(Kind);
126 if (!Val.empty()) ID.AddString(Val);
127
128 void *InsertPoint;
129 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
130
131 if (!PA) {
132 // If we didn't find any existing attributes of the same shape then create a
133 // new one and insert it.
134 void *Mem =
135 pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
136 alignof(StringAttributeImpl));
137 PA = new (Mem) StringAttributeImpl(Kind, Val);
138 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
139 }
140
141 // Return the Attribute that we found or created.
142 return Attribute(PA);
143 }
144
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)145 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
146 Type *Ty) {
147 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
148 LLVMContextImpl *pImpl = Context.pImpl;
149 FoldingSetNodeID ID;
150 ID.AddInteger(Kind);
151 ID.AddPointer(Ty);
152
153 void *InsertPoint;
154 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
155
156 if (!PA) {
157 // If we didn't find any existing attributes of the same shape then create a
158 // new one and insert it.
159 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
160 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
161 }
162
163 // Return the Attribute that we found or created.
164 return Attribute(PA);
165 }
166
getWithAlignment(LLVMContext & Context,Align A)167 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
168 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
169 return get(Context, Alignment, A.value());
170 }
171
getWithStackAlignment(LLVMContext & Context,Align A)172 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
173 assert(A <= 0x100 && "Alignment too large.");
174 return get(Context, StackAlignment, A.value());
175 }
176
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)177 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
178 uint64_t Bytes) {
179 assert(Bytes && "Bytes must be non-zero.");
180 return get(Context, Dereferenceable, Bytes);
181 }
182
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)183 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
184 uint64_t Bytes) {
185 assert(Bytes && "Bytes must be non-zero.");
186 return get(Context, DereferenceableOrNull, Bytes);
187 }
188
getWithByValType(LLVMContext & Context,Type * Ty)189 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
190 return get(Context, ByVal, Ty);
191 }
192
getWithStructRetType(LLVMContext & Context,Type * Ty)193 Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
194 return get(Context, StructRet, Ty);
195 }
196
getWithByRefType(LLVMContext & Context,Type * Ty)197 Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
198 return get(Context, ByRef, Ty);
199 }
200
getWithPreallocatedType(LLVMContext & Context,Type * Ty)201 Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
202 return get(Context, Preallocated, Ty);
203 }
204
getWithInAllocaType(LLVMContext & Context,Type * Ty)205 Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
206 return get(Context, InAlloca, Ty);
207 }
208
getWithUWTableKind(LLVMContext & Context,UWTableKind Kind)209 Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
210 UWTableKind Kind) {
211 return get(Context, UWTable, uint64_t(Kind));
212 }
213
getWithMemoryEffects(LLVMContext & Context,MemoryEffects ME)214 Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
215 MemoryEffects ME) {
216 return get(Context, Memory, ME.toIntValue());
217 }
218
219 Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)220 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
221 const std::optional<unsigned> &NumElemsArg) {
222 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
223 "Invalid allocsize arguments -- given allocsize(0, 0)");
224 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
225 }
226
getWithVScaleRangeArgs(LLVMContext & Context,unsigned MinValue,unsigned MaxValue)227 Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
228 unsigned MinValue,
229 unsigned MaxValue) {
230 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
231 }
232
getAttrKindFromName(StringRef AttrName)233 Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
234 return StringSwitch<Attribute::AttrKind>(AttrName)
235 #define GET_ATTR_NAMES
236 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
237 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
238 #include "llvm/IR/Attributes.inc"
239 .Default(Attribute::None);
240 }
241
getNameFromAttrKind(Attribute::AttrKind AttrKind)242 StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
243 switch (AttrKind) {
244 #define GET_ATTR_NAMES
245 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
246 case Attribute::ENUM_NAME: \
247 return #DISPLAY_NAME;
248 #include "llvm/IR/Attributes.inc"
249 case Attribute::None:
250 return "none";
251 default:
252 llvm_unreachable("invalid Kind");
253 }
254 }
255
isExistingAttribute(StringRef Name)256 bool Attribute::isExistingAttribute(StringRef Name) {
257 return StringSwitch<bool>(Name)
258 #define GET_ATTR_NAMES
259 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
260 #include "llvm/IR/Attributes.inc"
261 .Default(false);
262 }
263
264 //===----------------------------------------------------------------------===//
265 // Attribute Accessor Methods
266 //===----------------------------------------------------------------------===//
267
isEnumAttribute() const268 bool Attribute::isEnumAttribute() const {
269 return pImpl && pImpl->isEnumAttribute();
270 }
271
isIntAttribute() const272 bool Attribute::isIntAttribute() const {
273 return pImpl && pImpl->isIntAttribute();
274 }
275
isStringAttribute() const276 bool Attribute::isStringAttribute() const {
277 return pImpl && pImpl->isStringAttribute();
278 }
279
isTypeAttribute() const280 bool Attribute::isTypeAttribute() const {
281 return pImpl && pImpl->isTypeAttribute();
282 }
283
getKindAsEnum() const284 Attribute::AttrKind Attribute::getKindAsEnum() const {
285 if (!pImpl) return None;
286 assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
287 "Invalid attribute type to get the kind as an enum!");
288 return pImpl->getKindAsEnum();
289 }
290
getValueAsInt() const291 uint64_t Attribute::getValueAsInt() const {
292 if (!pImpl) return 0;
293 assert(isIntAttribute() &&
294 "Expected the attribute to be an integer attribute!");
295 return pImpl->getValueAsInt();
296 }
297
getValueAsBool() const298 bool Attribute::getValueAsBool() const {
299 if (!pImpl) return false;
300 assert(isStringAttribute() &&
301 "Expected the attribute to be a string attribute!");
302 return pImpl->getValueAsBool();
303 }
304
getKindAsString() const305 StringRef Attribute::getKindAsString() const {
306 if (!pImpl) return {};
307 assert(isStringAttribute() &&
308 "Invalid attribute type to get the kind as a string!");
309 return pImpl->getKindAsString();
310 }
311
getValueAsString() const312 StringRef Attribute::getValueAsString() const {
313 if (!pImpl) return {};
314 assert(isStringAttribute() &&
315 "Invalid attribute type to get the value as a string!");
316 return pImpl->getValueAsString();
317 }
318
getValueAsType() const319 Type *Attribute::getValueAsType() const {
320 if (!pImpl) return {};
321 assert(isTypeAttribute() &&
322 "Invalid attribute type to get the value as a type!");
323 return pImpl->getValueAsType();
324 }
325
326
hasAttribute(AttrKind Kind) const327 bool Attribute::hasAttribute(AttrKind Kind) const {
328 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
329 }
330
hasAttribute(StringRef Kind) const331 bool Attribute::hasAttribute(StringRef Kind) const {
332 if (!isStringAttribute()) return false;
333 return pImpl && pImpl->hasAttribute(Kind);
334 }
335
getAlignment() const336 MaybeAlign Attribute::getAlignment() const {
337 assert(hasAttribute(Attribute::Alignment) &&
338 "Trying to get alignment from non-alignment attribute!");
339 return MaybeAlign(pImpl->getValueAsInt());
340 }
341
getStackAlignment() const342 MaybeAlign Attribute::getStackAlignment() const {
343 assert(hasAttribute(Attribute::StackAlignment) &&
344 "Trying to get alignment from non-alignment attribute!");
345 return MaybeAlign(pImpl->getValueAsInt());
346 }
347
getDereferenceableBytes() const348 uint64_t Attribute::getDereferenceableBytes() const {
349 assert(hasAttribute(Attribute::Dereferenceable) &&
350 "Trying to get dereferenceable bytes from "
351 "non-dereferenceable attribute!");
352 return pImpl->getValueAsInt();
353 }
354
getDereferenceableOrNullBytes() const355 uint64_t Attribute::getDereferenceableOrNullBytes() const {
356 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
357 "Trying to get dereferenceable bytes from "
358 "non-dereferenceable attribute!");
359 return pImpl->getValueAsInt();
360 }
361
362 std::pair<unsigned, std::optional<unsigned>>
getAllocSizeArgs() const363 Attribute::getAllocSizeArgs() const {
364 assert(hasAttribute(Attribute::AllocSize) &&
365 "Trying to get allocsize args from non-allocsize attribute");
366 return unpackAllocSizeArgs(pImpl->getValueAsInt());
367 }
368
getVScaleRangeMin() const369 unsigned Attribute::getVScaleRangeMin() const {
370 assert(hasAttribute(Attribute::VScaleRange) &&
371 "Trying to get vscale args from non-vscale attribute");
372 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
373 }
374
getVScaleRangeMax() const375 std::optional<unsigned> Attribute::getVScaleRangeMax() const {
376 assert(hasAttribute(Attribute::VScaleRange) &&
377 "Trying to get vscale args from non-vscale attribute");
378 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
379 }
380
getUWTableKind() const381 UWTableKind Attribute::getUWTableKind() const {
382 assert(hasAttribute(Attribute::UWTable) &&
383 "Trying to get unwind table kind from non-uwtable attribute");
384 return UWTableKind(pImpl->getValueAsInt());
385 }
386
getAllocKind() const387 AllocFnKind Attribute::getAllocKind() const {
388 assert(hasAttribute(Attribute::AllocKind) &&
389 "Trying to get allockind value from non-allockind attribute");
390 return AllocFnKind(pImpl->getValueAsInt());
391 }
392
getMemoryEffects() const393 MemoryEffects Attribute::getMemoryEffects() const {
394 assert(hasAttribute(Attribute::Memory) &&
395 "Can only call getMemoryEffects() on memory attribute");
396 return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
397 }
398
getModRefStr(ModRefInfo MR)399 static const char *getModRefStr(ModRefInfo MR) {
400 switch (MR) {
401 case ModRefInfo::NoModRef:
402 return "none";
403 case ModRefInfo::Ref:
404 return "read";
405 case ModRefInfo::Mod:
406 return "write";
407 case ModRefInfo::ModRef:
408 return "readwrite";
409 }
410 llvm_unreachable("Invalid ModRefInfo");
411 }
412
getAsString(bool InAttrGrp) const413 std::string Attribute::getAsString(bool InAttrGrp) const {
414 if (!pImpl) return {};
415
416 if (isEnumAttribute())
417 return getNameFromAttrKind(getKindAsEnum()).str();
418
419 if (isTypeAttribute()) {
420 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
421 Result += '(';
422 raw_string_ostream OS(Result);
423 getValueAsType()->print(OS, false, true);
424 OS.flush();
425 Result += ')';
426 return Result;
427 }
428
429 // FIXME: These should be output like this:
430 //
431 // align=4
432 // alignstack=8
433 //
434 if (hasAttribute(Attribute::Alignment))
435 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
436 : "align " + Twine(getValueAsInt()))
437 .str();
438
439 auto AttrWithBytesToString = [&](const char *Name) {
440 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
441 : Name + ("(" + Twine(getValueAsInt())) + ")")
442 .str();
443 };
444
445 if (hasAttribute(Attribute::StackAlignment))
446 return AttrWithBytesToString("alignstack");
447
448 if (hasAttribute(Attribute::Dereferenceable))
449 return AttrWithBytesToString("dereferenceable");
450
451 if (hasAttribute(Attribute::DereferenceableOrNull))
452 return AttrWithBytesToString("dereferenceable_or_null");
453
454 if (hasAttribute(Attribute::AllocSize)) {
455 unsigned ElemSize;
456 std::optional<unsigned> NumElems;
457 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
458
459 return (NumElems
460 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
461 : "allocsize(" + Twine(ElemSize) + ")")
462 .str();
463 }
464
465 if (hasAttribute(Attribute::VScaleRange)) {
466 unsigned MinValue = getVScaleRangeMin();
467 std::optional<unsigned> MaxValue = getVScaleRangeMax();
468 return ("vscale_range(" + Twine(MinValue) + "," +
469 Twine(MaxValue.value_or(0)) + ")")
470 .str();
471 }
472
473 if (hasAttribute(Attribute::UWTable)) {
474 UWTableKind Kind = getUWTableKind();
475 if (Kind != UWTableKind::None) {
476 return Kind == UWTableKind::Default
477 ? "uwtable"
478 : ("uwtable(" +
479 Twine(Kind == UWTableKind::Sync ? "sync" : "async") + ")")
480 .str();
481 }
482 }
483
484 if (hasAttribute(Attribute::AllocKind)) {
485 AllocFnKind Kind = getAllocKind();
486 SmallVector<StringRef> parts;
487 if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
488 parts.push_back("alloc");
489 if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
490 parts.push_back("realloc");
491 if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
492 parts.push_back("free");
493 if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
494 parts.push_back("uninitialized");
495 if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
496 parts.push_back("zeroed");
497 if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
498 parts.push_back("aligned");
499 return ("allockind(\"" +
500 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
501 .str();
502 }
503
504 if (hasAttribute(Attribute::Memory)) {
505 std::string Result;
506 raw_string_ostream OS(Result);
507 bool First = true;
508 OS << "memory(";
509
510 MemoryEffects ME = getMemoryEffects();
511
512 // Print access kind for "other" as the default access kind. This way it
513 // will apply to any new location kinds that get split out of "other".
514 ModRefInfo OtherMR = ME.getModRef(MemoryEffects::Other);
515 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
516 First = false;
517 OS << getModRefStr(OtherMR);
518 }
519
520 for (auto Loc : MemoryEffects::locations()) {
521 ModRefInfo MR = ME.getModRef(Loc);
522 if (MR == OtherMR)
523 continue;
524
525 if (!First)
526 OS << ", ";
527 First = false;
528
529 switch (Loc) {
530 case MemoryEffects::ArgMem:
531 OS << "argmem: ";
532 break;
533 case MemoryEffects::InaccessibleMem:
534 OS << "inaccessiblemem: ";
535 break;
536 case MemoryEffects::Other:
537 llvm_unreachable("This is represented as the default access kind");
538 }
539 OS << getModRefStr(MR);
540 }
541 OS << ")";
542 OS.flush();
543 return Result;
544 }
545
546 // Convert target-dependent attributes to strings of the form:
547 //
548 // "kind"
549 // "kind" = "value"
550 //
551 if (isStringAttribute()) {
552 std::string Result;
553 {
554 raw_string_ostream OS(Result);
555 OS << '"' << getKindAsString() << '"';
556
557 // Since some attribute strings contain special characters that cannot be
558 // printable, those have to be escaped to make the attribute value
559 // printable as is. e.g. "\01__gnu_mcount_nc"
560 const auto &AttrVal = pImpl->getValueAsString();
561 if (!AttrVal.empty()) {
562 OS << "=\"";
563 printEscapedString(AttrVal, OS);
564 OS << "\"";
565 }
566 }
567 return Result;
568 }
569
570 llvm_unreachable("Unknown attribute");
571 }
572
hasParentContext(LLVMContext & C) const573 bool Attribute::hasParentContext(LLVMContext &C) const {
574 assert(isValid() && "invalid Attribute doesn't refer to any context");
575 FoldingSetNodeID ID;
576 pImpl->Profile(ID);
577 void *Unused;
578 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
579 }
580
operator <(Attribute A) const581 bool Attribute::operator<(Attribute A) const {
582 if (!pImpl && !A.pImpl) return false;
583 if (!pImpl) return true;
584 if (!A.pImpl) return false;
585 return *pImpl < *A.pImpl;
586 }
587
Profile(FoldingSetNodeID & ID) const588 void Attribute::Profile(FoldingSetNodeID &ID) const {
589 ID.AddPointer(pImpl);
590 }
591
592 enum AttributeProperty {
593 FnAttr = (1 << 0),
594 ParamAttr = (1 << 1),
595 RetAttr = (1 << 2),
596 };
597
598 #define GET_ATTR_PROP_TABLE
599 #include "llvm/IR/Attributes.inc"
600
hasAttributeProperty(Attribute::AttrKind Kind,AttributeProperty Prop)601 static bool hasAttributeProperty(Attribute::AttrKind Kind,
602 AttributeProperty Prop) {
603 unsigned Index = Kind - 1;
604 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
605 return AttrPropTable[Index] & Prop;
606 }
607
canUseAsFnAttr(AttrKind Kind)608 bool Attribute::canUseAsFnAttr(AttrKind Kind) {
609 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
610 }
611
canUseAsParamAttr(AttrKind Kind)612 bool Attribute::canUseAsParamAttr(AttrKind Kind) {
613 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
614 }
615
canUseAsRetAttr(AttrKind Kind)616 bool Attribute::canUseAsRetAttr(AttrKind Kind) {
617 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
618 }
619
620 //===----------------------------------------------------------------------===//
621 // AttributeImpl Definition
622 //===----------------------------------------------------------------------===//
623
hasAttribute(Attribute::AttrKind A) const624 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
625 if (isStringAttribute()) return false;
626 return getKindAsEnum() == A;
627 }
628
hasAttribute(StringRef Kind) const629 bool AttributeImpl::hasAttribute(StringRef Kind) const {
630 if (!isStringAttribute()) return false;
631 return getKindAsString() == Kind;
632 }
633
getKindAsEnum() const634 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
635 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
636 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
637 }
638
getValueAsInt() const639 uint64_t AttributeImpl::getValueAsInt() const {
640 assert(isIntAttribute());
641 return static_cast<const IntAttributeImpl *>(this)->getValue();
642 }
643
getValueAsBool() const644 bool AttributeImpl::getValueAsBool() const {
645 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
646 return getValueAsString() == "true";
647 }
648
getKindAsString() const649 StringRef AttributeImpl::getKindAsString() const {
650 assert(isStringAttribute());
651 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
652 }
653
getValueAsString() const654 StringRef AttributeImpl::getValueAsString() const {
655 assert(isStringAttribute());
656 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
657 }
658
getValueAsType() const659 Type *AttributeImpl::getValueAsType() const {
660 assert(isTypeAttribute());
661 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
662 }
663
operator <(const AttributeImpl & AI) const664 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
665 if (this == &AI)
666 return false;
667
668 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
669 // relative to their enum value) and then strings.
670 if (!isStringAttribute()) {
671 if (AI.isStringAttribute())
672 return true;
673 if (getKindAsEnum() != AI.getKindAsEnum())
674 return getKindAsEnum() < AI.getKindAsEnum();
675 assert(!AI.isEnumAttribute() && "Non-unique attribute");
676 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
677 // TODO: Is this actually needed?
678 assert(AI.isIntAttribute() && "Only possibility left");
679 return getValueAsInt() < AI.getValueAsInt();
680 }
681
682 if (!AI.isStringAttribute())
683 return false;
684 if (getKindAsString() == AI.getKindAsString())
685 return getValueAsString() < AI.getValueAsString();
686 return getKindAsString() < AI.getKindAsString();
687 }
688
689 //===----------------------------------------------------------------------===//
690 // AttributeSet Definition
691 //===----------------------------------------------------------------------===//
692
get(LLVMContext & C,const AttrBuilder & B)693 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
694 return AttributeSet(AttributeSetNode::get(C, B));
695 }
696
get(LLVMContext & C,ArrayRef<Attribute> Attrs)697 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
698 return AttributeSet(AttributeSetNode::get(C, Attrs));
699 }
700
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const701 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
702 Attribute::AttrKind Kind) const {
703 if (hasAttribute(Kind)) return *this;
704 AttrBuilder B(C);
705 B.addAttribute(Kind);
706 return addAttributes(C, AttributeSet::get(C, B));
707 }
708
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const709 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
710 StringRef Value) const {
711 AttrBuilder B(C);
712 B.addAttribute(Kind, Value);
713 return addAttributes(C, AttributeSet::get(C, B));
714 }
715
addAttributes(LLVMContext & C,const AttributeSet AS) const716 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
717 const AttributeSet AS) const {
718 if (!hasAttributes())
719 return AS;
720
721 if (!AS.hasAttributes())
722 return *this;
723
724 AttrBuilder B(C, *this);
725 B.merge(AttrBuilder(C, AS));
726 return get(C, B);
727 }
728
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const729 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
730 Attribute::AttrKind Kind) const {
731 if (!hasAttribute(Kind)) return *this;
732 AttrBuilder B(C, *this);
733 B.removeAttribute(Kind);
734 return get(C, B);
735 }
736
removeAttribute(LLVMContext & C,StringRef Kind) const737 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
738 StringRef Kind) const {
739 if (!hasAttribute(Kind)) return *this;
740 AttrBuilder B(C, *this);
741 B.removeAttribute(Kind);
742 return get(C, B);
743 }
744
removeAttributes(LLVMContext & C,const AttributeMask & Attrs) const745 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
746 const AttributeMask &Attrs) const {
747 AttrBuilder B(C, *this);
748 // If there is nothing to remove, directly return the original set.
749 if (!B.overlaps(Attrs))
750 return *this;
751
752 B.remove(Attrs);
753 return get(C, B);
754 }
755
getNumAttributes() const756 unsigned AttributeSet::getNumAttributes() const {
757 return SetNode ? SetNode->getNumAttributes() : 0;
758 }
759
hasAttribute(Attribute::AttrKind Kind) const760 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
761 return SetNode ? SetNode->hasAttribute(Kind) : false;
762 }
763
hasAttribute(StringRef Kind) const764 bool AttributeSet::hasAttribute(StringRef Kind) const {
765 return SetNode ? SetNode->hasAttribute(Kind) : false;
766 }
767
getAttribute(Attribute::AttrKind Kind) const768 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
769 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
770 }
771
getAttribute(StringRef Kind) const772 Attribute AttributeSet::getAttribute(StringRef Kind) const {
773 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
774 }
775
getAlignment() const776 MaybeAlign AttributeSet::getAlignment() const {
777 return SetNode ? SetNode->getAlignment() : std::nullopt;
778 }
779
getStackAlignment() const780 MaybeAlign AttributeSet::getStackAlignment() const {
781 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
782 }
783
getDereferenceableBytes() const784 uint64_t AttributeSet::getDereferenceableBytes() const {
785 return SetNode ? SetNode->getDereferenceableBytes() : 0;
786 }
787
getDereferenceableOrNullBytes() const788 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
789 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
790 }
791
getByRefType() const792 Type *AttributeSet::getByRefType() const {
793 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
794 }
795
getByValType() const796 Type *AttributeSet::getByValType() const {
797 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
798 }
799
getStructRetType() const800 Type *AttributeSet::getStructRetType() const {
801 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
802 }
803
getPreallocatedType() const804 Type *AttributeSet::getPreallocatedType() const {
805 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
806 }
807
getInAllocaType() const808 Type *AttributeSet::getInAllocaType() const {
809 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
810 }
811
getElementType() const812 Type *AttributeSet::getElementType() const {
813 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
814 }
815
816 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const817 AttributeSet::getAllocSizeArgs() const {
818 if (SetNode)
819 return SetNode->getAllocSizeArgs();
820 return std::nullopt;
821 }
822
getVScaleRangeMin() const823 unsigned AttributeSet::getVScaleRangeMin() const {
824 return SetNode ? SetNode->getVScaleRangeMin() : 1;
825 }
826
getVScaleRangeMax() const827 std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
828 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
829 }
830
getUWTableKind() const831 UWTableKind AttributeSet::getUWTableKind() const {
832 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
833 }
834
getAllocKind() const835 AllocFnKind AttributeSet::getAllocKind() const {
836 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
837 }
838
getMemoryEffects() const839 MemoryEffects AttributeSet::getMemoryEffects() const {
840 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
841 }
842
getAsString(bool InAttrGrp) const843 std::string AttributeSet::getAsString(bool InAttrGrp) const {
844 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
845 }
846
hasParentContext(LLVMContext & C) const847 bool AttributeSet::hasParentContext(LLVMContext &C) const {
848 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
849 FoldingSetNodeID ID;
850 SetNode->Profile(ID);
851 void *Unused;
852 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
853 }
854
begin() const855 AttributeSet::iterator AttributeSet::begin() const {
856 return SetNode ? SetNode->begin() : nullptr;
857 }
858
end() const859 AttributeSet::iterator AttributeSet::end() const {
860 return SetNode ? SetNode->end() : nullptr;
861 }
862
863 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const864 LLVM_DUMP_METHOD void AttributeSet::dump() const {
865 dbgs() << "AS =\n";
866 dbgs() << " { ";
867 dbgs() << getAsString(true) << " }\n";
868 }
869 #endif
870
871 //===----------------------------------------------------------------------===//
872 // AttributeSetNode Definition
873 //===----------------------------------------------------------------------===//
874
AttributeSetNode(ArrayRef<Attribute> Attrs)875 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
876 : NumAttrs(Attrs.size()) {
877 // There's memory after the node where we can store the entries in.
878 llvm::copy(Attrs, getTrailingObjects<Attribute>());
879
880 for (const auto &I : *this) {
881 if (I.isStringAttribute())
882 StringAttrs.insert({ I.getKindAsString(), I });
883 else
884 AvailableAttrs.addAttribute(I.getKindAsEnum());
885 }
886 }
887
get(LLVMContext & C,ArrayRef<Attribute> Attrs)888 AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
889 ArrayRef<Attribute> Attrs) {
890 SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
891 llvm::sort(SortedAttrs);
892 return getSorted(C, SortedAttrs);
893 }
894
getSorted(LLVMContext & C,ArrayRef<Attribute> SortedAttrs)895 AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
896 ArrayRef<Attribute> SortedAttrs) {
897 if (SortedAttrs.empty())
898 return nullptr;
899
900 // Build a key to look up the existing attributes.
901 LLVMContextImpl *pImpl = C.pImpl;
902 FoldingSetNodeID ID;
903
904 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
905 for (const auto &Attr : SortedAttrs)
906 Attr.Profile(ID);
907
908 void *InsertPoint;
909 AttributeSetNode *PA =
910 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
911
912 // If we didn't find any existing attributes of the same shape then create a
913 // new one and insert it.
914 if (!PA) {
915 // Coallocate entries after the AttributeSetNode itself.
916 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
917 PA = new (Mem) AttributeSetNode(SortedAttrs);
918 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
919 }
920
921 // Return the AttributeSetNode that we found or created.
922 return PA;
923 }
924
get(LLVMContext & C,const AttrBuilder & B)925 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
926 return getSorted(C, B.attrs());
927 }
928
hasAttribute(StringRef Kind) const929 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
930 return StringAttrs.count(Kind);
931 }
932
933 std::optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const934 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
935 // Do a quick presence check.
936 if (!hasAttribute(Kind))
937 return std::nullopt;
938
939 // Attributes in a set are sorted by enum value, followed by string
940 // attributes. Binary search the one we want.
941 const Attribute *I =
942 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
943 [](Attribute A, Attribute::AttrKind Kind) {
944 return A.getKindAsEnum() < Kind;
945 });
946 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
947 return *I;
948 }
949
getAttribute(Attribute::AttrKind Kind) const950 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
951 if (auto A = findEnumAttribute(Kind))
952 return *A;
953 return {};
954 }
955
getAttribute(StringRef Kind) const956 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
957 return StringAttrs.lookup(Kind);
958 }
959
getAlignment() const960 MaybeAlign AttributeSetNode::getAlignment() const {
961 if (auto A = findEnumAttribute(Attribute::Alignment))
962 return A->getAlignment();
963 return std::nullopt;
964 }
965
getStackAlignment() const966 MaybeAlign AttributeSetNode::getStackAlignment() const {
967 if (auto A = findEnumAttribute(Attribute::StackAlignment))
968 return A->getStackAlignment();
969 return std::nullopt;
970 }
971
getAttributeType(Attribute::AttrKind Kind) const972 Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
973 if (auto A = findEnumAttribute(Kind))
974 return A->getValueAsType();
975 return nullptr;
976 }
977
getDereferenceableBytes() const978 uint64_t AttributeSetNode::getDereferenceableBytes() const {
979 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
980 return A->getDereferenceableBytes();
981 return 0;
982 }
983
getDereferenceableOrNullBytes() const984 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
985 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
986 return A->getDereferenceableOrNullBytes();
987 return 0;
988 }
989
990 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const991 AttributeSetNode::getAllocSizeArgs() const {
992 if (auto A = findEnumAttribute(Attribute::AllocSize))
993 return A->getAllocSizeArgs();
994 return std::nullopt;
995 }
996
getVScaleRangeMin() const997 unsigned AttributeSetNode::getVScaleRangeMin() const {
998 if (auto A = findEnumAttribute(Attribute::VScaleRange))
999 return A->getVScaleRangeMin();
1000 return 1;
1001 }
1002
getVScaleRangeMax() const1003 std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1004 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1005 return A->getVScaleRangeMax();
1006 return std::nullopt;
1007 }
1008
getUWTableKind() const1009 UWTableKind AttributeSetNode::getUWTableKind() const {
1010 if (auto A = findEnumAttribute(Attribute::UWTable))
1011 return A->getUWTableKind();
1012 return UWTableKind::None;
1013 }
1014
getAllocKind() const1015 AllocFnKind AttributeSetNode::getAllocKind() const {
1016 if (auto A = findEnumAttribute(Attribute::AllocKind))
1017 return A->getAllocKind();
1018 return AllocFnKind::Unknown;
1019 }
1020
getMemoryEffects() const1021 MemoryEffects AttributeSetNode::getMemoryEffects() const {
1022 if (auto A = findEnumAttribute(Attribute::Memory))
1023 return A->getMemoryEffects();
1024 return MemoryEffects::unknown();
1025 }
1026
getAsString(bool InAttrGrp) const1027 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1028 std::string Str;
1029 for (iterator I = begin(), E = end(); I != E; ++I) {
1030 if (I != begin())
1031 Str += ' ';
1032 Str += I->getAsString(InAttrGrp);
1033 }
1034 return Str;
1035 }
1036
1037 //===----------------------------------------------------------------------===//
1038 // AttributeListImpl Definition
1039 //===----------------------------------------------------------------------===//
1040
1041 /// Map from AttributeList index to the internal array index. Adding one happens
1042 /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)1043 static unsigned attrIdxToArrayIdx(unsigned Index) {
1044 return Index + 1;
1045 }
1046
AttributeListImpl(ArrayRef<AttributeSet> Sets)1047 AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
1048 : NumAttrSets(Sets.size()) {
1049 assert(!Sets.empty() && "pointless AttributeListImpl");
1050
1051 // There's memory after the node where we can store the entries in.
1052 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1053
1054 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1055 // summary bitsets.
1056 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1057 if (!I.isStringAttribute())
1058 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1059
1060 for (const auto &Set : Sets)
1061 for (const auto &I : Set)
1062 if (!I.isStringAttribute())
1063 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1064 }
1065
Profile(FoldingSetNodeID & ID) const1066 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
1067 Profile(ID, ArrayRef(begin(), end()));
1068 }
1069
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)1070 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
1071 ArrayRef<AttributeSet> Sets) {
1072 for (const auto &Set : Sets)
1073 ID.AddPointer(Set.SetNode);
1074 }
1075
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const1076 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
1077 unsigned *Index) const {
1078 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1079 return false;
1080
1081 if (Index) {
1082 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1083 if (begin()[I].hasAttribute(Kind)) {
1084 *Index = I - 1;
1085 break;
1086 }
1087 }
1088 }
1089
1090 return true;
1091 }
1092
1093
1094 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1095 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1096 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1097 }
1098 #endif
1099
1100 //===----------------------------------------------------------------------===//
1101 // AttributeList Construction and Mutation Methods
1102 //===----------------------------------------------------------------------===//
1103
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)1104 AttributeList AttributeList::getImpl(LLVMContext &C,
1105 ArrayRef<AttributeSet> AttrSets) {
1106 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1107
1108 LLVMContextImpl *pImpl = C.pImpl;
1109 FoldingSetNodeID ID;
1110 AttributeListImpl::Profile(ID, AttrSets);
1111
1112 void *InsertPoint;
1113 AttributeListImpl *PA =
1114 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1115
1116 // If we didn't find any existing attributes of the same shape then
1117 // create a new one and insert it.
1118 if (!PA) {
1119 // Coallocate entries after the AttributeListImpl itself.
1120 void *Mem = pImpl->Alloc.Allocate(
1121 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1122 alignof(AttributeListImpl));
1123 PA = new (Mem) AttributeListImpl(AttrSets);
1124 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1125 }
1126
1127 // Return the AttributesList that we found or created.
1128 return AttributeList(PA);
1129 }
1130
1131 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)1132 AttributeList::get(LLVMContext &C,
1133 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1134 // If there are no attributes then return a null AttributesList pointer.
1135 if (Attrs.empty())
1136 return {};
1137
1138 assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1139 "Misordered Attributes list!");
1140 assert(llvm::all_of(Attrs,
1141 [](const std::pair<unsigned, Attribute> &Pair) {
1142 return Pair.second.isValid();
1143 }) &&
1144 "Pointless attribute!");
1145
1146 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1147 // list.
1148 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1149 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1150 E = Attrs.end(); I != E; ) {
1151 unsigned Index = I->first;
1152 SmallVector<Attribute, 4> AttrVec;
1153 while (I != E && I->first == Index) {
1154 AttrVec.push_back(I->second);
1155 ++I;
1156 }
1157
1158 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1159 }
1160
1161 return get(C, AttrPairVec);
1162 }
1163
1164 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1165 AttributeList::get(LLVMContext &C,
1166 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1167 // If there are no attributes then return a null AttributesList pointer.
1168 if (Attrs.empty())
1169 return {};
1170
1171 assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1172 "Misordered Attributes list!");
1173 assert(llvm::none_of(Attrs,
1174 [](const std::pair<unsigned, AttributeSet> &Pair) {
1175 return !Pair.second.hasAttributes();
1176 }) &&
1177 "Pointless attribute!");
1178
1179 unsigned MaxIndex = Attrs.back().first;
1180 // If the MaxIndex is FunctionIndex and there are other indices in front
1181 // of it, we need to use the largest of those to get the right size.
1182 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1183 MaxIndex = Attrs[Attrs.size() - 2].first;
1184
1185 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1186 for (const auto &Pair : Attrs)
1187 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1188
1189 return getImpl(C, AttrVec);
1190 }
1191
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)1192 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1193 AttributeSet RetAttrs,
1194 ArrayRef<AttributeSet> ArgAttrs) {
1195 // Scan from the end to find the last argument with attributes. Most
1196 // arguments don't have attributes, so it's nice if we can have fewer unique
1197 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1198 unsigned NumSets = 0;
1199 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1200 if (ArgAttrs[I - 1].hasAttributes()) {
1201 NumSets = I + 2;
1202 break;
1203 }
1204 }
1205 if (NumSets == 0) {
1206 // Check function and return attributes if we didn't have argument
1207 // attributes.
1208 if (RetAttrs.hasAttributes())
1209 NumSets = 2;
1210 else if (FnAttrs.hasAttributes())
1211 NumSets = 1;
1212 }
1213
1214 // If all attribute sets were empty, we can use the empty attribute list.
1215 if (NumSets == 0)
1216 return {};
1217
1218 SmallVector<AttributeSet, 8> AttrSets;
1219 AttrSets.reserve(NumSets);
1220 // If we have any attributes, we always have function attributes.
1221 AttrSets.push_back(FnAttrs);
1222 if (NumSets > 1)
1223 AttrSets.push_back(RetAttrs);
1224 if (NumSets > 2) {
1225 // Drop the empty argument attribute sets at the end.
1226 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1227 llvm::append_range(AttrSets, ArgAttrs);
1228 }
1229
1230 return getImpl(C, AttrSets);
1231 }
1232
get(LLVMContext & C,unsigned Index,AttributeSet Attrs)1233 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1234 AttributeSet Attrs) {
1235 if (!Attrs.hasAttributes())
1236 return {};
1237 Index = attrIdxToArrayIdx(Index);
1238 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1239 AttrSets[Index] = Attrs;
1240 return getImpl(C, AttrSets);
1241 }
1242
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1243 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1244 const AttrBuilder &B) {
1245 return get(C, Index, AttributeSet::get(C, B));
1246 }
1247
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1248 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1249 ArrayRef<Attribute::AttrKind> Kinds) {
1250 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1251 for (const auto K : Kinds)
1252 Attrs.emplace_back(Index, Attribute::get(C, K));
1253 return get(C, Attrs);
1254 }
1255
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)1256 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1257 ArrayRef<Attribute::AttrKind> Kinds,
1258 ArrayRef<uint64_t> Values) {
1259 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1260 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1261 auto VI = Values.begin();
1262 for (const auto K : Kinds)
1263 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1264 return get(C, Attrs);
1265 }
1266
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1267 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1268 ArrayRef<StringRef> Kinds) {
1269 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1270 for (const auto &K : Kinds)
1271 Attrs.emplace_back(Index, Attribute::get(C, K));
1272 return get(C, Attrs);
1273 }
1274
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1275 AttributeList AttributeList::get(LLVMContext &C,
1276 ArrayRef<AttributeList> Attrs) {
1277 if (Attrs.empty())
1278 return {};
1279 if (Attrs.size() == 1)
1280 return Attrs[0];
1281
1282 unsigned MaxSize = 0;
1283 for (const auto &List : Attrs)
1284 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1285
1286 // If every list was empty, there is no point in merging the lists.
1287 if (MaxSize == 0)
1288 return {};
1289
1290 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1291 for (unsigned I = 0; I < MaxSize; ++I) {
1292 AttrBuilder CurBuilder(C);
1293 for (const auto &List : Attrs)
1294 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1295 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1296 }
1297
1298 return getImpl(C, NewAttrSets);
1299 }
1300
1301 AttributeList
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1302 AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1303 Attribute::AttrKind Kind) const {
1304 AttributeSet Attrs = getAttributes(Index);
1305 if (Attrs.hasAttribute(Kind))
1306 return *this;
1307 // TODO: Insert at correct position and avoid sort.
1308 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1309 NewAttrs.push_back(Attribute::get(C, Kind));
1310 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1311 }
1312
addAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1313 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1314 StringRef Kind,
1315 StringRef Value) const {
1316 AttrBuilder B(C);
1317 B.addAttribute(Kind, Value);
1318 return addAttributesAtIndex(C, Index, B);
1319 }
1320
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute A) const1321 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1322 Attribute A) const {
1323 AttrBuilder B(C);
1324 B.addAttribute(A);
1325 return addAttributesAtIndex(C, Index, B);
1326 }
1327
setAttributesAtIndex(LLVMContext & C,unsigned Index,AttributeSet Attrs) const1328 AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1329 unsigned Index,
1330 AttributeSet Attrs) const {
1331 Index = attrIdxToArrayIdx(Index);
1332 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1333 if (Index >= AttrSets.size())
1334 AttrSets.resize(Index + 1);
1335 AttrSets[Index] = Attrs;
1336
1337 // Remove trailing empty attribute sets.
1338 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1339 AttrSets.pop_back();
1340 if (AttrSets.empty())
1341 return {};
1342 return AttributeList::getImpl(C, AttrSets);
1343 }
1344
addAttributesAtIndex(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1345 AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1346 unsigned Index,
1347 const AttrBuilder &B) const {
1348 if (!B.hasAttributes())
1349 return *this;
1350
1351 if (!pImpl)
1352 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1353
1354 AttrBuilder Merged(C, getAttributes(Index));
1355 Merged.merge(B);
1356 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1357 }
1358
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const1359 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1360 ArrayRef<unsigned> ArgNos,
1361 Attribute A) const {
1362 assert(llvm::is_sorted(ArgNos));
1363
1364 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1365 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1366 if (MaxIndex >= AttrSets.size())
1367 AttrSets.resize(MaxIndex + 1);
1368
1369 for (unsigned ArgNo : ArgNos) {
1370 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1371 AttrBuilder B(C, AttrSets[Index]);
1372 B.addAttribute(A);
1373 AttrSets[Index] = AttributeSet::get(C, B);
1374 }
1375
1376 return getImpl(C, AttrSets);
1377 }
1378
1379 AttributeList
removeAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1380 AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1381 Attribute::AttrKind Kind) const {
1382 AttributeSet Attrs = getAttributes(Index);
1383 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1384 if (Attrs == NewAttrs)
1385 return *this;
1386 return setAttributesAtIndex(C, Index, NewAttrs);
1387 }
1388
removeAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind) const1389 AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1390 unsigned Index,
1391 StringRef Kind) const {
1392 AttributeSet Attrs = getAttributes(Index);
1393 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1394 if (Attrs == NewAttrs)
1395 return *this;
1396 return setAttributesAtIndex(C, Index, NewAttrs);
1397 }
1398
removeAttributesAtIndex(LLVMContext & C,unsigned Index,const AttributeMask & AttrsToRemove) const1399 AttributeList AttributeList::removeAttributesAtIndex(
1400 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1401 AttributeSet Attrs = getAttributes(Index);
1402 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1403 // If nothing was removed, return the original list.
1404 if (Attrs == NewAttrs)
1405 return *this;
1406 return setAttributesAtIndex(C, Index, NewAttrs);
1407 }
1408
1409 AttributeList
removeAttributesAtIndex(LLVMContext & C,unsigned WithoutIndex) const1410 AttributeList::removeAttributesAtIndex(LLVMContext &C,
1411 unsigned WithoutIndex) const {
1412 if (!pImpl)
1413 return {};
1414 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1415 return *this;
1416 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1417 }
1418
addDereferenceableRetAttr(LLVMContext & C,uint64_t Bytes) const1419 AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1420 uint64_t Bytes) const {
1421 AttrBuilder B(C);
1422 B.addDereferenceableAttr(Bytes);
1423 return addRetAttributes(C, B);
1424 }
1425
addDereferenceableParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1426 AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1427 unsigned Index,
1428 uint64_t Bytes) const {
1429 AttrBuilder B(C);
1430 B.addDereferenceableAttr(Bytes);
1431 return addParamAttributes(C, Index, B);
1432 }
1433
1434 AttributeList
addDereferenceableOrNullParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1435 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1436 uint64_t Bytes) const {
1437 AttrBuilder B(C);
1438 B.addDereferenceableOrNullAttr(Bytes);
1439 return addParamAttributes(C, Index, B);
1440 }
1441
addAllocSizeParamAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)1442 AttributeList AttributeList::addAllocSizeParamAttr(
1443 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1444 const std::optional<unsigned> &NumElemsArg) {
1445 AttrBuilder B(C);
1446 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1447 return addParamAttributes(C, Index, B);
1448 }
1449
1450 //===----------------------------------------------------------------------===//
1451 // AttributeList Accessor Methods
1452 //===----------------------------------------------------------------------===//
1453
getParamAttrs(unsigned ArgNo) const1454 AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1455 return getAttributes(ArgNo + FirstArgIndex);
1456 }
1457
getRetAttrs() const1458 AttributeSet AttributeList::getRetAttrs() const {
1459 return getAttributes(ReturnIndex);
1460 }
1461
getFnAttrs() const1462 AttributeSet AttributeList::getFnAttrs() const {
1463 return getAttributes(FunctionIndex);
1464 }
1465
hasAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1466 bool AttributeList::hasAttributeAtIndex(unsigned Index,
1467 Attribute::AttrKind Kind) const {
1468 return getAttributes(Index).hasAttribute(Kind);
1469 }
1470
hasAttributeAtIndex(unsigned Index,StringRef Kind) const1471 bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1472 return getAttributes(Index).hasAttribute(Kind);
1473 }
1474
hasAttributesAtIndex(unsigned Index) const1475 bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1476 return getAttributes(Index).hasAttributes();
1477 }
1478
hasFnAttr(Attribute::AttrKind Kind) const1479 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1480 return pImpl && pImpl->hasFnAttribute(Kind);
1481 }
1482
hasFnAttr(StringRef Kind) const1483 bool AttributeList::hasFnAttr(StringRef Kind) const {
1484 return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1485 }
1486
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1487 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1488 unsigned *Index) const {
1489 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1490 }
1491
getAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1492 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1493 Attribute::AttrKind Kind) const {
1494 return getAttributes(Index).getAttribute(Kind);
1495 }
1496
getAttributeAtIndex(unsigned Index,StringRef Kind) const1497 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1498 StringRef Kind) const {
1499 return getAttributes(Index).getAttribute(Kind);
1500 }
1501
getRetAlignment() const1502 MaybeAlign AttributeList::getRetAlignment() const {
1503 return getAttributes(ReturnIndex).getAlignment();
1504 }
1505
getParamAlignment(unsigned ArgNo) const1506 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1507 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1508 }
1509
getParamStackAlignment(unsigned ArgNo) const1510 MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1511 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1512 }
1513
getParamByValType(unsigned Index) const1514 Type *AttributeList::getParamByValType(unsigned Index) const {
1515 return getAttributes(Index+FirstArgIndex).getByValType();
1516 }
1517
getParamStructRetType(unsigned Index) const1518 Type *AttributeList::getParamStructRetType(unsigned Index) const {
1519 return getAttributes(Index + FirstArgIndex).getStructRetType();
1520 }
1521
getParamByRefType(unsigned Index) const1522 Type *AttributeList::getParamByRefType(unsigned Index) const {
1523 return getAttributes(Index + FirstArgIndex).getByRefType();
1524 }
1525
getParamPreallocatedType(unsigned Index) const1526 Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1527 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1528 }
1529
getParamInAllocaType(unsigned Index) const1530 Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1531 return getAttributes(Index + FirstArgIndex).getInAllocaType();
1532 }
1533
getParamElementType(unsigned Index) const1534 Type *AttributeList::getParamElementType(unsigned Index) const {
1535 return getAttributes(Index + FirstArgIndex).getElementType();
1536 }
1537
getFnStackAlignment() const1538 MaybeAlign AttributeList::getFnStackAlignment() const {
1539 return getFnAttrs().getStackAlignment();
1540 }
1541
getRetStackAlignment() const1542 MaybeAlign AttributeList::getRetStackAlignment() const {
1543 return getRetAttrs().getStackAlignment();
1544 }
1545
getRetDereferenceableBytes() const1546 uint64_t AttributeList::getRetDereferenceableBytes() const {
1547 return getRetAttrs().getDereferenceableBytes();
1548 }
1549
getParamDereferenceableBytes(unsigned Index) const1550 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1551 return getParamAttrs(Index).getDereferenceableBytes();
1552 }
1553
getRetDereferenceableOrNullBytes() const1554 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1555 return getRetAttrs().getDereferenceableOrNullBytes();
1556 }
1557
1558 uint64_t
getParamDereferenceableOrNullBytes(unsigned Index) const1559 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1560 return getParamAttrs(Index).getDereferenceableOrNullBytes();
1561 }
1562
getUWTableKind() const1563 UWTableKind AttributeList::getUWTableKind() const {
1564 return getFnAttrs().getUWTableKind();
1565 }
1566
getAllocKind() const1567 AllocFnKind AttributeList::getAllocKind() const {
1568 return getFnAttrs().getAllocKind();
1569 }
1570
getMemoryEffects() const1571 MemoryEffects AttributeList::getMemoryEffects() const {
1572 return getFnAttrs().getMemoryEffects();
1573 }
1574
getAsString(unsigned Index,bool InAttrGrp) const1575 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1576 return getAttributes(Index).getAsString(InAttrGrp);
1577 }
1578
getAttributes(unsigned Index) const1579 AttributeSet AttributeList::getAttributes(unsigned Index) const {
1580 Index = attrIdxToArrayIdx(Index);
1581 if (!pImpl || Index >= getNumAttrSets())
1582 return {};
1583 return pImpl->begin()[Index];
1584 }
1585
hasParentContext(LLVMContext & C) const1586 bool AttributeList::hasParentContext(LLVMContext &C) const {
1587 assert(!isEmpty() && "an empty attribute list has no parent context");
1588 FoldingSetNodeID ID;
1589 pImpl->Profile(ID);
1590 void *Unused;
1591 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1592 }
1593
begin() const1594 AttributeList::iterator AttributeList::begin() const {
1595 return pImpl ? pImpl->begin() : nullptr;
1596 }
1597
end() const1598 AttributeList::iterator AttributeList::end() const {
1599 return pImpl ? pImpl->end() : nullptr;
1600 }
1601
1602 //===----------------------------------------------------------------------===//
1603 // AttributeList Introspection Methods
1604 //===----------------------------------------------------------------------===//
1605
getNumAttrSets() const1606 unsigned AttributeList::getNumAttrSets() const {
1607 return pImpl ? pImpl->NumAttrSets : 0;
1608 }
1609
print(raw_ostream & O) const1610 void AttributeList::print(raw_ostream &O) const {
1611 O << "AttributeList[\n";
1612
1613 for (unsigned i : indexes()) {
1614 if (!getAttributes(i).hasAttributes())
1615 continue;
1616 O << " { ";
1617 switch (i) {
1618 case AttrIndex::ReturnIndex:
1619 O << "return";
1620 break;
1621 case AttrIndex::FunctionIndex:
1622 O << "function";
1623 break;
1624 default:
1625 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1626 }
1627 O << " => " << getAsString(i) << " }\n";
1628 }
1629
1630 O << "]\n";
1631 }
1632
1633 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1634 LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
1635 #endif
1636
1637 //===----------------------------------------------------------------------===//
1638 // AttrBuilder Method Implementations
1639 //===----------------------------------------------------------------------===//
1640
AttrBuilder(LLVMContext & Ctx,AttributeSet AS)1641 AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
1642 append_range(Attrs, AS);
1643 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
1644 }
1645
clear()1646 void AttrBuilder::clear() { Attrs.clear(); }
1647
1648 /// Attribute comparator that only compares attribute keys. Enum attributes are
1649 /// sorted before string attributes.
1650 struct AttributeComparator {
operator ()AttributeComparator1651 bool operator()(Attribute A0, Attribute A1) const {
1652 bool A0IsString = A0.isStringAttribute();
1653 bool A1IsString = A1.isStringAttribute();
1654 if (A0IsString) {
1655 if (A1IsString)
1656 return A0.getKindAsString() < A1.getKindAsString();
1657 else
1658 return false;
1659 }
1660 if (A1IsString)
1661 return true;
1662 return A0.getKindAsEnum() < A1.getKindAsEnum();
1663 }
operator ()AttributeComparator1664 bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
1665 if (A0.isStringAttribute())
1666 return false;
1667 return A0.getKindAsEnum() < Kind;
1668 }
operator ()AttributeComparator1669 bool operator()(Attribute A0, StringRef Kind) const {
1670 if (A0.isStringAttribute())
1671 return A0.getKindAsString() < Kind;
1672 return true;
1673 }
1674 };
1675
1676 template <typename K>
addAttributeImpl(SmallVectorImpl<Attribute> & Attrs,K Kind,Attribute Attr)1677 static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
1678 Attribute Attr) {
1679 auto It = lower_bound(Attrs, Kind, AttributeComparator());
1680 if (It != Attrs.end() && It->hasAttribute(Kind))
1681 std::swap(*It, Attr);
1682 else
1683 Attrs.insert(It, Attr);
1684 }
1685
addAttribute(Attribute Attr)1686 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1687 if (Attr.isStringAttribute())
1688 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1689 else
1690 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
1691 return *this;
1692 }
1693
addAttribute(Attribute::AttrKind Kind)1694 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
1695 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
1696 return *this;
1697 }
1698
addAttribute(StringRef A,StringRef V)1699 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1700 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
1701 return *this;
1702 }
1703
removeAttribute(Attribute::AttrKind Val)1704 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1705 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1706 auto It = lower_bound(Attrs, Val, AttributeComparator());
1707 if (It != Attrs.end() && It->hasAttribute(Val))
1708 Attrs.erase(It);
1709 return *this;
1710 }
1711
removeAttribute(StringRef A)1712 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1713 auto It = lower_bound(Attrs, A, AttributeComparator());
1714 if (It != Attrs.end() && It->hasAttribute(A))
1715 Attrs.erase(It);
1716 return *this;
1717 }
1718
1719 std::optional<uint64_t>
getRawIntAttr(Attribute::AttrKind Kind) const1720 AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
1721 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
1722 Attribute A = getAttribute(Kind);
1723 if (A.isValid())
1724 return A.getValueAsInt();
1725 return std::nullopt;
1726 }
1727
addRawIntAttr(Attribute::AttrKind Kind,uint64_t Value)1728 AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
1729 uint64_t Value) {
1730 return addAttribute(Attribute::get(Ctx, Kind, Value));
1731 }
1732
1733 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1734 AttrBuilder::getAllocSizeArgs() const {
1735 Attribute A = getAttribute(Attribute::AllocSize);
1736 if (A.isValid())
1737 return A.getAllocSizeArgs();
1738 return std::nullopt;
1739 }
1740
addAlignmentAttr(MaybeAlign Align)1741 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1742 if (!Align)
1743 return *this;
1744
1745 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1746 return addRawIntAttr(Attribute::Alignment, Align->value());
1747 }
1748
addStackAlignmentAttr(MaybeAlign Align)1749 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1750 // Default alignment, allow the target to define how to align it.
1751 if (!Align)
1752 return *this;
1753
1754 assert(*Align <= 0x100 && "Alignment too large.");
1755 return addRawIntAttr(Attribute::StackAlignment, Align->value());
1756 }
1757
addDereferenceableAttr(uint64_t Bytes)1758 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1759 if (Bytes == 0) return *this;
1760
1761 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
1762 }
1763
addDereferenceableOrNullAttr(uint64_t Bytes)1764 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1765 if (Bytes == 0)
1766 return *this;
1767
1768 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
1769 }
1770
1771 AttrBuilder &
addAllocSizeAttr(unsigned ElemSize,const std::optional<unsigned> & NumElems)1772 AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1773 const std::optional<unsigned> &NumElems) {
1774 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1775 }
1776
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1777 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1778 // (0, 0) is our "not present" value, so we need to check for it here.
1779 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1780 return addRawIntAttr(Attribute::AllocSize, RawArgs);
1781 }
1782
addVScaleRangeAttr(unsigned MinValue,std::optional<unsigned> MaxValue)1783 AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
1784 std::optional<unsigned> MaxValue) {
1785 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
1786 }
1787
addVScaleRangeAttrFromRawRepr(uint64_t RawArgs)1788 AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
1789 // (0, 0) is not present hence ignore this case
1790 if (RawArgs == 0)
1791 return *this;
1792
1793 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1794 }
1795
addUWTableAttr(UWTableKind Kind)1796 AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
1797 if (Kind == UWTableKind::None)
1798 return *this;
1799 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
1800 }
1801
addMemoryAttr(MemoryEffects ME)1802 AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
1803 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
1804 }
1805
addAllocKindAttr(AllocFnKind Kind)1806 AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
1807 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
1808 }
1809
getTypeAttr(Attribute::AttrKind Kind) const1810 Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
1811 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
1812 Attribute A = getAttribute(Kind);
1813 return A.isValid() ? A.getValueAsType() : nullptr;
1814 }
1815
addTypeAttr(Attribute::AttrKind Kind,Type * Ty)1816 AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
1817 return addAttribute(Attribute::get(Ctx, Kind, Ty));
1818 }
1819
addByValAttr(Type * Ty)1820 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
1821 return addTypeAttr(Attribute::ByVal, Ty);
1822 }
1823
addStructRetAttr(Type * Ty)1824 AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
1825 return addTypeAttr(Attribute::StructRet, Ty);
1826 }
1827
addByRefAttr(Type * Ty)1828 AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
1829 return addTypeAttr(Attribute::ByRef, Ty);
1830 }
1831
addPreallocatedAttr(Type * Ty)1832 AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
1833 return addTypeAttr(Attribute::Preallocated, Ty);
1834 }
1835
addInAllocaAttr(Type * Ty)1836 AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
1837 return addTypeAttr(Attribute::InAlloca, Ty);
1838 }
1839
merge(const AttrBuilder & B)1840 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1841 // TODO: Could make this O(n) as we're merging two sorted lists.
1842 for (const auto &I : B.attrs())
1843 addAttribute(I);
1844
1845 return *this;
1846 }
1847
remove(const AttributeMask & AM)1848 AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
1849 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
1850 return *this;
1851 }
1852
overlaps(const AttributeMask & AM) const1853 bool AttrBuilder::overlaps(const AttributeMask &AM) const {
1854 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
1855 }
1856
getAttribute(Attribute::AttrKind A) const1857 Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
1858 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
1859 auto It = lower_bound(Attrs, A, AttributeComparator());
1860 if (It != Attrs.end() && It->hasAttribute(A))
1861 return *It;
1862 return {};
1863 }
1864
getAttribute(StringRef A) const1865 Attribute AttrBuilder::getAttribute(StringRef A) const {
1866 auto It = lower_bound(Attrs, A, AttributeComparator());
1867 if (It != Attrs.end() && It->hasAttribute(A))
1868 return *It;
1869 return {};
1870 }
1871
contains(Attribute::AttrKind A) const1872 bool AttrBuilder::contains(Attribute::AttrKind A) const {
1873 return getAttribute(A).isValid();
1874 }
1875
contains(StringRef A) const1876 bool AttrBuilder::contains(StringRef A) const {
1877 return getAttribute(A).isValid();
1878 }
1879
operator ==(const AttrBuilder & B) const1880 bool AttrBuilder::operator==(const AttrBuilder &B) const {
1881 return Attrs == B.Attrs;
1882 }
1883
1884 //===----------------------------------------------------------------------===//
1885 // AttributeFuncs Function Defintions
1886 //===----------------------------------------------------------------------===//
1887
1888 /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty,AttributeSafetyKind ASK)1889 AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
1890 AttributeSafetyKind ASK) {
1891 AttributeMask Incompatible;
1892
1893 if (!Ty->isIntegerTy()) {
1894 // Attributes that only apply to integers.
1895 if (ASK & ASK_SAFE_TO_DROP)
1896 Incompatible.addAttribute(Attribute::AllocAlign);
1897 if (ASK & ASK_UNSAFE_TO_DROP)
1898 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
1899 }
1900
1901 if (!Ty->isPointerTy()) {
1902 // Attributes that only apply to pointers.
1903 if (ASK & ASK_SAFE_TO_DROP)
1904 Incompatible.addAttribute(Attribute::NoAlias)
1905 .addAttribute(Attribute::NoCapture)
1906 .addAttribute(Attribute::NonNull)
1907 .addAttribute(Attribute::ReadNone)
1908 .addAttribute(Attribute::ReadOnly)
1909 .addAttribute(Attribute::Dereferenceable)
1910 .addAttribute(Attribute::DereferenceableOrNull);
1911 if (ASK & ASK_UNSAFE_TO_DROP)
1912 Incompatible.addAttribute(Attribute::Nest)
1913 .addAttribute(Attribute::SwiftError)
1914 .addAttribute(Attribute::Preallocated)
1915 .addAttribute(Attribute::InAlloca)
1916 .addAttribute(Attribute::ByVal)
1917 .addAttribute(Attribute::StructRet)
1918 .addAttribute(Attribute::ByRef)
1919 .addAttribute(Attribute::ElementType)
1920 .addAttribute(Attribute::AllocatedPointer);
1921 }
1922
1923 // Attributes that only apply to pointers or vectors of pointers.
1924 if (!Ty->isPtrOrPtrVectorTy()) {
1925 if (ASK & ASK_SAFE_TO_DROP)
1926 Incompatible.addAttribute(Attribute::Alignment);
1927 }
1928
1929 // Some attributes can apply to all "values" but there are no `void` values.
1930 if (Ty->isVoidTy()) {
1931 if (ASK & ASK_SAFE_TO_DROP)
1932 Incompatible.addAttribute(Attribute::NoUndef);
1933 }
1934
1935 return Incompatible;
1936 }
1937
getUBImplyingAttributes()1938 AttributeMask AttributeFuncs::getUBImplyingAttributes() {
1939 AttributeMask AM;
1940 AM.addAttribute(Attribute::NoUndef);
1941 AM.addAttribute(Attribute::Dereferenceable);
1942 AM.addAttribute(Attribute::DereferenceableOrNull);
1943 return AM;
1944 }
1945
1946 template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)1947 static bool isEqual(const Function &Caller, const Function &Callee) {
1948 return Caller.getFnAttribute(AttrClass::getKind()) ==
1949 Callee.getFnAttribute(AttrClass::getKind());
1950 }
1951
1952 /// Compute the logical AND of the attributes of the caller and the
1953 /// callee.
1954 ///
1955 /// This function sets the caller's attribute to false if the callee's attribute
1956 /// is false.
1957 template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)1958 static void setAND(Function &Caller, const Function &Callee) {
1959 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
1960 !AttrClass::isSet(Callee, AttrClass::getKind()))
1961 AttrClass::set(Caller, AttrClass::getKind(), false);
1962 }
1963
1964 /// Compute the logical OR of the attributes of the caller and the
1965 /// callee.
1966 ///
1967 /// This function sets the caller's attribute to true if the callee's attribute
1968 /// is true.
1969 template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)1970 static void setOR(Function &Caller, const Function &Callee) {
1971 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
1972 AttrClass::isSet(Callee, AttrClass::getKind()))
1973 AttrClass::set(Caller, AttrClass::getKind(), true);
1974 }
1975
1976 /// If the inlined function had a higher stack protection level than the
1977 /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)1978 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1979 // If the calling function has *no* stack protection level (e.g. it was built
1980 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
1981 // change it as that could change the program's semantics.
1982 if (!Caller.hasStackProtectorFnAttr())
1983 return;
1984
1985 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1986 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1987 // clutter to the IR.
1988 AttributeMask OldSSPAttr;
1989 OldSSPAttr.addAttribute(Attribute::StackProtect)
1990 .addAttribute(Attribute::StackProtectStrong)
1991 .addAttribute(Attribute::StackProtectReq);
1992
1993 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1994 Caller.removeFnAttrs(OldSSPAttr);
1995 Caller.addFnAttr(Attribute::StackProtectReq);
1996 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
1997 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1998 Caller.removeFnAttrs(OldSSPAttr);
1999 Caller.addFnAttr(Attribute::StackProtectStrong);
2000 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2001 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2002 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2003 Caller.addFnAttr(Attribute::StackProtect);
2004 }
2005
2006 /// If the inlined function required stack probes, then ensure that
2007 /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)2008 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2009 if (!Caller.hasFnAttribute("probe-stack") &&
2010 Callee.hasFnAttribute("probe-stack")) {
2011 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2012 }
2013 }
2014
2015 /// If the inlined function defines the size of guard region
2016 /// on the stack, then ensure that the calling function defines a guard region
2017 /// that is no larger.
2018 static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)2019 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
2020 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2021 if (CalleeAttr.isValid()) {
2022 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2023 if (CallerAttr.isValid()) {
2024 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2025 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2026 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2027
2028 if (CallerStackProbeSize > CalleeStackProbeSize) {
2029 Caller.addFnAttr(CalleeAttr);
2030 }
2031 } else {
2032 Caller.addFnAttr(CalleeAttr);
2033 }
2034 }
2035 }
2036
2037 /// If the inlined function defines a min legal vector width, then ensure
2038 /// the calling function has the same or larger min legal vector width. If the
2039 /// caller has the attribute, but the callee doesn't, we need to remove the
2040 /// attribute from the caller since we can't make any guarantees about the
2041 /// caller's requirements.
2042 /// This function is called after the inlining decision has been made so we have
2043 /// to merge the attribute this way. Heuristics that would use
2044 /// min-legal-vector-width to determine inline compatibility would need to be
2045 /// handled as part of inline cost analysis.
2046 static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)2047 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
2048 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2049 if (CallerAttr.isValid()) {
2050 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2051 if (CalleeAttr.isValid()) {
2052 uint64_t CallerVectorWidth, CalleeVectorWidth;
2053 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2054 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2055 if (CallerVectorWidth < CalleeVectorWidth)
2056 Caller.addFnAttr(CalleeAttr);
2057 } else {
2058 // If the callee doesn't have the attribute then we don't know anything
2059 // and must drop the attribute from the caller.
2060 Caller.removeFnAttr("min-legal-vector-width");
2061 }
2062 }
2063 }
2064
2065 /// If the inlined function has null_pointer_is_valid attribute,
2066 /// set this attribute in the caller post inlining.
2067 static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)2068 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2069 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2070 Caller.addFnAttr(Attribute::NullPointerIsValid);
2071 }
2072 }
2073
2074 struct EnumAttr {
isSetEnumAttr2075 static bool isSet(const Function &Fn,
2076 Attribute::AttrKind Kind) {
2077 return Fn.hasFnAttribute(Kind);
2078 }
2079
setEnumAttr2080 static void set(Function &Fn,
2081 Attribute::AttrKind Kind, bool Val) {
2082 if (Val)
2083 Fn.addFnAttr(Kind);
2084 else
2085 Fn.removeFnAttr(Kind);
2086 }
2087 };
2088
2089 struct StrBoolAttr {
isSetStrBoolAttr2090 static bool isSet(const Function &Fn,
2091 StringRef Kind) {
2092 auto A = Fn.getFnAttribute(Kind);
2093 return A.getValueAsString().equals("true");
2094 }
2095
setStrBoolAttr2096 static void set(Function &Fn,
2097 StringRef Kind, bool Val) {
2098 Fn.addFnAttr(Kind, Val ? "true" : "false");
2099 }
2100 };
2101
2102 #define GET_ATTR_NAMES
2103 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2104 struct ENUM_NAME##Attr : EnumAttr { \
2105 static enum Attribute::AttrKind getKind() { \
2106 return llvm::Attribute::ENUM_NAME; \
2107 } \
2108 };
2109 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2110 struct ENUM_NAME##Attr : StrBoolAttr { \
2111 static StringRef getKind() { return #DISPLAY_NAME; } \
2112 };
2113 #include "llvm/IR/Attributes.inc"
2114
2115 #define GET_ATTR_COMPAT_FUNC
2116 #include "llvm/IR/Attributes.inc"
2117
areInlineCompatible(const Function & Caller,const Function & Callee)2118 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2119 const Function &Callee) {
2120 return hasCompatibleFnAttrs(Caller, Callee);
2121 }
2122
areOutlineCompatible(const Function & A,const Function & B)2123 bool AttributeFuncs::areOutlineCompatible(const Function &A,
2124 const Function &B) {
2125 return hasCompatibleFnAttrs(A, B);
2126 }
2127
mergeAttributesForInlining(Function & Caller,const Function & Callee)2128 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2129 const Function &Callee) {
2130 mergeFnAttrs(Caller, Callee);
2131 }
2132
mergeAttributesForOutlining(Function & Base,const Function & ToMerge)2133 void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2134 const Function &ToMerge) {
2135
2136 // We merge functions so that they meet the most general case.
2137 // For example, if the NoNansFPMathAttr is set in one function, but not in
2138 // the other, in the merged function we can say that the NoNansFPMathAttr
2139 // is not set.
2140 // However if we have the SpeculativeLoadHardeningAttr set true in one
2141 // function, but not the other, we make sure that the function retains
2142 // that aspect in the merged function.
2143 mergeFnAttrs(Base, ToMerge);
2144 }
2145
updateMinLegalVectorWidthAttr(Function & Fn,uint64_t Width)2146 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2147 uint64_t Width) {
2148 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2149 if (Attr.isValid()) {
2150 uint64_t OldWidth;
2151 Attr.getValueAsString().getAsInteger(0, OldWidth);
2152 if (Width > OldWidth)
2153 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2154 }
2155 }
2156