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/AttributeMask.h"
27 #include "llvm/IR/ConstantRange.h"
28 #include "llvm/IR/ConstantRangeList.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/LLVMContext.h"
31 #include "llvm/IR/Type.h"
32 #include "llvm/Support/Compiler.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/ModRef.h"
35 #include "llvm/Support/raw_ostream.h"
36 #include <algorithm>
37 #include <cassert>
38 #include <cstddef>
39 #include <cstdint>
40 #include <limits>
41 #include <optional>
42 #include <string>
43 #include <tuple>
44 #include <utility>
45
46 using namespace llvm;
47
48 //===----------------------------------------------------------------------===//
49 // Attribute Construction Methods
50 //===----------------------------------------------------------------------===//
51
52 // allocsize has two integer arguments, but because they're both 32 bits, we can
53 // pack them into one 64-bit value, at the cost of making said value
54 // nonsensical.
55 //
56 // In order to do this, we need to reserve one value of the second (optional)
57 // allocsize argument to signify "not present."
58 static const unsigned AllocSizeNumElemsNotPresent = -1;
59
packAllocSizeArgs(unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)60 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
61 const std::optional<unsigned> &NumElemsArg) {
62 assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
63 "Attempting to pack a reserved value");
64
65 return uint64_t(ElemSizeArg) << 32 |
66 NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
67 }
68
69 static std::pair<unsigned, std::optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)70 unpackAllocSizeArgs(uint64_t Num) {
71 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
72 unsigned ElemSizeArg = Num >> 32;
73
74 std::optional<unsigned> NumElemsArg;
75 if (NumElems != AllocSizeNumElemsNotPresent)
76 NumElemsArg = NumElems;
77 return std::make_pair(ElemSizeArg, NumElemsArg);
78 }
79
packVScaleRangeArgs(unsigned MinValue,std::optional<unsigned> MaxValue)80 static uint64_t packVScaleRangeArgs(unsigned MinValue,
81 std::optional<unsigned> MaxValue) {
82 return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
83 }
84
85 static std::pair<unsigned, std::optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value)86 unpackVScaleRangeArgs(uint64_t Value) {
87 unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
88 unsigned MinValue = Value >> 32;
89
90 return std::make_pair(MinValue,
91 MaxValue > 0 ? MaxValue : std::optional<unsigned>());
92 }
93
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)94 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
95 uint64_t Val) {
96 bool IsIntAttr = Attribute::isIntAttrKind(Kind);
97 assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
98 "Not an enum or int attribute");
99
100 LLVMContextImpl *pImpl = Context.pImpl;
101 FoldingSetNodeID ID;
102 ID.AddInteger(Kind);
103 if (IsIntAttr)
104 ID.AddInteger(Val);
105 else
106 assert(Val == 0 && "Value must be zero for enum attributes");
107
108 void *InsertPoint;
109 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
110
111 if (!PA) {
112 // If we didn't find any existing attributes of the same shape then create a
113 // new one and insert it.
114 if (!IsIntAttr)
115 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
116 else
117 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
118 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
119 }
120
121 // Return the Attribute that we found or created.
122 return Attribute(PA);
123 }
124
get(LLVMContext & Context,StringRef Kind,StringRef Val)125 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
126 LLVMContextImpl *pImpl = Context.pImpl;
127 FoldingSetNodeID ID;
128 ID.AddString(Kind);
129 if (!Val.empty()) ID.AddString(Val);
130
131 void *InsertPoint;
132 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
133
134 if (!PA) {
135 // If we didn't find any existing attributes of the same shape then create a
136 // new one and insert it.
137 void *Mem =
138 pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
139 alignof(StringAttributeImpl));
140 PA = new (Mem) StringAttributeImpl(Kind, Val);
141 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
142 }
143
144 // Return the Attribute that we found or created.
145 return Attribute(PA);
146 }
147
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)148 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
149 Type *Ty) {
150 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
151 LLVMContextImpl *pImpl = Context.pImpl;
152 FoldingSetNodeID ID;
153 ID.AddInteger(Kind);
154 ID.AddPointer(Ty);
155
156 void *InsertPoint;
157 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
158
159 if (!PA) {
160 // If we didn't find any existing attributes of the same shape then create a
161 // new one and insert it.
162 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
163 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
164 }
165
166 // Return the Attribute that we found or created.
167 return Attribute(PA);
168 }
169
get(LLVMContext & Context,Attribute::AttrKind Kind,const ConstantRange & CR)170 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
171 const ConstantRange &CR) {
172 assert(Attribute::isConstantRangeAttrKind(Kind) &&
173 "Not a ConstantRange attribute");
174 LLVMContextImpl *pImpl = Context.pImpl;
175 FoldingSetNodeID ID;
176 ID.AddInteger(Kind);
177 CR.getLower().Profile(ID);
178 CR.getUpper().Profile(ID);
179
180 void *InsertPoint;
181 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
182
183 if (!PA) {
184 // If we didn't find any existing attributes of the same shape then create a
185 // new one and insert it.
186 PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
187 ConstantRangeAttributeImpl(Kind, CR);
188 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
189 }
190
191 // Return the Attribute that we found or created.
192 return Attribute(PA);
193 }
194
get(LLVMContext & Context,Attribute::AttrKind Kind,ArrayRef<ConstantRange> Val)195 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
196 ArrayRef<ConstantRange> Val) {
197 assert(Attribute::isConstantRangeListAttrKind(Kind) &&
198 "Not a ConstantRangeList attribute");
199 LLVMContextImpl *pImpl = Context.pImpl;
200 FoldingSetNodeID ID;
201 ID.AddInteger(Kind);
202 ID.AddInteger(Val.size());
203 for (auto &CR : Val) {
204 CR.getLower().Profile(ID);
205 CR.getUpper().Profile(ID);
206 }
207
208 void *InsertPoint;
209 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
210
211 if (!PA) {
212 // If we didn't find any existing attributes of the same shape then create a
213 // new one and insert it.
214 // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
215 // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
216 // allocation and record the allocated pointer in
217 // `ConstantRangeListAttributes`. LLVMContext destructor will call the
218 // destructor of the allocated pointer explicitly.
219 void *Mem = pImpl->Alloc.Allocate(
220 ConstantRangeListAttributeImpl::totalSizeToAlloc(Val),
221 alignof(ConstantRangeListAttributeImpl));
222 PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
223 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
224 pImpl->ConstantRangeListAttributes.push_back(
225 reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
226 }
227
228 // Return the Attribute that we found or created.
229 return Attribute(PA);
230 }
231
getWithAlignment(LLVMContext & Context,Align A)232 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
233 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
234 return get(Context, Alignment, A.value());
235 }
236
getWithStackAlignment(LLVMContext & Context,Align A)237 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
238 assert(A <= 0x100 && "Alignment too large.");
239 return get(Context, StackAlignment, A.value());
240 }
241
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)242 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
243 uint64_t Bytes) {
244 assert(Bytes && "Bytes must be non-zero.");
245 return get(Context, Dereferenceable, Bytes);
246 }
247
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)248 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
249 uint64_t Bytes) {
250 assert(Bytes && "Bytes must be non-zero.");
251 return get(Context, DereferenceableOrNull, Bytes);
252 }
253
getWithByValType(LLVMContext & Context,Type * Ty)254 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
255 return get(Context, ByVal, Ty);
256 }
257
getWithStructRetType(LLVMContext & Context,Type * Ty)258 Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
259 return get(Context, StructRet, Ty);
260 }
261
getWithByRefType(LLVMContext & Context,Type * Ty)262 Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
263 return get(Context, ByRef, Ty);
264 }
265
getWithPreallocatedType(LLVMContext & Context,Type * Ty)266 Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
267 return get(Context, Preallocated, Ty);
268 }
269
getWithInAllocaType(LLVMContext & Context,Type * Ty)270 Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
271 return get(Context, InAlloca, Ty);
272 }
273
getWithUWTableKind(LLVMContext & Context,UWTableKind Kind)274 Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
275 UWTableKind Kind) {
276 return get(Context, UWTable, uint64_t(Kind));
277 }
278
getWithMemoryEffects(LLVMContext & Context,MemoryEffects ME)279 Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
280 MemoryEffects ME) {
281 return get(Context, Memory, ME.toIntValue());
282 }
283
getWithNoFPClass(LLVMContext & Context,FPClassTest ClassMask)284 Attribute Attribute::getWithNoFPClass(LLVMContext &Context,
285 FPClassTest ClassMask) {
286 return get(Context, NoFPClass, ClassMask);
287 }
288
289 Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)290 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
291 const std::optional<unsigned> &NumElemsArg) {
292 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
293 "Invalid allocsize arguments -- given allocsize(0, 0)");
294 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
295 }
296
getWithVScaleRangeArgs(LLVMContext & Context,unsigned MinValue,unsigned MaxValue)297 Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
298 unsigned MinValue,
299 unsigned MaxValue) {
300 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
301 }
302
getAttrKindFromName(StringRef AttrName)303 Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
304 return StringSwitch<Attribute::AttrKind>(AttrName)
305 #define GET_ATTR_NAMES
306 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
307 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
308 #include "llvm/IR/Attributes.inc"
309 .Default(Attribute::None);
310 }
311
getNameFromAttrKind(Attribute::AttrKind AttrKind)312 StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
313 switch (AttrKind) {
314 #define GET_ATTR_NAMES
315 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
316 case Attribute::ENUM_NAME: \
317 return #DISPLAY_NAME;
318 #include "llvm/IR/Attributes.inc"
319 case Attribute::None:
320 return "none";
321 default:
322 llvm_unreachable("invalid Kind");
323 }
324 }
325
isExistingAttribute(StringRef Name)326 bool Attribute::isExistingAttribute(StringRef Name) {
327 return StringSwitch<bool>(Name)
328 #define GET_ATTR_NAMES
329 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
330 #include "llvm/IR/Attributes.inc"
331 .Default(false);
332 }
333
334 //===----------------------------------------------------------------------===//
335 // Attribute Accessor Methods
336 //===----------------------------------------------------------------------===//
337
isEnumAttribute() const338 bool Attribute::isEnumAttribute() const {
339 return pImpl && pImpl->isEnumAttribute();
340 }
341
isIntAttribute() const342 bool Attribute::isIntAttribute() const {
343 return pImpl && pImpl->isIntAttribute();
344 }
345
isStringAttribute() const346 bool Attribute::isStringAttribute() const {
347 return pImpl && pImpl->isStringAttribute();
348 }
349
isTypeAttribute() const350 bool Attribute::isTypeAttribute() const {
351 return pImpl && pImpl->isTypeAttribute();
352 }
353
isConstantRangeAttribute() const354 bool Attribute::isConstantRangeAttribute() const {
355 return pImpl && pImpl->isConstantRangeAttribute();
356 }
357
isConstantRangeListAttribute() const358 bool Attribute::isConstantRangeListAttribute() const {
359 return pImpl && pImpl->isConstantRangeListAttribute();
360 }
361
getKindAsEnum() const362 Attribute::AttrKind Attribute::getKindAsEnum() const {
363 if (!pImpl) return None;
364 assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
365 isConstantRangeAttribute() || isConstantRangeListAttribute()) &&
366 "Invalid attribute type to get the kind as an enum!");
367 return pImpl->getKindAsEnum();
368 }
369
getValueAsInt() const370 uint64_t Attribute::getValueAsInt() const {
371 if (!pImpl) return 0;
372 assert(isIntAttribute() &&
373 "Expected the attribute to be an integer attribute!");
374 return pImpl->getValueAsInt();
375 }
376
getValueAsBool() const377 bool Attribute::getValueAsBool() const {
378 if (!pImpl) return false;
379 assert(isStringAttribute() &&
380 "Expected the attribute to be a string attribute!");
381 return pImpl->getValueAsBool();
382 }
383
getKindAsString() const384 StringRef Attribute::getKindAsString() const {
385 if (!pImpl) return {};
386 assert(isStringAttribute() &&
387 "Invalid attribute type to get the kind as a string!");
388 return pImpl->getKindAsString();
389 }
390
getValueAsString() const391 StringRef Attribute::getValueAsString() const {
392 if (!pImpl) return {};
393 assert(isStringAttribute() &&
394 "Invalid attribute type to get the value as a string!");
395 return pImpl->getValueAsString();
396 }
397
getValueAsType() const398 Type *Attribute::getValueAsType() const {
399 if (!pImpl) return {};
400 assert(isTypeAttribute() &&
401 "Invalid attribute type to get the value as a type!");
402 return pImpl->getValueAsType();
403 }
404
getValueAsConstantRange() const405 const ConstantRange &Attribute::getValueAsConstantRange() const {
406 assert(isConstantRangeAttribute() &&
407 "Invalid attribute type to get the value as a ConstantRange!");
408 return pImpl->getValueAsConstantRange();
409 }
410
getValueAsConstantRangeList() const411 ArrayRef<ConstantRange> Attribute::getValueAsConstantRangeList() const {
412 assert(isConstantRangeListAttribute() &&
413 "Invalid attribute type to get the value as a ConstantRangeList!");
414 return pImpl->getValueAsConstantRangeList();
415 }
416
hasAttribute(AttrKind Kind) const417 bool Attribute::hasAttribute(AttrKind Kind) const {
418 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
419 }
420
hasAttribute(StringRef Kind) const421 bool Attribute::hasAttribute(StringRef Kind) const {
422 if (!isStringAttribute()) return false;
423 return pImpl && pImpl->hasAttribute(Kind);
424 }
425
getAlignment() const426 MaybeAlign Attribute::getAlignment() const {
427 assert(hasAttribute(Attribute::Alignment) &&
428 "Trying to get alignment from non-alignment attribute!");
429 return MaybeAlign(pImpl->getValueAsInt());
430 }
431
getStackAlignment() const432 MaybeAlign Attribute::getStackAlignment() const {
433 assert(hasAttribute(Attribute::StackAlignment) &&
434 "Trying to get alignment from non-alignment attribute!");
435 return MaybeAlign(pImpl->getValueAsInt());
436 }
437
getDereferenceableBytes() const438 uint64_t Attribute::getDereferenceableBytes() const {
439 assert(hasAttribute(Attribute::Dereferenceable) &&
440 "Trying to get dereferenceable bytes from "
441 "non-dereferenceable attribute!");
442 return pImpl->getValueAsInt();
443 }
444
getDereferenceableOrNullBytes() const445 uint64_t Attribute::getDereferenceableOrNullBytes() const {
446 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
447 "Trying to get dereferenceable bytes from "
448 "non-dereferenceable attribute!");
449 return pImpl->getValueAsInt();
450 }
451
452 std::pair<unsigned, std::optional<unsigned>>
getAllocSizeArgs() const453 Attribute::getAllocSizeArgs() const {
454 assert(hasAttribute(Attribute::AllocSize) &&
455 "Trying to get allocsize args from non-allocsize attribute");
456 return unpackAllocSizeArgs(pImpl->getValueAsInt());
457 }
458
getVScaleRangeMin() const459 unsigned Attribute::getVScaleRangeMin() const {
460 assert(hasAttribute(Attribute::VScaleRange) &&
461 "Trying to get vscale args from non-vscale attribute");
462 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
463 }
464
getVScaleRangeMax() const465 std::optional<unsigned> Attribute::getVScaleRangeMax() const {
466 assert(hasAttribute(Attribute::VScaleRange) &&
467 "Trying to get vscale args from non-vscale attribute");
468 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
469 }
470
getUWTableKind() const471 UWTableKind Attribute::getUWTableKind() const {
472 assert(hasAttribute(Attribute::UWTable) &&
473 "Trying to get unwind table kind from non-uwtable attribute");
474 return UWTableKind(pImpl->getValueAsInt());
475 }
476
getAllocKind() const477 AllocFnKind Attribute::getAllocKind() const {
478 assert(hasAttribute(Attribute::AllocKind) &&
479 "Trying to get allockind value from non-allockind attribute");
480 return AllocFnKind(pImpl->getValueAsInt());
481 }
482
getMemoryEffects() const483 MemoryEffects Attribute::getMemoryEffects() const {
484 assert(hasAttribute(Attribute::Memory) &&
485 "Can only call getMemoryEffects() on memory attribute");
486 return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
487 }
488
getNoFPClass() const489 FPClassTest Attribute::getNoFPClass() const {
490 assert(hasAttribute(Attribute::NoFPClass) &&
491 "Can only call getNoFPClass() on nofpclass attribute");
492 return static_cast<FPClassTest>(pImpl->getValueAsInt());
493 }
494
getRange() const495 const ConstantRange &Attribute::getRange() const {
496 assert(hasAttribute(Attribute::Range) &&
497 "Trying to get range args from non-range attribute");
498 return pImpl->getValueAsConstantRange();
499 }
500
getInitializes() const501 ArrayRef<ConstantRange> Attribute::getInitializes() const {
502 assert(hasAttribute(Attribute::Initializes) &&
503 "Trying to get initializes attr from non-ConstantRangeList attribute");
504 return pImpl->getValueAsConstantRangeList();
505 }
506
getModRefStr(ModRefInfo MR)507 static const char *getModRefStr(ModRefInfo MR) {
508 switch (MR) {
509 case ModRefInfo::NoModRef:
510 return "none";
511 case ModRefInfo::Ref:
512 return "read";
513 case ModRefInfo::Mod:
514 return "write";
515 case ModRefInfo::ModRef:
516 return "readwrite";
517 }
518 llvm_unreachable("Invalid ModRefInfo");
519 }
520
getAsString(bool InAttrGrp) const521 std::string Attribute::getAsString(bool InAttrGrp) const {
522 if (!pImpl) return {};
523
524 if (isEnumAttribute())
525 return getNameFromAttrKind(getKindAsEnum()).str();
526
527 if (isTypeAttribute()) {
528 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
529 Result += '(';
530 raw_string_ostream OS(Result);
531 getValueAsType()->print(OS, false, true);
532 OS.flush();
533 Result += ')';
534 return Result;
535 }
536
537 // FIXME: These should be output like this:
538 //
539 // align=4
540 // alignstack=8
541 //
542 if (hasAttribute(Attribute::Alignment))
543 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
544 : "align " + Twine(getValueAsInt()))
545 .str();
546
547 auto AttrWithBytesToString = [&](const char *Name) {
548 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
549 : Name + ("(" + Twine(getValueAsInt())) + ")")
550 .str();
551 };
552
553 if (hasAttribute(Attribute::StackAlignment))
554 return AttrWithBytesToString("alignstack");
555
556 if (hasAttribute(Attribute::Dereferenceable))
557 return AttrWithBytesToString("dereferenceable");
558
559 if (hasAttribute(Attribute::DereferenceableOrNull))
560 return AttrWithBytesToString("dereferenceable_or_null");
561
562 if (hasAttribute(Attribute::AllocSize)) {
563 unsigned ElemSize;
564 std::optional<unsigned> NumElems;
565 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
566
567 return (NumElems
568 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
569 : "allocsize(" + Twine(ElemSize) + ")")
570 .str();
571 }
572
573 if (hasAttribute(Attribute::VScaleRange)) {
574 unsigned MinValue = getVScaleRangeMin();
575 std::optional<unsigned> MaxValue = getVScaleRangeMax();
576 return ("vscale_range(" + Twine(MinValue) + "," +
577 Twine(MaxValue.value_or(0)) + ")")
578 .str();
579 }
580
581 if (hasAttribute(Attribute::UWTable)) {
582 UWTableKind Kind = getUWTableKind();
583 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
584 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
585 }
586
587 if (hasAttribute(Attribute::AllocKind)) {
588 AllocFnKind Kind = getAllocKind();
589 SmallVector<StringRef> parts;
590 if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
591 parts.push_back("alloc");
592 if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
593 parts.push_back("realloc");
594 if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
595 parts.push_back("free");
596 if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
597 parts.push_back("uninitialized");
598 if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
599 parts.push_back("zeroed");
600 if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
601 parts.push_back("aligned");
602 return ("allockind(\"" +
603 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
604 .str();
605 }
606
607 if (hasAttribute(Attribute::Memory)) {
608 std::string Result;
609 raw_string_ostream OS(Result);
610 bool First = true;
611 OS << "memory(";
612
613 MemoryEffects ME = getMemoryEffects();
614
615 // Print access kind for "other" as the default access kind. This way it
616 // will apply to any new location kinds that get split out of "other".
617 ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other);
618 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
619 First = false;
620 OS << getModRefStr(OtherMR);
621 }
622
623 for (auto Loc : MemoryEffects::locations()) {
624 ModRefInfo MR = ME.getModRef(Loc);
625 if (MR == OtherMR)
626 continue;
627
628 if (!First)
629 OS << ", ";
630 First = false;
631
632 switch (Loc) {
633 case IRMemLocation::ArgMem:
634 OS << "argmem: ";
635 break;
636 case IRMemLocation::InaccessibleMem:
637 OS << "inaccessiblemem: ";
638 break;
639 case IRMemLocation::Other:
640 llvm_unreachable("This is represented as the default access kind");
641 }
642 OS << getModRefStr(MR);
643 }
644 OS << ")";
645 OS.flush();
646 return Result;
647 }
648
649 if (hasAttribute(Attribute::NoFPClass)) {
650 std::string Result = "nofpclass";
651 raw_string_ostream OS(Result);
652 OS << getNoFPClass();
653 return Result;
654 }
655
656 if (hasAttribute(Attribute::Range)) {
657 std::string Result;
658 raw_string_ostream OS(Result);
659 const ConstantRange &CR = getValueAsConstantRange();
660 OS << "range(";
661 OS << "i" << CR.getBitWidth() << " ";
662 OS << CR.getLower() << ", " << CR.getUpper();
663 OS << ")";
664 OS.flush();
665 return Result;
666 }
667
668 if (hasAttribute(Attribute::Initializes)) {
669 std::string Result;
670 raw_string_ostream OS(Result);
671 ConstantRangeList CRL = getInitializes();
672 OS << "initializes(";
673 CRL.print(OS);
674 OS << ")";
675 OS.flush();
676 return Result;
677 }
678
679 // Convert target-dependent attributes to strings of the form:
680 //
681 // "kind"
682 // "kind" = "value"
683 //
684 if (isStringAttribute()) {
685 std::string Result;
686 {
687 raw_string_ostream OS(Result);
688 OS << '"' << getKindAsString() << '"';
689
690 // Since some attribute strings contain special characters that cannot be
691 // printable, those have to be escaped to make the attribute value
692 // printable as is. e.g. "\01__gnu_mcount_nc"
693 const auto &AttrVal = pImpl->getValueAsString();
694 if (!AttrVal.empty()) {
695 OS << "=\"";
696 printEscapedString(AttrVal, OS);
697 OS << "\"";
698 }
699 }
700 return Result;
701 }
702
703 llvm_unreachable("Unknown attribute");
704 }
705
hasParentContext(LLVMContext & C) const706 bool Attribute::hasParentContext(LLVMContext &C) const {
707 assert(isValid() && "invalid Attribute doesn't refer to any context");
708 FoldingSetNodeID ID;
709 pImpl->Profile(ID);
710 void *Unused;
711 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
712 }
713
operator <(Attribute A) const714 bool Attribute::operator<(Attribute A) const {
715 if (!pImpl && !A.pImpl) return false;
716 if (!pImpl) return true;
717 if (!A.pImpl) return false;
718 return *pImpl < *A.pImpl;
719 }
720
Profile(FoldingSetNodeID & ID) const721 void Attribute::Profile(FoldingSetNodeID &ID) const {
722 ID.AddPointer(pImpl);
723 }
724
725 enum AttributeProperty {
726 FnAttr = (1 << 0),
727 ParamAttr = (1 << 1),
728 RetAttr = (1 << 2),
729 };
730
731 #define GET_ATTR_PROP_TABLE
732 #include "llvm/IR/Attributes.inc"
733
hasAttributeProperty(Attribute::AttrKind Kind,AttributeProperty Prop)734 static bool hasAttributeProperty(Attribute::AttrKind Kind,
735 AttributeProperty Prop) {
736 unsigned Index = Kind - 1;
737 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
738 return AttrPropTable[Index] & Prop;
739 }
740
canUseAsFnAttr(AttrKind Kind)741 bool Attribute::canUseAsFnAttr(AttrKind Kind) {
742 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
743 }
744
canUseAsParamAttr(AttrKind Kind)745 bool Attribute::canUseAsParamAttr(AttrKind Kind) {
746 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
747 }
748
canUseAsRetAttr(AttrKind Kind)749 bool Attribute::canUseAsRetAttr(AttrKind Kind) {
750 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
751 }
752
753 //===----------------------------------------------------------------------===//
754 // AttributeImpl Definition
755 //===----------------------------------------------------------------------===//
756
hasAttribute(Attribute::AttrKind A) const757 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
758 if (isStringAttribute()) return false;
759 return getKindAsEnum() == A;
760 }
761
hasAttribute(StringRef Kind) const762 bool AttributeImpl::hasAttribute(StringRef Kind) const {
763 if (!isStringAttribute()) return false;
764 return getKindAsString() == Kind;
765 }
766
getKindAsEnum() const767 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
768 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
769 isConstantRangeAttribute() || isConstantRangeListAttribute());
770 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
771 }
772
getValueAsInt() const773 uint64_t AttributeImpl::getValueAsInt() const {
774 assert(isIntAttribute());
775 return static_cast<const IntAttributeImpl *>(this)->getValue();
776 }
777
getValueAsBool() const778 bool AttributeImpl::getValueAsBool() const {
779 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
780 return getValueAsString() == "true";
781 }
782
getKindAsString() const783 StringRef AttributeImpl::getKindAsString() const {
784 assert(isStringAttribute());
785 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
786 }
787
getValueAsString() const788 StringRef AttributeImpl::getValueAsString() const {
789 assert(isStringAttribute());
790 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
791 }
792
getValueAsType() const793 Type *AttributeImpl::getValueAsType() const {
794 assert(isTypeAttribute());
795 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
796 }
797
getValueAsConstantRange() const798 const ConstantRange &AttributeImpl::getValueAsConstantRange() const {
799 assert(isConstantRangeAttribute());
800 return static_cast<const ConstantRangeAttributeImpl *>(this)
801 ->getConstantRangeValue();
802 }
803
getValueAsConstantRangeList() const804 ArrayRef<ConstantRange> AttributeImpl::getValueAsConstantRangeList() const {
805 assert(isConstantRangeListAttribute());
806 return static_cast<const ConstantRangeListAttributeImpl *>(this)
807 ->getConstantRangeListValue();
808 }
809
operator <(const AttributeImpl & AI) const810 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
811 if (this == &AI)
812 return false;
813
814 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
815 // relative to their enum value) and then strings.
816 if (!isStringAttribute()) {
817 if (AI.isStringAttribute())
818 return true;
819 if (getKindAsEnum() != AI.getKindAsEnum())
820 return getKindAsEnum() < AI.getKindAsEnum();
821 assert(!AI.isEnumAttribute() && "Non-unique attribute");
822 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
823 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
824 assert(!AI.isConstantRangeListAttribute() &&
825 "Unclear how to compare range list");
826 // TODO: Is this actually needed?
827 assert(AI.isIntAttribute() && "Only possibility left");
828 return getValueAsInt() < AI.getValueAsInt();
829 }
830
831 if (!AI.isStringAttribute())
832 return false;
833 if (getKindAsString() == AI.getKindAsString())
834 return getValueAsString() < AI.getValueAsString();
835 return getKindAsString() < AI.getKindAsString();
836 }
837
838 //===----------------------------------------------------------------------===//
839 // AttributeSet Definition
840 //===----------------------------------------------------------------------===//
841
get(LLVMContext & C,const AttrBuilder & B)842 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
843 return AttributeSet(AttributeSetNode::get(C, B));
844 }
845
get(LLVMContext & C,ArrayRef<Attribute> Attrs)846 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
847 return AttributeSet(AttributeSetNode::get(C, Attrs));
848 }
849
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const850 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
851 Attribute::AttrKind Kind) const {
852 if (hasAttribute(Kind)) return *this;
853 AttrBuilder B(C);
854 B.addAttribute(Kind);
855 return addAttributes(C, AttributeSet::get(C, B));
856 }
857
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const858 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
859 StringRef Value) const {
860 AttrBuilder B(C);
861 B.addAttribute(Kind, Value);
862 return addAttributes(C, AttributeSet::get(C, B));
863 }
864
addAttributes(LLVMContext & C,const AttributeSet AS) const865 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
866 const AttributeSet AS) const {
867 if (!hasAttributes())
868 return AS;
869
870 if (!AS.hasAttributes())
871 return *this;
872
873 AttrBuilder B(C, *this);
874 B.merge(AttrBuilder(C, AS));
875 return get(C, B);
876 }
877
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const878 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
879 Attribute::AttrKind Kind) const {
880 if (!hasAttribute(Kind)) return *this;
881 AttrBuilder B(C, *this);
882 B.removeAttribute(Kind);
883 return get(C, B);
884 }
885
removeAttribute(LLVMContext & C,StringRef Kind) const886 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
887 StringRef Kind) const {
888 if (!hasAttribute(Kind)) return *this;
889 AttrBuilder B(C, *this);
890 B.removeAttribute(Kind);
891 return get(C, B);
892 }
893
removeAttributes(LLVMContext & C,const AttributeMask & Attrs) const894 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
895 const AttributeMask &Attrs) const {
896 AttrBuilder B(C, *this);
897 // If there is nothing to remove, directly return the original set.
898 if (!B.overlaps(Attrs))
899 return *this;
900
901 B.remove(Attrs);
902 return get(C, B);
903 }
904
getNumAttributes() const905 unsigned AttributeSet::getNumAttributes() const {
906 return SetNode ? SetNode->getNumAttributes() : 0;
907 }
908
hasAttribute(Attribute::AttrKind Kind) const909 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
910 return SetNode ? SetNode->hasAttribute(Kind) : false;
911 }
912
hasAttribute(StringRef Kind) const913 bool AttributeSet::hasAttribute(StringRef Kind) const {
914 return SetNode ? SetNode->hasAttribute(Kind) : false;
915 }
916
getAttribute(Attribute::AttrKind Kind) const917 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
918 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
919 }
920
getAttribute(StringRef Kind) const921 Attribute AttributeSet::getAttribute(StringRef Kind) const {
922 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
923 }
924
getAlignment() const925 MaybeAlign AttributeSet::getAlignment() const {
926 return SetNode ? SetNode->getAlignment() : std::nullopt;
927 }
928
getStackAlignment() const929 MaybeAlign AttributeSet::getStackAlignment() const {
930 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
931 }
932
getDereferenceableBytes() const933 uint64_t AttributeSet::getDereferenceableBytes() const {
934 return SetNode ? SetNode->getDereferenceableBytes() : 0;
935 }
936
getDereferenceableOrNullBytes() const937 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
938 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
939 }
940
getByRefType() const941 Type *AttributeSet::getByRefType() const {
942 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
943 }
944
getByValType() const945 Type *AttributeSet::getByValType() const {
946 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
947 }
948
getStructRetType() const949 Type *AttributeSet::getStructRetType() const {
950 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
951 }
952
getPreallocatedType() const953 Type *AttributeSet::getPreallocatedType() const {
954 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
955 }
956
getInAllocaType() const957 Type *AttributeSet::getInAllocaType() const {
958 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
959 }
960
getElementType() const961 Type *AttributeSet::getElementType() const {
962 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
963 }
964
965 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const966 AttributeSet::getAllocSizeArgs() const {
967 if (SetNode)
968 return SetNode->getAllocSizeArgs();
969 return std::nullopt;
970 }
971
getVScaleRangeMin() const972 unsigned AttributeSet::getVScaleRangeMin() const {
973 return SetNode ? SetNode->getVScaleRangeMin() : 1;
974 }
975
getVScaleRangeMax() const976 std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
977 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
978 }
979
getUWTableKind() const980 UWTableKind AttributeSet::getUWTableKind() const {
981 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
982 }
983
getAllocKind() const984 AllocFnKind AttributeSet::getAllocKind() const {
985 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
986 }
987
getMemoryEffects() const988 MemoryEffects AttributeSet::getMemoryEffects() const {
989 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
990 }
991
getNoFPClass() const992 FPClassTest AttributeSet::getNoFPClass() const {
993 return SetNode ? SetNode->getNoFPClass() : fcNone;
994 }
995
getAsString(bool InAttrGrp) const996 std::string AttributeSet::getAsString(bool InAttrGrp) const {
997 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
998 }
999
hasParentContext(LLVMContext & C) const1000 bool AttributeSet::hasParentContext(LLVMContext &C) const {
1001 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1002 FoldingSetNodeID ID;
1003 SetNode->Profile(ID);
1004 void *Unused;
1005 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1006 }
1007
begin() const1008 AttributeSet::iterator AttributeSet::begin() const {
1009 return SetNode ? SetNode->begin() : nullptr;
1010 }
1011
end() const1012 AttributeSet::iterator AttributeSet::end() const {
1013 return SetNode ? SetNode->end() : nullptr;
1014 }
1015
1016 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1017 LLVM_DUMP_METHOD void AttributeSet::dump() const {
1018 dbgs() << "AS =\n";
1019 dbgs() << " { ";
1020 dbgs() << getAsString(true) << " }\n";
1021 }
1022 #endif
1023
1024 //===----------------------------------------------------------------------===//
1025 // AttributeSetNode Definition
1026 //===----------------------------------------------------------------------===//
1027
AttributeSetNode(ArrayRef<Attribute> Attrs)1028 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1029 : NumAttrs(Attrs.size()) {
1030 // There's memory after the node where we can store the entries in.
1031 llvm::copy(Attrs, getTrailingObjects<Attribute>());
1032
1033 for (const auto &I : *this) {
1034 if (I.isStringAttribute())
1035 StringAttrs.insert({ I.getKindAsString(), I });
1036 else
1037 AvailableAttrs.addAttribute(I.getKindAsEnum());
1038 }
1039 }
1040
get(LLVMContext & C,ArrayRef<Attribute> Attrs)1041 AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
1042 ArrayRef<Attribute> Attrs) {
1043 SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
1044 llvm::sort(SortedAttrs);
1045 return getSorted(C, SortedAttrs);
1046 }
1047
getSorted(LLVMContext & C,ArrayRef<Attribute> SortedAttrs)1048 AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1049 ArrayRef<Attribute> SortedAttrs) {
1050 if (SortedAttrs.empty())
1051 return nullptr;
1052
1053 // Build a key to look up the existing attributes.
1054 LLVMContextImpl *pImpl = C.pImpl;
1055 FoldingSetNodeID ID;
1056
1057 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1058 for (const auto &Attr : SortedAttrs)
1059 Attr.Profile(ID);
1060
1061 void *InsertPoint;
1062 AttributeSetNode *PA =
1063 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1064
1065 // If we didn't find any existing attributes of the same shape then create a
1066 // new one and insert it.
1067 if (!PA) {
1068 // Coallocate entries after the AttributeSetNode itself.
1069 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1070 PA = new (Mem) AttributeSetNode(SortedAttrs);
1071 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1072 }
1073
1074 // Return the AttributeSetNode that we found or created.
1075 return PA;
1076 }
1077
get(LLVMContext & C,const AttrBuilder & B)1078 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
1079 return getSorted(C, B.attrs());
1080 }
1081
hasAttribute(StringRef Kind) const1082 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
1083 return StringAttrs.count(Kind);
1084 }
1085
1086 std::optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const1087 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1088 // Do a quick presence check.
1089 if (!hasAttribute(Kind))
1090 return std::nullopt;
1091
1092 // Attributes in a set are sorted by enum value, followed by string
1093 // attributes. Binary search the one we want.
1094 const Attribute *I =
1095 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1096 [](Attribute A, Attribute::AttrKind Kind) {
1097 return A.getKindAsEnum() < Kind;
1098 });
1099 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1100 return *I;
1101 }
1102
getAttribute(Attribute::AttrKind Kind) const1103 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
1104 if (auto A = findEnumAttribute(Kind))
1105 return *A;
1106 return {};
1107 }
1108
getAttribute(StringRef Kind) const1109 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
1110 return StringAttrs.lookup(Kind);
1111 }
1112
getAlignment() const1113 MaybeAlign AttributeSetNode::getAlignment() const {
1114 if (auto A = findEnumAttribute(Attribute::Alignment))
1115 return A->getAlignment();
1116 return std::nullopt;
1117 }
1118
getStackAlignment() const1119 MaybeAlign AttributeSetNode::getStackAlignment() const {
1120 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1121 return A->getStackAlignment();
1122 return std::nullopt;
1123 }
1124
getAttributeType(Attribute::AttrKind Kind) const1125 Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
1126 if (auto A = findEnumAttribute(Kind))
1127 return A->getValueAsType();
1128 return nullptr;
1129 }
1130
getDereferenceableBytes() const1131 uint64_t AttributeSetNode::getDereferenceableBytes() const {
1132 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1133 return A->getDereferenceableBytes();
1134 return 0;
1135 }
1136
getDereferenceableOrNullBytes() const1137 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
1138 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1139 return A->getDereferenceableOrNullBytes();
1140 return 0;
1141 }
1142
1143 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1144 AttributeSetNode::getAllocSizeArgs() const {
1145 if (auto A = findEnumAttribute(Attribute::AllocSize))
1146 return A->getAllocSizeArgs();
1147 return std::nullopt;
1148 }
1149
getVScaleRangeMin() const1150 unsigned AttributeSetNode::getVScaleRangeMin() const {
1151 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1152 return A->getVScaleRangeMin();
1153 return 1;
1154 }
1155
getVScaleRangeMax() const1156 std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1157 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1158 return A->getVScaleRangeMax();
1159 return std::nullopt;
1160 }
1161
getUWTableKind() const1162 UWTableKind AttributeSetNode::getUWTableKind() const {
1163 if (auto A = findEnumAttribute(Attribute::UWTable))
1164 return A->getUWTableKind();
1165 return UWTableKind::None;
1166 }
1167
getAllocKind() const1168 AllocFnKind AttributeSetNode::getAllocKind() const {
1169 if (auto A = findEnumAttribute(Attribute::AllocKind))
1170 return A->getAllocKind();
1171 return AllocFnKind::Unknown;
1172 }
1173
getMemoryEffects() const1174 MemoryEffects AttributeSetNode::getMemoryEffects() const {
1175 if (auto A = findEnumAttribute(Attribute::Memory))
1176 return A->getMemoryEffects();
1177 return MemoryEffects::unknown();
1178 }
1179
getNoFPClass() const1180 FPClassTest AttributeSetNode::getNoFPClass() const {
1181 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1182 return A->getNoFPClass();
1183 return fcNone;
1184 }
1185
getAsString(bool InAttrGrp) const1186 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1187 std::string Str;
1188 for (iterator I = begin(), E = end(); I != E; ++I) {
1189 if (I != begin())
1190 Str += ' ';
1191 Str += I->getAsString(InAttrGrp);
1192 }
1193 return Str;
1194 }
1195
1196 //===----------------------------------------------------------------------===//
1197 // AttributeListImpl Definition
1198 //===----------------------------------------------------------------------===//
1199
1200 /// Map from AttributeList index to the internal array index. Adding one happens
1201 /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)1202 static unsigned attrIdxToArrayIdx(unsigned Index) {
1203 return Index + 1;
1204 }
1205
AttributeListImpl(ArrayRef<AttributeSet> Sets)1206 AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
1207 : NumAttrSets(Sets.size()) {
1208 assert(!Sets.empty() && "pointless AttributeListImpl");
1209
1210 // There's memory after the node where we can store the entries in.
1211 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1212
1213 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1214 // summary bitsets.
1215 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1216 if (!I.isStringAttribute())
1217 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1218
1219 for (const auto &Set : Sets)
1220 for (const auto &I : Set)
1221 if (!I.isStringAttribute())
1222 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1223 }
1224
Profile(FoldingSetNodeID & ID) const1225 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
1226 Profile(ID, ArrayRef(begin(), end()));
1227 }
1228
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)1229 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
1230 ArrayRef<AttributeSet> Sets) {
1231 for (const auto &Set : Sets)
1232 ID.AddPointer(Set.SetNode);
1233 }
1234
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const1235 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
1236 unsigned *Index) const {
1237 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1238 return false;
1239
1240 if (Index) {
1241 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1242 if (begin()[I].hasAttribute(Kind)) {
1243 *Index = I - 1;
1244 break;
1245 }
1246 }
1247 }
1248
1249 return true;
1250 }
1251
1252
1253 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1254 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1255 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1256 }
1257 #endif
1258
1259 //===----------------------------------------------------------------------===//
1260 // AttributeList Construction and Mutation Methods
1261 //===----------------------------------------------------------------------===//
1262
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)1263 AttributeList AttributeList::getImpl(LLVMContext &C,
1264 ArrayRef<AttributeSet> AttrSets) {
1265 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1266
1267 LLVMContextImpl *pImpl = C.pImpl;
1268 FoldingSetNodeID ID;
1269 AttributeListImpl::Profile(ID, AttrSets);
1270
1271 void *InsertPoint;
1272 AttributeListImpl *PA =
1273 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1274
1275 // If we didn't find any existing attributes of the same shape then
1276 // create a new one and insert it.
1277 if (!PA) {
1278 // Coallocate entries after the AttributeListImpl itself.
1279 void *Mem = pImpl->Alloc.Allocate(
1280 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1281 alignof(AttributeListImpl));
1282 PA = new (Mem) AttributeListImpl(AttrSets);
1283 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1284 }
1285
1286 // Return the AttributesList that we found or created.
1287 return AttributeList(PA);
1288 }
1289
1290 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)1291 AttributeList::get(LLVMContext &C,
1292 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1293 // If there are no attributes then return a null AttributesList pointer.
1294 if (Attrs.empty())
1295 return {};
1296
1297 assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1298 "Misordered Attributes list!");
1299 assert(llvm::all_of(Attrs,
1300 [](const std::pair<unsigned, Attribute> &Pair) {
1301 return Pair.second.isValid();
1302 }) &&
1303 "Pointless attribute!");
1304
1305 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1306 // list.
1307 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1308 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1309 E = Attrs.end(); I != E; ) {
1310 unsigned Index = I->first;
1311 SmallVector<Attribute, 4> AttrVec;
1312 while (I != E && I->first == Index) {
1313 AttrVec.push_back(I->second);
1314 ++I;
1315 }
1316
1317 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1318 }
1319
1320 return get(C, AttrPairVec);
1321 }
1322
1323 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1324 AttributeList::get(LLVMContext &C,
1325 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1326 // If there are no attributes then return a null AttributesList pointer.
1327 if (Attrs.empty())
1328 return {};
1329
1330 assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1331 "Misordered Attributes list!");
1332 assert(llvm::none_of(Attrs,
1333 [](const std::pair<unsigned, AttributeSet> &Pair) {
1334 return !Pair.second.hasAttributes();
1335 }) &&
1336 "Pointless attribute!");
1337
1338 unsigned MaxIndex = Attrs.back().first;
1339 // If the MaxIndex is FunctionIndex and there are other indices in front
1340 // of it, we need to use the largest of those to get the right size.
1341 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1342 MaxIndex = Attrs[Attrs.size() - 2].first;
1343
1344 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1345 for (const auto &Pair : Attrs)
1346 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1347
1348 return getImpl(C, AttrVec);
1349 }
1350
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)1351 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1352 AttributeSet RetAttrs,
1353 ArrayRef<AttributeSet> ArgAttrs) {
1354 // Scan from the end to find the last argument with attributes. Most
1355 // arguments don't have attributes, so it's nice if we can have fewer unique
1356 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1357 unsigned NumSets = 0;
1358 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1359 if (ArgAttrs[I - 1].hasAttributes()) {
1360 NumSets = I + 2;
1361 break;
1362 }
1363 }
1364 if (NumSets == 0) {
1365 // Check function and return attributes if we didn't have argument
1366 // attributes.
1367 if (RetAttrs.hasAttributes())
1368 NumSets = 2;
1369 else if (FnAttrs.hasAttributes())
1370 NumSets = 1;
1371 }
1372
1373 // If all attribute sets were empty, we can use the empty attribute list.
1374 if (NumSets == 0)
1375 return {};
1376
1377 SmallVector<AttributeSet, 8> AttrSets;
1378 AttrSets.reserve(NumSets);
1379 // If we have any attributes, we always have function attributes.
1380 AttrSets.push_back(FnAttrs);
1381 if (NumSets > 1)
1382 AttrSets.push_back(RetAttrs);
1383 if (NumSets > 2) {
1384 // Drop the empty argument attribute sets at the end.
1385 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1386 llvm::append_range(AttrSets, ArgAttrs);
1387 }
1388
1389 return getImpl(C, AttrSets);
1390 }
1391
get(LLVMContext & C,unsigned Index,AttributeSet Attrs)1392 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1393 AttributeSet Attrs) {
1394 if (!Attrs.hasAttributes())
1395 return {};
1396 Index = attrIdxToArrayIdx(Index);
1397 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1398 AttrSets[Index] = Attrs;
1399 return getImpl(C, AttrSets);
1400 }
1401
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1402 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1403 const AttrBuilder &B) {
1404 return get(C, Index, AttributeSet::get(C, B));
1405 }
1406
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1407 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1408 ArrayRef<Attribute::AttrKind> Kinds) {
1409 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1410 for (const auto K : Kinds)
1411 Attrs.emplace_back(Index, Attribute::get(C, K));
1412 return get(C, Attrs);
1413 }
1414
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)1415 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1416 ArrayRef<Attribute::AttrKind> Kinds,
1417 ArrayRef<uint64_t> Values) {
1418 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1419 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1420 auto VI = Values.begin();
1421 for (const auto K : Kinds)
1422 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1423 return get(C, Attrs);
1424 }
1425
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1426 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1427 ArrayRef<StringRef> Kinds) {
1428 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1429 for (const auto &K : Kinds)
1430 Attrs.emplace_back(Index, Attribute::get(C, K));
1431 return get(C, Attrs);
1432 }
1433
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1434 AttributeList AttributeList::get(LLVMContext &C,
1435 ArrayRef<AttributeList> Attrs) {
1436 if (Attrs.empty())
1437 return {};
1438 if (Attrs.size() == 1)
1439 return Attrs[0];
1440
1441 unsigned MaxSize = 0;
1442 for (const auto &List : Attrs)
1443 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1444
1445 // If every list was empty, there is no point in merging the lists.
1446 if (MaxSize == 0)
1447 return {};
1448
1449 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1450 for (unsigned I = 0; I < MaxSize; ++I) {
1451 AttrBuilder CurBuilder(C);
1452 for (const auto &List : Attrs)
1453 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1454 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1455 }
1456
1457 return getImpl(C, NewAttrSets);
1458 }
1459
1460 AttributeList
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1461 AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1462 Attribute::AttrKind Kind) const {
1463 AttributeSet Attrs = getAttributes(Index);
1464 if (Attrs.hasAttribute(Kind))
1465 return *this;
1466 // TODO: Insert at correct position and avoid sort.
1467 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1468 NewAttrs.push_back(Attribute::get(C, Kind));
1469 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1470 }
1471
addAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1472 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1473 StringRef Kind,
1474 StringRef Value) const {
1475 AttrBuilder B(C);
1476 B.addAttribute(Kind, Value);
1477 return addAttributesAtIndex(C, Index, B);
1478 }
1479
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute A) const1480 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1481 Attribute A) const {
1482 AttrBuilder B(C);
1483 B.addAttribute(A);
1484 return addAttributesAtIndex(C, Index, B);
1485 }
1486
setAttributesAtIndex(LLVMContext & C,unsigned Index,AttributeSet Attrs) const1487 AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1488 unsigned Index,
1489 AttributeSet Attrs) const {
1490 Index = attrIdxToArrayIdx(Index);
1491 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1492 if (Index >= AttrSets.size())
1493 AttrSets.resize(Index + 1);
1494 AttrSets[Index] = Attrs;
1495
1496 // Remove trailing empty attribute sets.
1497 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1498 AttrSets.pop_back();
1499 if (AttrSets.empty())
1500 return {};
1501 return AttributeList::getImpl(C, AttrSets);
1502 }
1503
addAttributesAtIndex(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1504 AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1505 unsigned Index,
1506 const AttrBuilder &B) const {
1507 if (!B.hasAttributes())
1508 return *this;
1509
1510 if (!pImpl)
1511 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1512
1513 AttrBuilder Merged(C, getAttributes(Index));
1514 Merged.merge(B);
1515 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1516 }
1517
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const1518 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1519 ArrayRef<unsigned> ArgNos,
1520 Attribute A) const {
1521 assert(llvm::is_sorted(ArgNos));
1522
1523 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1524 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1525 if (MaxIndex >= AttrSets.size())
1526 AttrSets.resize(MaxIndex + 1);
1527
1528 for (unsigned ArgNo : ArgNos) {
1529 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1530 AttrBuilder B(C, AttrSets[Index]);
1531 B.addAttribute(A);
1532 AttrSets[Index] = AttributeSet::get(C, B);
1533 }
1534
1535 return getImpl(C, AttrSets);
1536 }
1537
1538 AttributeList
removeAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1539 AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1540 Attribute::AttrKind Kind) const {
1541 AttributeSet Attrs = getAttributes(Index);
1542 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1543 if (Attrs == NewAttrs)
1544 return *this;
1545 return setAttributesAtIndex(C, Index, NewAttrs);
1546 }
1547
removeAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind) const1548 AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1549 unsigned Index,
1550 StringRef Kind) const {
1551 AttributeSet Attrs = getAttributes(Index);
1552 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1553 if (Attrs == NewAttrs)
1554 return *this;
1555 return setAttributesAtIndex(C, Index, NewAttrs);
1556 }
1557
removeAttributesAtIndex(LLVMContext & C,unsigned Index,const AttributeMask & AttrsToRemove) const1558 AttributeList AttributeList::removeAttributesAtIndex(
1559 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1560 AttributeSet Attrs = getAttributes(Index);
1561 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1562 // If nothing was removed, return the original list.
1563 if (Attrs == NewAttrs)
1564 return *this;
1565 return setAttributesAtIndex(C, Index, NewAttrs);
1566 }
1567
1568 AttributeList
removeAttributesAtIndex(LLVMContext & C,unsigned WithoutIndex) const1569 AttributeList::removeAttributesAtIndex(LLVMContext &C,
1570 unsigned WithoutIndex) const {
1571 if (!pImpl)
1572 return {};
1573 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1574 return *this;
1575 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1576 }
1577
addDereferenceableRetAttr(LLVMContext & C,uint64_t Bytes) const1578 AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1579 uint64_t Bytes) const {
1580 AttrBuilder B(C);
1581 B.addDereferenceableAttr(Bytes);
1582 return addRetAttributes(C, B);
1583 }
1584
addDereferenceableParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1585 AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1586 unsigned Index,
1587 uint64_t Bytes) const {
1588 AttrBuilder B(C);
1589 B.addDereferenceableAttr(Bytes);
1590 return addParamAttributes(C, Index, B);
1591 }
1592
1593 AttributeList
addDereferenceableOrNullParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1594 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1595 uint64_t Bytes) const {
1596 AttrBuilder B(C);
1597 B.addDereferenceableOrNullAttr(Bytes);
1598 return addParamAttributes(C, Index, B);
1599 }
1600
addRangeRetAttr(LLVMContext & C,const ConstantRange & CR) const1601 AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
1602 const ConstantRange &CR) const {
1603 AttrBuilder B(C);
1604 B.addRangeAttr(CR);
1605 return addRetAttributes(C, B);
1606 }
1607
addAllocSizeParamAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)1608 AttributeList AttributeList::addAllocSizeParamAttr(
1609 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1610 const std::optional<unsigned> &NumElemsArg) {
1611 AttrBuilder B(C);
1612 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1613 return addParamAttributes(C, Index, B);
1614 }
1615
1616 //===----------------------------------------------------------------------===//
1617 // AttributeList Accessor Methods
1618 //===----------------------------------------------------------------------===//
1619
getParamAttrs(unsigned ArgNo) const1620 AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1621 return getAttributes(ArgNo + FirstArgIndex);
1622 }
1623
getRetAttrs() const1624 AttributeSet AttributeList::getRetAttrs() const {
1625 return getAttributes(ReturnIndex);
1626 }
1627
getFnAttrs() const1628 AttributeSet AttributeList::getFnAttrs() const {
1629 return getAttributes(FunctionIndex);
1630 }
1631
hasAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1632 bool AttributeList::hasAttributeAtIndex(unsigned Index,
1633 Attribute::AttrKind Kind) const {
1634 return getAttributes(Index).hasAttribute(Kind);
1635 }
1636
hasAttributeAtIndex(unsigned Index,StringRef Kind) const1637 bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1638 return getAttributes(Index).hasAttribute(Kind);
1639 }
1640
hasAttributesAtIndex(unsigned Index) const1641 bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1642 return getAttributes(Index).hasAttributes();
1643 }
1644
hasFnAttr(Attribute::AttrKind Kind) const1645 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1646 return pImpl && pImpl->hasFnAttribute(Kind);
1647 }
1648
hasFnAttr(StringRef Kind) const1649 bool AttributeList::hasFnAttr(StringRef Kind) const {
1650 return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1651 }
1652
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1653 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1654 unsigned *Index) const {
1655 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1656 }
1657
getAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1658 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1659 Attribute::AttrKind Kind) const {
1660 return getAttributes(Index).getAttribute(Kind);
1661 }
1662
getAttributeAtIndex(unsigned Index,StringRef Kind) const1663 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1664 StringRef Kind) const {
1665 return getAttributes(Index).getAttribute(Kind);
1666 }
1667
getRetAlignment() const1668 MaybeAlign AttributeList::getRetAlignment() const {
1669 return getAttributes(ReturnIndex).getAlignment();
1670 }
1671
getParamAlignment(unsigned ArgNo) const1672 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1673 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1674 }
1675
getParamStackAlignment(unsigned ArgNo) const1676 MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1677 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1678 }
1679
getParamByValType(unsigned Index) const1680 Type *AttributeList::getParamByValType(unsigned Index) const {
1681 return getAttributes(Index+FirstArgIndex).getByValType();
1682 }
1683
getParamStructRetType(unsigned Index) const1684 Type *AttributeList::getParamStructRetType(unsigned Index) const {
1685 return getAttributes(Index + FirstArgIndex).getStructRetType();
1686 }
1687
getParamByRefType(unsigned Index) const1688 Type *AttributeList::getParamByRefType(unsigned Index) const {
1689 return getAttributes(Index + FirstArgIndex).getByRefType();
1690 }
1691
getParamPreallocatedType(unsigned Index) const1692 Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1693 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1694 }
1695
getParamInAllocaType(unsigned Index) const1696 Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1697 return getAttributes(Index + FirstArgIndex).getInAllocaType();
1698 }
1699
getParamElementType(unsigned Index) const1700 Type *AttributeList::getParamElementType(unsigned Index) const {
1701 return getAttributes(Index + FirstArgIndex).getElementType();
1702 }
1703
getFnStackAlignment() const1704 MaybeAlign AttributeList::getFnStackAlignment() const {
1705 return getFnAttrs().getStackAlignment();
1706 }
1707
getRetStackAlignment() const1708 MaybeAlign AttributeList::getRetStackAlignment() const {
1709 return getRetAttrs().getStackAlignment();
1710 }
1711
getRetDereferenceableBytes() const1712 uint64_t AttributeList::getRetDereferenceableBytes() const {
1713 return getRetAttrs().getDereferenceableBytes();
1714 }
1715
getParamDereferenceableBytes(unsigned Index) const1716 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1717 return getParamAttrs(Index).getDereferenceableBytes();
1718 }
1719
getRetDereferenceableOrNullBytes() const1720 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1721 return getRetAttrs().getDereferenceableOrNullBytes();
1722 }
1723
1724 uint64_t
getParamDereferenceableOrNullBytes(unsigned Index) const1725 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1726 return getParamAttrs(Index).getDereferenceableOrNullBytes();
1727 }
1728
getRetNoFPClass() const1729 FPClassTest AttributeList::getRetNoFPClass() const {
1730 return getRetAttrs().getNoFPClass();
1731 }
1732
getParamNoFPClass(unsigned Index) const1733 FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {
1734 return getParamAttrs(Index).getNoFPClass();
1735 }
1736
getUWTableKind() const1737 UWTableKind AttributeList::getUWTableKind() const {
1738 return getFnAttrs().getUWTableKind();
1739 }
1740
getAllocKind() const1741 AllocFnKind AttributeList::getAllocKind() const {
1742 return getFnAttrs().getAllocKind();
1743 }
1744
getMemoryEffects() const1745 MemoryEffects AttributeList::getMemoryEffects() const {
1746 return getFnAttrs().getMemoryEffects();
1747 }
1748
getAsString(unsigned Index,bool InAttrGrp) const1749 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1750 return getAttributes(Index).getAsString(InAttrGrp);
1751 }
1752
getAttributes(unsigned Index) const1753 AttributeSet AttributeList::getAttributes(unsigned Index) const {
1754 Index = attrIdxToArrayIdx(Index);
1755 if (!pImpl || Index >= getNumAttrSets())
1756 return {};
1757 return pImpl->begin()[Index];
1758 }
1759
hasParentContext(LLVMContext & C) const1760 bool AttributeList::hasParentContext(LLVMContext &C) const {
1761 assert(!isEmpty() && "an empty attribute list has no parent context");
1762 FoldingSetNodeID ID;
1763 pImpl->Profile(ID);
1764 void *Unused;
1765 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1766 }
1767
begin() const1768 AttributeList::iterator AttributeList::begin() const {
1769 return pImpl ? pImpl->begin() : nullptr;
1770 }
1771
end() const1772 AttributeList::iterator AttributeList::end() const {
1773 return pImpl ? pImpl->end() : nullptr;
1774 }
1775
1776 //===----------------------------------------------------------------------===//
1777 // AttributeList Introspection Methods
1778 //===----------------------------------------------------------------------===//
1779
getNumAttrSets() const1780 unsigned AttributeList::getNumAttrSets() const {
1781 return pImpl ? pImpl->NumAttrSets : 0;
1782 }
1783
print(raw_ostream & O) const1784 void AttributeList::print(raw_ostream &O) const {
1785 O << "AttributeList[\n";
1786
1787 for (unsigned i : indexes()) {
1788 if (!getAttributes(i).hasAttributes())
1789 continue;
1790 O << " { ";
1791 switch (i) {
1792 case AttrIndex::ReturnIndex:
1793 O << "return";
1794 break;
1795 case AttrIndex::FunctionIndex:
1796 O << "function";
1797 break;
1798 default:
1799 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1800 }
1801 O << " => " << getAsString(i) << " }\n";
1802 }
1803
1804 O << "]\n";
1805 }
1806
1807 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1808 LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
1809 #endif
1810
1811 //===----------------------------------------------------------------------===//
1812 // AttrBuilder Method Implementations
1813 //===----------------------------------------------------------------------===//
1814
AttrBuilder(LLVMContext & Ctx,AttributeSet AS)1815 AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
1816 append_range(Attrs, AS);
1817 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
1818 }
1819
clear()1820 void AttrBuilder::clear() { Attrs.clear(); }
1821
1822 /// Attribute comparator that only compares attribute keys. Enum attributes are
1823 /// sorted before string attributes.
1824 struct AttributeComparator {
operator ()AttributeComparator1825 bool operator()(Attribute A0, Attribute A1) const {
1826 bool A0IsString = A0.isStringAttribute();
1827 bool A1IsString = A1.isStringAttribute();
1828 if (A0IsString) {
1829 if (A1IsString)
1830 return A0.getKindAsString() < A1.getKindAsString();
1831 else
1832 return false;
1833 }
1834 if (A1IsString)
1835 return true;
1836 return A0.getKindAsEnum() < A1.getKindAsEnum();
1837 }
operator ()AttributeComparator1838 bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
1839 if (A0.isStringAttribute())
1840 return false;
1841 return A0.getKindAsEnum() < Kind;
1842 }
operator ()AttributeComparator1843 bool operator()(Attribute A0, StringRef Kind) const {
1844 if (A0.isStringAttribute())
1845 return A0.getKindAsString() < Kind;
1846 return true;
1847 }
1848 };
1849
1850 template <typename K>
addAttributeImpl(SmallVectorImpl<Attribute> & Attrs,K Kind,Attribute Attr)1851 static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
1852 Attribute Attr) {
1853 auto It = lower_bound(Attrs, Kind, AttributeComparator());
1854 if (It != Attrs.end() && It->hasAttribute(Kind))
1855 std::swap(*It, Attr);
1856 else
1857 Attrs.insert(It, Attr);
1858 }
1859
addAttribute(Attribute Attr)1860 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1861 if (Attr.isStringAttribute())
1862 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1863 else
1864 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
1865 return *this;
1866 }
1867
addAttribute(Attribute::AttrKind Kind)1868 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
1869 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
1870 return *this;
1871 }
1872
addAttribute(StringRef A,StringRef V)1873 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1874 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
1875 return *this;
1876 }
1877
removeAttribute(Attribute::AttrKind Val)1878 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1879 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1880 auto It = lower_bound(Attrs, Val, AttributeComparator());
1881 if (It != Attrs.end() && It->hasAttribute(Val))
1882 Attrs.erase(It);
1883 return *this;
1884 }
1885
removeAttribute(StringRef A)1886 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1887 auto It = lower_bound(Attrs, A, AttributeComparator());
1888 if (It != Attrs.end() && It->hasAttribute(A))
1889 Attrs.erase(It);
1890 return *this;
1891 }
1892
1893 std::optional<uint64_t>
getRawIntAttr(Attribute::AttrKind Kind) const1894 AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
1895 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
1896 Attribute A = getAttribute(Kind);
1897 if (A.isValid())
1898 return A.getValueAsInt();
1899 return std::nullopt;
1900 }
1901
addRawIntAttr(Attribute::AttrKind Kind,uint64_t Value)1902 AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
1903 uint64_t Value) {
1904 return addAttribute(Attribute::get(Ctx, Kind, Value));
1905 }
1906
1907 std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1908 AttrBuilder::getAllocSizeArgs() const {
1909 Attribute A = getAttribute(Attribute::AllocSize);
1910 if (A.isValid())
1911 return A.getAllocSizeArgs();
1912 return std::nullopt;
1913 }
1914
addAlignmentAttr(MaybeAlign Align)1915 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1916 if (!Align)
1917 return *this;
1918
1919 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1920 return addRawIntAttr(Attribute::Alignment, Align->value());
1921 }
1922
addStackAlignmentAttr(MaybeAlign Align)1923 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1924 // Default alignment, allow the target to define how to align it.
1925 if (!Align)
1926 return *this;
1927
1928 assert(*Align <= 0x100 && "Alignment too large.");
1929 return addRawIntAttr(Attribute::StackAlignment, Align->value());
1930 }
1931
addDereferenceableAttr(uint64_t Bytes)1932 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1933 if (Bytes == 0) return *this;
1934
1935 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
1936 }
1937
addDereferenceableOrNullAttr(uint64_t Bytes)1938 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1939 if (Bytes == 0)
1940 return *this;
1941
1942 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
1943 }
1944
1945 AttrBuilder &
addAllocSizeAttr(unsigned ElemSize,const std::optional<unsigned> & NumElems)1946 AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1947 const std::optional<unsigned> &NumElems) {
1948 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1949 }
1950
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1951 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1952 // (0, 0) is our "not present" value, so we need to check for it here.
1953 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1954 return addRawIntAttr(Attribute::AllocSize, RawArgs);
1955 }
1956
addVScaleRangeAttr(unsigned MinValue,std::optional<unsigned> MaxValue)1957 AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
1958 std::optional<unsigned> MaxValue) {
1959 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
1960 }
1961
addVScaleRangeAttrFromRawRepr(uint64_t RawArgs)1962 AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
1963 // (0, 0) is not present hence ignore this case
1964 if (RawArgs == 0)
1965 return *this;
1966
1967 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1968 }
1969
addUWTableAttr(UWTableKind Kind)1970 AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
1971 if (Kind == UWTableKind::None)
1972 return *this;
1973 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
1974 }
1975
addMemoryAttr(MemoryEffects ME)1976 AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
1977 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
1978 }
1979
addNoFPClassAttr(FPClassTest Mask)1980 AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
1981 if (Mask == fcNone)
1982 return *this;
1983
1984 return addRawIntAttr(Attribute::NoFPClass, Mask);
1985 }
1986
addAllocKindAttr(AllocFnKind Kind)1987 AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
1988 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
1989 }
1990
getTypeAttr(Attribute::AttrKind Kind) const1991 Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
1992 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
1993 Attribute A = getAttribute(Kind);
1994 return A.isValid() ? A.getValueAsType() : nullptr;
1995 }
1996
addTypeAttr(Attribute::AttrKind Kind,Type * Ty)1997 AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
1998 return addAttribute(Attribute::get(Ctx, Kind, Ty));
1999 }
2000
addByValAttr(Type * Ty)2001 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
2002 return addTypeAttr(Attribute::ByVal, Ty);
2003 }
2004
addStructRetAttr(Type * Ty)2005 AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
2006 return addTypeAttr(Attribute::StructRet, Ty);
2007 }
2008
addByRefAttr(Type * Ty)2009 AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
2010 return addTypeAttr(Attribute::ByRef, Ty);
2011 }
2012
addPreallocatedAttr(Type * Ty)2013 AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
2014 return addTypeAttr(Attribute::Preallocated, Ty);
2015 }
2016
addInAllocaAttr(Type * Ty)2017 AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
2018 return addTypeAttr(Attribute::InAlloca, Ty);
2019 }
2020
addConstantRangeAttr(Attribute::AttrKind Kind,const ConstantRange & CR)2021 AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,
2022 const ConstantRange &CR) {
2023 return addAttribute(Attribute::get(Ctx, Kind, CR));
2024 }
2025
addRangeAttr(const ConstantRange & CR)2026 AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
2027 return addConstantRangeAttr(Attribute::Range, CR);
2028 }
2029
2030 AttrBuilder &
addConstantRangeListAttr(Attribute::AttrKind Kind,ArrayRef<ConstantRange> Val)2031 AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
2032 ArrayRef<ConstantRange> Val) {
2033 return addAttribute(Attribute::get(Ctx, Kind, Val));
2034 }
2035
addInitializesAttr(const ConstantRangeList & CRL)2036 AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
2037 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2038 }
2039
merge(const AttrBuilder & B)2040 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
2041 // TODO: Could make this O(n) as we're merging two sorted lists.
2042 for (const auto &I : B.attrs())
2043 addAttribute(I);
2044
2045 return *this;
2046 }
2047
remove(const AttributeMask & AM)2048 AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
2049 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2050 return *this;
2051 }
2052
overlaps(const AttributeMask & AM) const2053 bool AttrBuilder::overlaps(const AttributeMask &AM) const {
2054 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2055 }
2056
getAttribute(Attribute::AttrKind A) const2057 Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
2058 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2059 auto It = lower_bound(Attrs, A, AttributeComparator());
2060 if (It != Attrs.end() && It->hasAttribute(A))
2061 return *It;
2062 return {};
2063 }
2064
getAttribute(StringRef A) const2065 Attribute AttrBuilder::getAttribute(StringRef A) const {
2066 auto It = lower_bound(Attrs, A, AttributeComparator());
2067 if (It != Attrs.end() && It->hasAttribute(A))
2068 return *It;
2069 return {};
2070 }
2071
contains(Attribute::AttrKind A) const2072 bool AttrBuilder::contains(Attribute::AttrKind A) const {
2073 return getAttribute(A).isValid();
2074 }
2075
contains(StringRef A) const2076 bool AttrBuilder::contains(StringRef A) const {
2077 return getAttribute(A).isValid();
2078 }
2079
operator ==(const AttrBuilder & B) const2080 bool AttrBuilder::operator==(const AttrBuilder &B) const {
2081 return Attrs == B.Attrs;
2082 }
2083
2084 //===----------------------------------------------------------------------===//
2085 // AttributeFuncs Function Defintions
2086 //===----------------------------------------------------------------------===//
2087
2088 /// Returns true if this is a type legal for the 'nofpclass' attribute. This
2089 /// follows the same type rules as FPMathOperator.
2090 ///
2091 /// TODO: Consider relaxing to any FP type struct fields.
isNoFPClassCompatibleType(Type * Ty)2092 bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2093 while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
2094 Ty = ArrTy->getElementType();
2095 return Ty->isFPOrFPVectorTy();
2096 }
2097
2098 /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty,AttributeSafetyKind ASK)2099 AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
2100 AttributeSafetyKind ASK) {
2101 AttributeMask Incompatible;
2102
2103 if (!Ty->isIntegerTy()) {
2104 // Attributes that only apply to integers.
2105 if (ASK & ASK_SAFE_TO_DROP)
2106 Incompatible.addAttribute(Attribute::AllocAlign);
2107 if (ASK & ASK_UNSAFE_TO_DROP)
2108 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2109 }
2110
2111 if (!Ty->isIntOrIntVectorTy()) {
2112 // Attributes that only apply to integers or vector of integers.
2113 if (ASK & ASK_SAFE_TO_DROP)
2114 Incompatible.addAttribute(Attribute::Range);
2115 }
2116
2117 if (!Ty->isPointerTy()) {
2118 // Attributes that only apply to pointers.
2119 if (ASK & ASK_SAFE_TO_DROP)
2120 Incompatible.addAttribute(Attribute::NoAlias)
2121 .addAttribute(Attribute::NoCapture)
2122 .addAttribute(Attribute::NonNull)
2123 .addAttribute(Attribute::ReadNone)
2124 .addAttribute(Attribute::ReadOnly)
2125 .addAttribute(Attribute::Dereferenceable)
2126 .addAttribute(Attribute::DereferenceableOrNull)
2127 .addAttribute(Attribute::Writable)
2128 .addAttribute(Attribute::DeadOnUnwind)
2129 .addAttribute(Attribute::Initializes);
2130 if (ASK & ASK_UNSAFE_TO_DROP)
2131 Incompatible.addAttribute(Attribute::Nest)
2132 .addAttribute(Attribute::SwiftError)
2133 .addAttribute(Attribute::Preallocated)
2134 .addAttribute(Attribute::InAlloca)
2135 .addAttribute(Attribute::ByVal)
2136 .addAttribute(Attribute::StructRet)
2137 .addAttribute(Attribute::ByRef)
2138 .addAttribute(Attribute::ElementType)
2139 .addAttribute(Attribute::AllocatedPointer);
2140 }
2141
2142 // Attributes that only apply to pointers or vectors of pointers.
2143 if (!Ty->isPtrOrPtrVectorTy()) {
2144 if (ASK & ASK_SAFE_TO_DROP)
2145 Incompatible.addAttribute(Attribute::Alignment);
2146 }
2147
2148 if (ASK & ASK_SAFE_TO_DROP) {
2149 if (!isNoFPClassCompatibleType(Ty))
2150 Incompatible.addAttribute(Attribute::NoFPClass);
2151 }
2152
2153 // Some attributes can apply to all "values" but there are no `void` values.
2154 if (Ty->isVoidTy()) {
2155 if (ASK & ASK_SAFE_TO_DROP)
2156 Incompatible.addAttribute(Attribute::NoUndef);
2157 }
2158
2159 return Incompatible;
2160 }
2161
getUBImplyingAttributes()2162 AttributeMask AttributeFuncs::getUBImplyingAttributes() {
2163 AttributeMask AM;
2164 AM.addAttribute(Attribute::NoUndef);
2165 AM.addAttribute(Attribute::Dereferenceable);
2166 AM.addAttribute(Attribute::DereferenceableOrNull);
2167 return AM;
2168 }
2169
2170 /// Callees with dynamic denormal modes are compatible with any caller mode.
denormModeCompatible(DenormalMode CallerMode,DenormalMode CalleeMode)2171 static bool denormModeCompatible(DenormalMode CallerMode,
2172 DenormalMode CalleeMode) {
2173 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2174 return true;
2175
2176 // If they don't exactly match, it's OK if the mismatched component is
2177 // dynamic.
2178 if (CalleeMode.Input == CallerMode.Input &&
2179 CalleeMode.Output == DenormalMode::Dynamic)
2180 return true;
2181
2182 if (CalleeMode.Output == CallerMode.Output &&
2183 CalleeMode.Input == DenormalMode::Dynamic)
2184 return true;
2185 return false;
2186 }
2187
checkDenormMode(const Function & Caller,const Function & Callee)2188 static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2189 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2190 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2191
2192 if (denormModeCompatible(CallerMode, CalleeMode)) {
2193 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2194 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2195 if (CallerModeF32 == DenormalMode::getInvalid())
2196 CallerModeF32 = CallerMode;
2197 if (CalleeModeF32 == DenormalMode::getInvalid())
2198 CalleeModeF32 = CalleeMode;
2199 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2200 }
2201
2202 return false;
2203 }
2204
checkStrictFP(const Function & Caller,const Function & Callee)2205 static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2206 // Do not inline strictfp function into non-strictfp one. It would require
2207 // conversion of all FP operations in host function to constrained intrinsics.
2208 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2209 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2210 }
2211
2212 template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)2213 static bool isEqual(const Function &Caller, const Function &Callee) {
2214 return Caller.getFnAttribute(AttrClass::getKind()) ==
2215 Callee.getFnAttribute(AttrClass::getKind());
2216 }
2217
isEqual(const Function & Caller,const Function & Callee,const StringRef & AttrName)2218 static bool isEqual(const Function &Caller, const Function &Callee,
2219 const StringRef &AttrName) {
2220 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2221 }
2222
2223 /// Compute the logical AND of the attributes of the caller and the
2224 /// callee.
2225 ///
2226 /// This function sets the caller's attribute to false if the callee's attribute
2227 /// is false.
2228 template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)2229 static void setAND(Function &Caller, const Function &Callee) {
2230 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2231 !AttrClass::isSet(Callee, AttrClass::getKind()))
2232 AttrClass::set(Caller, AttrClass::getKind(), false);
2233 }
2234
2235 /// Compute the logical OR of the attributes of the caller and the
2236 /// callee.
2237 ///
2238 /// This function sets the caller's attribute to true if the callee's attribute
2239 /// is true.
2240 template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)2241 static void setOR(Function &Caller, const Function &Callee) {
2242 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2243 AttrClass::isSet(Callee, AttrClass::getKind()))
2244 AttrClass::set(Caller, AttrClass::getKind(), true);
2245 }
2246
2247 /// If the inlined function had a higher stack protection level than the
2248 /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)2249 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2250 // If the calling function has *no* stack protection level (e.g. it was built
2251 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2252 // change it as that could change the program's semantics.
2253 if (!Caller.hasStackProtectorFnAttr())
2254 return;
2255
2256 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2257 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2258 // clutter to the IR.
2259 AttributeMask OldSSPAttr;
2260 OldSSPAttr.addAttribute(Attribute::StackProtect)
2261 .addAttribute(Attribute::StackProtectStrong)
2262 .addAttribute(Attribute::StackProtectReq);
2263
2264 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2265 Caller.removeFnAttrs(OldSSPAttr);
2266 Caller.addFnAttr(Attribute::StackProtectReq);
2267 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2268 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2269 Caller.removeFnAttrs(OldSSPAttr);
2270 Caller.addFnAttr(Attribute::StackProtectStrong);
2271 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2272 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2273 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2274 Caller.addFnAttr(Attribute::StackProtect);
2275 }
2276
2277 /// If the inlined function required stack probes, then ensure that
2278 /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)2279 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2280 if (!Caller.hasFnAttribute("probe-stack") &&
2281 Callee.hasFnAttribute("probe-stack")) {
2282 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2283 }
2284 }
2285
2286 /// If the inlined function defines the size of guard region
2287 /// on the stack, then ensure that the calling function defines a guard region
2288 /// that is no larger.
2289 static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)2290 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
2291 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2292 if (CalleeAttr.isValid()) {
2293 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2294 if (CallerAttr.isValid()) {
2295 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2296 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2297 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2298
2299 if (CallerStackProbeSize > CalleeStackProbeSize) {
2300 Caller.addFnAttr(CalleeAttr);
2301 }
2302 } else {
2303 Caller.addFnAttr(CalleeAttr);
2304 }
2305 }
2306 }
2307
2308 /// If the inlined function defines a min legal vector width, then ensure
2309 /// the calling function has the same or larger min legal vector width. If the
2310 /// caller has the attribute, but the callee doesn't, we need to remove the
2311 /// attribute from the caller since we can't make any guarantees about the
2312 /// caller's requirements.
2313 /// This function is called after the inlining decision has been made so we have
2314 /// to merge the attribute this way. Heuristics that would use
2315 /// min-legal-vector-width to determine inline compatibility would need to be
2316 /// handled as part of inline cost analysis.
2317 static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)2318 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
2319 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2320 if (CallerAttr.isValid()) {
2321 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2322 if (CalleeAttr.isValid()) {
2323 uint64_t CallerVectorWidth, CalleeVectorWidth;
2324 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2325 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2326 if (CallerVectorWidth < CalleeVectorWidth)
2327 Caller.addFnAttr(CalleeAttr);
2328 } else {
2329 // If the callee doesn't have the attribute then we don't know anything
2330 // and must drop the attribute from the caller.
2331 Caller.removeFnAttr("min-legal-vector-width");
2332 }
2333 }
2334 }
2335
2336 /// If the inlined function has null_pointer_is_valid attribute,
2337 /// set this attribute in the caller post inlining.
2338 static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)2339 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2340 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2341 Caller.addFnAttr(Attribute::NullPointerIsValid);
2342 }
2343 }
2344
2345 struct EnumAttr {
isSetEnumAttr2346 static bool isSet(const Function &Fn,
2347 Attribute::AttrKind Kind) {
2348 return Fn.hasFnAttribute(Kind);
2349 }
2350
setEnumAttr2351 static void set(Function &Fn,
2352 Attribute::AttrKind Kind, bool Val) {
2353 if (Val)
2354 Fn.addFnAttr(Kind);
2355 else
2356 Fn.removeFnAttr(Kind);
2357 }
2358 };
2359
2360 struct StrBoolAttr {
isSetStrBoolAttr2361 static bool isSet(const Function &Fn,
2362 StringRef Kind) {
2363 auto A = Fn.getFnAttribute(Kind);
2364 return A.getValueAsString() == "true";
2365 }
2366
setStrBoolAttr2367 static void set(Function &Fn,
2368 StringRef Kind, bool Val) {
2369 Fn.addFnAttr(Kind, Val ? "true" : "false");
2370 }
2371 };
2372
2373 #define GET_ATTR_NAMES
2374 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2375 struct ENUM_NAME##Attr : EnumAttr { \
2376 static enum Attribute::AttrKind getKind() { \
2377 return llvm::Attribute::ENUM_NAME; \
2378 } \
2379 };
2380 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2381 struct ENUM_NAME##Attr : StrBoolAttr { \
2382 static StringRef getKind() { return #DISPLAY_NAME; } \
2383 };
2384 #include "llvm/IR/Attributes.inc"
2385
2386 #define GET_ATTR_COMPAT_FUNC
2387 #include "llvm/IR/Attributes.inc"
2388
areInlineCompatible(const Function & Caller,const Function & Callee)2389 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2390 const Function &Callee) {
2391 return hasCompatibleFnAttrs(Caller, Callee);
2392 }
2393
areOutlineCompatible(const Function & A,const Function & B)2394 bool AttributeFuncs::areOutlineCompatible(const Function &A,
2395 const Function &B) {
2396 return hasCompatibleFnAttrs(A, B);
2397 }
2398
mergeAttributesForInlining(Function & Caller,const Function & Callee)2399 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2400 const Function &Callee) {
2401 mergeFnAttrs(Caller, Callee);
2402 }
2403
mergeAttributesForOutlining(Function & Base,const Function & ToMerge)2404 void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2405 const Function &ToMerge) {
2406
2407 // We merge functions so that they meet the most general case.
2408 // For example, if the NoNansFPMathAttr is set in one function, but not in
2409 // the other, in the merged function we can say that the NoNansFPMathAttr
2410 // is not set.
2411 // However if we have the SpeculativeLoadHardeningAttr set true in one
2412 // function, but not the other, we make sure that the function retains
2413 // that aspect in the merged function.
2414 mergeFnAttrs(Base, ToMerge);
2415 }
2416
updateMinLegalVectorWidthAttr(Function & Fn,uint64_t Width)2417 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2418 uint64_t Width) {
2419 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2420 if (Attr.isValid()) {
2421 uint64_t OldWidth;
2422 Attr.getValueAsString().getAsInteger(0, OldWidth);
2423 if (Width > OldWidth)
2424 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2425 }
2426 }
2427