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/Optional.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/StringExtras.h"
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/Config/llvm-config.h"
27 #include "llvm/IR/Function.h"
28 #include "llvm/IR/LLVMContext.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include <algorithm>
34 #include <cassert>
35 #include <cstddef>
36 #include <cstdint>
37 #include <limits>
38 #include <string>
39 #include <tuple>
40 #include <utility>
41
42 using namespace llvm;
43
44 //===----------------------------------------------------------------------===//
45 // Attribute Construction Methods
46 //===----------------------------------------------------------------------===//
47
48 // allocsize has two integer arguments, but because they're both 32 bits, we can
49 // pack them into one 64-bit value, at the cost of making said value
50 // nonsensical.
51 //
52 // In order to do this, we need to reserve one value of the second (optional)
53 // allocsize argument to signify "not present."
54 static const unsigned AllocSizeNumElemsNotPresent = -1;
55
packAllocSizeArgs(unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)56 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
57 const Optional<unsigned> &NumElemsArg) {
58 assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
59 "Attempting to pack a reserved value");
60
61 return uint64_t(ElemSizeArg) << 32 |
62 NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
63 }
64
65 static std::pair<unsigned, Optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)66 unpackAllocSizeArgs(uint64_t Num) {
67 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
68 unsigned ElemSizeArg = Num >> 32;
69
70 Optional<unsigned> NumElemsArg;
71 if (NumElems != AllocSizeNumElemsNotPresent)
72 NumElemsArg = NumElems;
73 return std::make_pair(ElemSizeArg, NumElemsArg);
74 }
75
packVScaleRangeArgs(unsigned MinValue,Optional<unsigned> MaxValue)76 static uint64_t packVScaleRangeArgs(unsigned MinValue,
77 Optional<unsigned> MaxValue) {
78 return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
79 }
80
81 static std::pair<unsigned, Optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value)82 unpackVScaleRangeArgs(uint64_t Value) {
83 unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
84 unsigned MinValue = Value >> 32;
85
86 return std::make_pair(MinValue,
87 MaxValue > 0 ? MaxValue : Optional<unsigned>());
88 }
89
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)90 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
91 uint64_t Val) {
92 if (Val)
93 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
94 else
95 assert(Attribute::isEnumAttrKind(Kind) && "Not an enum attribute");
96
97 LLVMContextImpl *pImpl = Context.pImpl;
98 FoldingSetNodeID ID;
99 ID.AddInteger(Kind);
100 if (Val) ID.AddInteger(Val);
101
102 void *InsertPoint;
103 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
104
105 if (!PA) {
106 // If we didn't find any existing attributes of the same shape then create a
107 // new one and insert it.
108 if (!Val)
109 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
110 else
111 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
112 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
113 }
114
115 // Return the Attribute that we found or created.
116 return Attribute(PA);
117 }
118
get(LLVMContext & Context,StringRef Kind,StringRef Val)119 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
120 LLVMContextImpl *pImpl = Context.pImpl;
121 FoldingSetNodeID ID;
122 ID.AddString(Kind);
123 if (!Val.empty()) ID.AddString(Val);
124
125 void *InsertPoint;
126 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
127
128 if (!PA) {
129 // If we didn't find any existing attributes of the same shape then create a
130 // new one and insert it.
131 void *Mem =
132 pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
133 alignof(StringAttributeImpl));
134 PA = new (Mem) StringAttributeImpl(Kind, Val);
135 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
136 }
137
138 // Return the Attribute that we found or created.
139 return Attribute(PA);
140 }
141
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)142 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
143 Type *Ty) {
144 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
145 LLVMContextImpl *pImpl = Context.pImpl;
146 FoldingSetNodeID ID;
147 ID.AddInteger(Kind);
148 ID.AddPointer(Ty);
149
150 void *InsertPoint;
151 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
152
153 if (!PA) {
154 // If we didn't find any existing attributes of the same shape then create a
155 // new one and insert it.
156 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
157 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
158 }
159
160 // Return the Attribute that we found or created.
161 return Attribute(PA);
162 }
163
getWithAlignment(LLVMContext & Context,Align A)164 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
165 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
166 return get(Context, Alignment, A.value());
167 }
168
getWithStackAlignment(LLVMContext & Context,Align A)169 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
170 assert(A <= 0x100 && "Alignment too large.");
171 return get(Context, StackAlignment, A.value());
172 }
173
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)174 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
175 uint64_t Bytes) {
176 assert(Bytes && "Bytes must be non-zero.");
177 return get(Context, Dereferenceable, Bytes);
178 }
179
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)180 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
181 uint64_t Bytes) {
182 assert(Bytes && "Bytes must be non-zero.");
183 return get(Context, DereferenceableOrNull, Bytes);
184 }
185
getWithByValType(LLVMContext & Context,Type * Ty)186 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
187 return get(Context, ByVal, Ty);
188 }
189
getWithStructRetType(LLVMContext & Context,Type * Ty)190 Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
191 return get(Context, StructRet, Ty);
192 }
193
getWithByRefType(LLVMContext & Context,Type * Ty)194 Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
195 return get(Context, ByRef, Ty);
196 }
197
getWithPreallocatedType(LLVMContext & Context,Type * Ty)198 Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
199 return get(Context, Preallocated, Ty);
200 }
201
getWithInAllocaType(LLVMContext & Context,Type * Ty)202 Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
203 return get(Context, InAlloca, Ty);
204 }
205
getWithUWTableKind(LLVMContext & Context,UWTableKind Kind)206 Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
207 UWTableKind Kind) {
208 return get(Context, UWTable, uint64_t(Kind));
209 }
210
211 Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)212 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
213 const Optional<unsigned> &NumElemsArg) {
214 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
215 "Invalid allocsize arguments -- given allocsize(0, 0)");
216 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
217 }
218
getWithVScaleRangeArgs(LLVMContext & Context,unsigned MinValue,unsigned MaxValue)219 Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
220 unsigned MinValue,
221 unsigned MaxValue) {
222 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
223 }
224
getAttrKindFromName(StringRef AttrName)225 Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
226 return StringSwitch<Attribute::AttrKind>(AttrName)
227 #define GET_ATTR_NAMES
228 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
229 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
230 #include "llvm/IR/Attributes.inc"
231 .Default(Attribute::None);
232 }
233
getNameFromAttrKind(Attribute::AttrKind AttrKind)234 StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
235 switch (AttrKind) {
236 #define GET_ATTR_NAMES
237 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
238 case Attribute::ENUM_NAME: \
239 return #DISPLAY_NAME;
240 #include "llvm/IR/Attributes.inc"
241 case Attribute::None:
242 return "none";
243 default:
244 llvm_unreachable("invalid Kind");
245 }
246 }
247
isExistingAttribute(StringRef Name)248 bool Attribute::isExistingAttribute(StringRef Name) {
249 return StringSwitch<bool>(Name)
250 #define GET_ATTR_NAMES
251 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
252 #include "llvm/IR/Attributes.inc"
253 .Default(false);
254 }
255
256 //===----------------------------------------------------------------------===//
257 // Attribute Accessor Methods
258 //===----------------------------------------------------------------------===//
259
isEnumAttribute() const260 bool Attribute::isEnumAttribute() const {
261 return pImpl && pImpl->isEnumAttribute();
262 }
263
isIntAttribute() const264 bool Attribute::isIntAttribute() const {
265 return pImpl && pImpl->isIntAttribute();
266 }
267
isStringAttribute() const268 bool Attribute::isStringAttribute() const {
269 return pImpl && pImpl->isStringAttribute();
270 }
271
isTypeAttribute() const272 bool Attribute::isTypeAttribute() const {
273 return pImpl && pImpl->isTypeAttribute();
274 }
275
getKindAsEnum() const276 Attribute::AttrKind Attribute::getKindAsEnum() const {
277 if (!pImpl) return None;
278 assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
279 "Invalid attribute type to get the kind as an enum!");
280 return pImpl->getKindAsEnum();
281 }
282
getValueAsInt() const283 uint64_t Attribute::getValueAsInt() const {
284 if (!pImpl) return 0;
285 assert(isIntAttribute() &&
286 "Expected the attribute to be an integer attribute!");
287 return pImpl->getValueAsInt();
288 }
289
getValueAsBool() const290 bool Attribute::getValueAsBool() const {
291 if (!pImpl) return false;
292 assert(isStringAttribute() &&
293 "Expected the attribute to be a string attribute!");
294 return pImpl->getValueAsBool();
295 }
296
getKindAsString() const297 StringRef Attribute::getKindAsString() const {
298 if (!pImpl) return {};
299 assert(isStringAttribute() &&
300 "Invalid attribute type to get the kind as a string!");
301 return pImpl->getKindAsString();
302 }
303
getValueAsString() const304 StringRef Attribute::getValueAsString() const {
305 if (!pImpl) return {};
306 assert(isStringAttribute() &&
307 "Invalid attribute type to get the value as a string!");
308 return pImpl->getValueAsString();
309 }
310
getValueAsType() const311 Type *Attribute::getValueAsType() const {
312 if (!pImpl) return {};
313 assert(isTypeAttribute() &&
314 "Invalid attribute type to get the value as a type!");
315 return pImpl->getValueAsType();
316 }
317
318
hasAttribute(AttrKind Kind) const319 bool Attribute::hasAttribute(AttrKind Kind) const {
320 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
321 }
322
hasAttribute(StringRef Kind) const323 bool Attribute::hasAttribute(StringRef Kind) const {
324 if (!isStringAttribute()) return false;
325 return pImpl && pImpl->hasAttribute(Kind);
326 }
327
getAlignment() const328 MaybeAlign Attribute::getAlignment() const {
329 assert(hasAttribute(Attribute::Alignment) &&
330 "Trying to get alignment from non-alignment attribute!");
331 return MaybeAlign(pImpl->getValueAsInt());
332 }
333
getStackAlignment() const334 MaybeAlign Attribute::getStackAlignment() const {
335 assert(hasAttribute(Attribute::StackAlignment) &&
336 "Trying to get alignment from non-alignment attribute!");
337 return MaybeAlign(pImpl->getValueAsInt());
338 }
339
getDereferenceableBytes() const340 uint64_t Attribute::getDereferenceableBytes() const {
341 assert(hasAttribute(Attribute::Dereferenceable) &&
342 "Trying to get dereferenceable bytes from "
343 "non-dereferenceable attribute!");
344 return pImpl->getValueAsInt();
345 }
346
getDereferenceableOrNullBytes() const347 uint64_t Attribute::getDereferenceableOrNullBytes() const {
348 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
349 "Trying to get dereferenceable bytes from "
350 "non-dereferenceable attribute!");
351 return pImpl->getValueAsInt();
352 }
353
getAllocSizeArgs() const354 std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
355 assert(hasAttribute(Attribute::AllocSize) &&
356 "Trying to get allocsize args from non-allocsize attribute");
357 return unpackAllocSizeArgs(pImpl->getValueAsInt());
358 }
359
getVScaleRangeMin() const360 unsigned Attribute::getVScaleRangeMin() const {
361 assert(hasAttribute(Attribute::VScaleRange) &&
362 "Trying to get vscale args from non-vscale attribute");
363 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
364 }
365
getVScaleRangeMax() const366 Optional<unsigned> Attribute::getVScaleRangeMax() const {
367 assert(hasAttribute(Attribute::VScaleRange) &&
368 "Trying to get vscale args from non-vscale attribute");
369 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
370 }
371
getUWTableKind() const372 UWTableKind Attribute::getUWTableKind() const {
373 assert(hasAttribute(Attribute::UWTable) &&
374 "Trying to get unwind table kind from non-uwtable attribute");
375 return UWTableKind(pImpl->getValueAsInt());
376 }
377
getAllocKind() const378 AllocFnKind Attribute::getAllocKind() const {
379 assert(hasAttribute(Attribute::AllocKind) &&
380 "Trying to get allockind value from non-allockind attribute");
381 return AllocFnKind(pImpl->getValueAsInt());
382 }
383
getAsString(bool InAttrGrp) const384 std::string Attribute::getAsString(bool InAttrGrp) const {
385 if (!pImpl) return {};
386
387 if (isEnumAttribute())
388 return getNameFromAttrKind(getKindAsEnum()).str();
389
390 if (isTypeAttribute()) {
391 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
392 Result += '(';
393 raw_string_ostream OS(Result);
394 getValueAsType()->print(OS, false, true);
395 OS.flush();
396 Result += ')';
397 return Result;
398 }
399
400 // FIXME: These should be output like this:
401 //
402 // align=4
403 // alignstack=8
404 //
405 if (hasAttribute(Attribute::Alignment))
406 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
407 : "align " + Twine(getValueAsInt()))
408 .str();
409
410 auto AttrWithBytesToString = [&](const char *Name) {
411 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
412 : Name + ("(" + Twine(getValueAsInt())) + ")")
413 .str();
414 };
415
416 if (hasAttribute(Attribute::StackAlignment))
417 return AttrWithBytesToString("alignstack");
418
419 if (hasAttribute(Attribute::Dereferenceable))
420 return AttrWithBytesToString("dereferenceable");
421
422 if (hasAttribute(Attribute::DereferenceableOrNull))
423 return AttrWithBytesToString("dereferenceable_or_null");
424
425 if (hasAttribute(Attribute::AllocSize)) {
426 unsigned ElemSize;
427 Optional<unsigned> NumElems;
428 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
429
430 return (NumElems
431 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
432 : "allocsize(" + Twine(ElemSize) + ")")
433 .str();
434 }
435
436 if (hasAttribute(Attribute::VScaleRange)) {
437 unsigned MinValue = getVScaleRangeMin();
438 Optional<unsigned> MaxValue = getVScaleRangeMax();
439 return ("vscale_range(" + Twine(MinValue) + "," +
440 Twine(MaxValue.value_or(0)) + ")")
441 .str();
442 }
443
444 if (hasAttribute(Attribute::UWTable)) {
445 UWTableKind Kind = getUWTableKind();
446 if (Kind != UWTableKind::None) {
447 return Kind == UWTableKind::Default
448 ? "uwtable"
449 : ("uwtable(" +
450 Twine(Kind == UWTableKind::Sync ? "sync" : "async") + ")")
451 .str();
452 }
453 }
454
455 if (hasAttribute(Attribute::AllocKind)) {
456 AllocFnKind Kind = getAllocKind();
457 SmallVector<StringRef> parts;
458 if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
459 parts.push_back("alloc");
460 if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
461 parts.push_back("realloc");
462 if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
463 parts.push_back("free");
464 if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
465 parts.push_back("uninitialized");
466 if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
467 parts.push_back("zeroed");
468 if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
469 parts.push_back("aligned");
470 return ("allockind(\"" +
471 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
472 .str();
473 }
474
475 // Convert target-dependent attributes to strings of the form:
476 //
477 // "kind"
478 // "kind" = "value"
479 //
480 if (isStringAttribute()) {
481 std::string Result;
482 {
483 raw_string_ostream OS(Result);
484 OS << '"' << getKindAsString() << '"';
485
486 // Since some attribute strings contain special characters that cannot be
487 // printable, those have to be escaped to make the attribute value
488 // printable as is. e.g. "\01__gnu_mcount_nc"
489 const auto &AttrVal = pImpl->getValueAsString();
490 if (!AttrVal.empty()) {
491 OS << "=\"";
492 printEscapedString(AttrVal, OS);
493 OS << "\"";
494 }
495 }
496 return Result;
497 }
498
499 llvm_unreachable("Unknown attribute");
500 }
501
hasParentContext(LLVMContext & C) const502 bool Attribute::hasParentContext(LLVMContext &C) const {
503 assert(isValid() && "invalid Attribute doesn't refer to any context");
504 FoldingSetNodeID ID;
505 pImpl->Profile(ID);
506 void *Unused;
507 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
508 }
509
operator <(Attribute A) const510 bool Attribute::operator<(Attribute A) const {
511 if (!pImpl && !A.pImpl) return false;
512 if (!pImpl) return true;
513 if (!A.pImpl) return false;
514 return *pImpl < *A.pImpl;
515 }
516
Profile(FoldingSetNodeID & ID) const517 void Attribute::Profile(FoldingSetNodeID &ID) const {
518 ID.AddPointer(pImpl);
519 }
520
521 enum AttributeProperty {
522 FnAttr = (1 << 0),
523 ParamAttr = (1 << 1),
524 RetAttr = (1 << 2),
525 };
526
527 #define GET_ATTR_PROP_TABLE
528 #include "llvm/IR/Attributes.inc"
529
hasAttributeProperty(Attribute::AttrKind Kind,AttributeProperty Prop)530 static bool hasAttributeProperty(Attribute::AttrKind Kind,
531 AttributeProperty Prop) {
532 unsigned Index = Kind - 1;
533 assert(Index < sizeof(AttrPropTable) / sizeof(AttrPropTable[0]) &&
534 "Invalid attribute kind");
535 return AttrPropTable[Index] & Prop;
536 }
537
canUseAsFnAttr(AttrKind Kind)538 bool Attribute::canUseAsFnAttr(AttrKind Kind) {
539 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
540 }
541
canUseAsParamAttr(AttrKind Kind)542 bool Attribute::canUseAsParamAttr(AttrKind Kind) {
543 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
544 }
545
canUseAsRetAttr(AttrKind Kind)546 bool Attribute::canUseAsRetAttr(AttrKind Kind) {
547 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
548 }
549
550 //===----------------------------------------------------------------------===//
551 // AttributeImpl Definition
552 //===----------------------------------------------------------------------===//
553
hasAttribute(Attribute::AttrKind A) const554 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
555 if (isStringAttribute()) return false;
556 return getKindAsEnum() == A;
557 }
558
hasAttribute(StringRef Kind) const559 bool AttributeImpl::hasAttribute(StringRef Kind) const {
560 if (!isStringAttribute()) return false;
561 return getKindAsString() == Kind;
562 }
563
getKindAsEnum() const564 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
565 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
566 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
567 }
568
getValueAsInt() const569 uint64_t AttributeImpl::getValueAsInt() const {
570 assert(isIntAttribute());
571 return static_cast<const IntAttributeImpl *>(this)->getValue();
572 }
573
getValueAsBool() const574 bool AttributeImpl::getValueAsBool() const {
575 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
576 return getValueAsString() == "true";
577 }
578
getKindAsString() const579 StringRef AttributeImpl::getKindAsString() const {
580 assert(isStringAttribute());
581 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
582 }
583
getValueAsString() const584 StringRef AttributeImpl::getValueAsString() const {
585 assert(isStringAttribute());
586 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
587 }
588
getValueAsType() const589 Type *AttributeImpl::getValueAsType() const {
590 assert(isTypeAttribute());
591 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
592 }
593
operator <(const AttributeImpl & AI) const594 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
595 if (this == &AI)
596 return false;
597
598 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
599 // relative to their enum value) and then strings.
600 if (!isStringAttribute()) {
601 if (AI.isStringAttribute())
602 return true;
603 if (getKindAsEnum() != AI.getKindAsEnum())
604 return getKindAsEnum() < AI.getKindAsEnum();
605 assert(!AI.isEnumAttribute() && "Non-unique attribute");
606 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
607 // TODO: Is this actually needed?
608 assert(AI.isIntAttribute() && "Only possibility left");
609 return getValueAsInt() < AI.getValueAsInt();
610 }
611
612 if (!AI.isStringAttribute())
613 return false;
614 if (getKindAsString() == AI.getKindAsString())
615 return getValueAsString() < AI.getValueAsString();
616 return getKindAsString() < AI.getKindAsString();
617 }
618
619 //===----------------------------------------------------------------------===//
620 // AttributeSet Definition
621 //===----------------------------------------------------------------------===//
622
get(LLVMContext & C,const AttrBuilder & B)623 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
624 return AttributeSet(AttributeSetNode::get(C, B));
625 }
626
get(LLVMContext & C,ArrayRef<Attribute> Attrs)627 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
628 return AttributeSet(AttributeSetNode::get(C, Attrs));
629 }
630
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const631 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
632 Attribute::AttrKind Kind) const {
633 if (hasAttribute(Kind)) return *this;
634 AttrBuilder B(C);
635 B.addAttribute(Kind);
636 return addAttributes(C, AttributeSet::get(C, B));
637 }
638
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const639 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
640 StringRef Value) const {
641 AttrBuilder B(C);
642 B.addAttribute(Kind, Value);
643 return addAttributes(C, AttributeSet::get(C, B));
644 }
645
addAttributes(LLVMContext & C,const AttributeSet AS) const646 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
647 const AttributeSet AS) const {
648 if (!hasAttributes())
649 return AS;
650
651 if (!AS.hasAttributes())
652 return *this;
653
654 AttrBuilder B(C, *this);
655 B.merge(AttrBuilder(C, AS));
656 return get(C, B);
657 }
658
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const659 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
660 Attribute::AttrKind Kind) const {
661 if (!hasAttribute(Kind)) return *this;
662 AttrBuilder B(C, *this);
663 B.removeAttribute(Kind);
664 return get(C, B);
665 }
666
removeAttribute(LLVMContext & C,StringRef Kind) const667 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
668 StringRef Kind) const {
669 if (!hasAttribute(Kind)) return *this;
670 AttrBuilder B(C, *this);
671 B.removeAttribute(Kind);
672 return get(C, B);
673 }
674
removeAttributes(LLVMContext & C,const AttributeMask & Attrs) const675 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
676 const AttributeMask &Attrs) const {
677 AttrBuilder B(C, *this);
678 // If there is nothing to remove, directly return the original set.
679 if (!B.overlaps(Attrs))
680 return *this;
681
682 B.remove(Attrs);
683 return get(C, B);
684 }
685
getNumAttributes() const686 unsigned AttributeSet::getNumAttributes() const {
687 return SetNode ? SetNode->getNumAttributes() : 0;
688 }
689
hasAttribute(Attribute::AttrKind Kind) const690 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
691 return SetNode ? SetNode->hasAttribute(Kind) : false;
692 }
693
hasAttribute(StringRef Kind) const694 bool AttributeSet::hasAttribute(StringRef Kind) const {
695 return SetNode ? SetNode->hasAttribute(Kind) : false;
696 }
697
getAttribute(Attribute::AttrKind Kind) const698 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
699 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
700 }
701
getAttribute(StringRef Kind) const702 Attribute AttributeSet::getAttribute(StringRef Kind) const {
703 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
704 }
705
getAlignment() const706 MaybeAlign AttributeSet::getAlignment() const {
707 return SetNode ? SetNode->getAlignment() : None;
708 }
709
getStackAlignment() const710 MaybeAlign AttributeSet::getStackAlignment() const {
711 return SetNode ? SetNode->getStackAlignment() : None;
712 }
713
getDereferenceableBytes() const714 uint64_t AttributeSet::getDereferenceableBytes() const {
715 return SetNode ? SetNode->getDereferenceableBytes() : 0;
716 }
717
getDereferenceableOrNullBytes() const718 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
719 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
720 }
721
getByRefType() const722 Type *AttributeSet::getByRefType() const {
723 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
724 }
725
getByValType() const726 Type *AttributeSet::getByValType() const {
727 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
728 }
729
getStructRetType() const730 Type *AttributeSet::getStructRetType() const {
731 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
732 }
733
getPreallocatedType() const734 Type *AttributeSet::getPreallocatedType() const {
735 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
736 }
737
getInAllocaType() const738 Type *AttributeSet::getInAllocaType() const {
739 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
740 }
741
getElementType() const742 Type *AttributeSet::getElementType() const {
743 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
744 }
745
getAllocSizeArgs() const746 std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
747 return SetNode ? SetNode->getAllocSizeArgs()
748 : std::pair<unsigned, Optional<unsigned>>(0, 0);
749 }
750
getVScaleRangeMin() const751 unsigned AttributeSet::getVScaleRangeMin() const {
752 return SetNode ? SetNode->getVScaleRangeMin() : 1;
753 }
754
getVScaleRangeMax() const755 Optional<unsigned> AttributeSet::getVScaleRangeMax() const {
756 return SetNode ? SetNode->getVScaleRangeMax() : None;
757 }
758
getUWTableKind() const759 UWTableKind AttributeSet::getUWTableKind() const {
760 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
761 }
762
getAllocKind() const763 AllocFnKind AttributeSet::getAllocKind() const {
764 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
765 }
766
getAsString(bool InAttrGrp) const767 std::string AttributeSet::getAsString(bool InAttrGrp) const {
768 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
769 }
770
hasParentContext(LLVMContext & C) const771 bool AttributeSet::hasParentContext(LLVMContext &C) const {
772 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
773 FoldingSetNodeID ID;
774 SetNode->Profile(ID);
775 void *Unused;
776 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
777 }
778
begin() const779 AttributeSet::iterator AttributeSet::begin() const {
780 return SetNode ? SetNode->begin() : nullptr;
781 }
782
end() const783 AttributeSet::iterator AttributeSet::end() const {
784 return SetNode ? SetNode->end() : nullptr;
785 }
786
787 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const788 LLVM_DUMP_METHOD void AttributeSet::dump() const {
789 dbgs() << "AS =\n";
790 dbgs() << " { ";
791 dbgs() << getAsString(true) << " }\n";
792 }
793 #endif
794
795 //===----------------------------------------------------------------------===//
796 // AttributeSetNode Definition
797 //===----------------------------------------------------------------------===//
798
AttributeSetNode(ArrayRef<Attribute> Attrs)799 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
800 : NumAttrs(Attrs.size()) {
801 // There's memory after the node where we can store the entries in.
802 llvm::copy(Attrs, getTrailingObjects<Attribute>());
803
804 for (const auto &I : *this) {
805 if (I.isStringAttribute())
806 StringAttrs.insert({ I.getKindAsString(), I });
807 else
808 AvailableAttrs.addAttribute(I.getKindAsEnum());
809 }
810 }
811
get(LLVMContext & C,ArrayRef<Attribute> Attrs)812 AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
813 ArrayRef<Attribute> Attrs) {
814 SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
815 llvm::sort(SortedAttrs);
816 return getSorted(C, SortedAttrs);
817 }
818
getSorted(LLVMContext & C,ArrayRef<Attribute> SortedAttrs)819 AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
820 ArrayRef<Attribute> SortedAttrs) {
821 if (SortedAttrs.empty())
822 return nullptr;
823
824 // Build a key to look up the existing attributes.
825 LLVMContextImpl *pImpl = C.pImpl;
826 FoldingSetNodeID ID;
827
828 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
829 for (const auto &Attr : SortedAttrs)
830 Attr.Profile(ID);
831
832 void *InsertPoint;
833 AttributeSetNode *PA =
834 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
835
836 // If we didn't find any existing attributes of the same shape then create a
837 // new one and insert it.
838 if (!PA) {
839 // Coallocate entries after the AttributeSetNode itself.
840 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
841 PA = new (Mem) AttributeSetNode(SortedAttrs);
842 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
843 }
844
845 // Return the AttributeSetNode that we found or created.
846 return PA;
847 }
848
get(LLVMContext & C,const AttrBuilder & B)849 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
850 return getSorted(C, B.attrs());
851 }
852
hasAttribute(StringRef Kind) const853 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
854 return StringAttrs.count(Kind);
855 }
856
857 Optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const858 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
859 // Do a quick presence check.
860 if (!hasAttribute(Kind))
861 return None;
862
863 // Attributes in a set are sorted by enum value, followed by string
864 // attributes. Binary search the one we want.
865 const Attribute *I =
866 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
867 [](Attribute A, Attribute::AttrKind Kind) {
868 return A.getKindAsEnum() < Kind;
869 });
870 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
871 return *I;
872 }
873
getAttribute(Attribute::AttrKind Kind) const874 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
875 if (auto A = findEnumAttribute(Kind))
876 return *A;
877 return {};
878 }
879
getAttribute(StringRef Kind) const880 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
881 return StringAttrs.lookup(Kind);
882 }
883
getAlignment() const884 MaybeAlign AttributeSetNode::getAlignment() const {
885 if (auto A = findEnumAttribute(Attribute::Alignment))
886 return A->getAlignment();
887 return None;
888 }
889
getStackAlignment() const890 MaybeAlign AttributeSetNode::getStackAlignment() const {
891 if (auto A = findEnumAttribute(Attribute::StackAlignment))
892 return A->getStackAlignment();
893 return None;
894 }
895
getAttributeType(Attribute::AttrKind Kind) const896 Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
897 if (auto A = findEnumAttribute(Kind))
898 return A->getValueAsType();
899 return nullptr;
900 }
901
getDereferenceableBytes() const902 uint64_t AttributeSetNode::getDereferenceableBytes() const {
903 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
904 return A->getDereferenceableBytes();
905 return 0;
906 }
907
getDereferenceableOrNullBytes() const908 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
909 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
910 return A->getDereferenceableOrNullBytes();
911 return 0;
912 }
913
914 std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs() const915 AttributeSetNode::getAllocSizeArgs() const {
916 if (auto A = findEnumAttribute(Attribute::AllocSize))
917 return A->getAllocSizeArgs();
918 return std::make_pair(0, 0);
919 }
920
getVScaleRangeMin() const921 unsigned AttributeSetNode::getVScaleRangeMin() const {
922 if (auto A = findEnumAttribute(Attribute::VScaleRange))
923 return A->getVScaleRangeMin();
924 return 1;
925 }
926
getVScaleRangeMax() const927 Optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
928 if (auto A = findEnumAttribute(Attribute::VScaleRange))
929 return A->getVScaleRangeMax();
930 return None;
931 }
932
getUWTableKind() const933 UWTableKind AttributeSetNode::getUWTableKind() const {
934 if (auto A = findEnumAttribute(Attribute::UWTable))
935 return A->getUWTableKind();
936 return UWTableKind::None;
937 }
938
getAllocKind() const939 AllocFnKind AttributeSetNode::getAllocKind() const {
940 if (auto A = findEnumAttribute(Attribute::AllocKind))
941 return A->getAllocKind();
942 return AllocFnKind::Unknown;
943 }
944
getAsString(bool InAttrGrp) const945 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
946 std::string Str;
947 for (iterator I = begin(), E = end(); I != E; ++I) {
948 if (I != begin())
949 Str += ' ';
950 Str += I->getAsString(InAttrGrp);
951 }
952 return Str;
953 }
954
955 //===----------------------------------------------------------------------===//
956 // AttributeListImpl Definition
957 //===----------------------------------------------------------------------===//
958
959 /// Map from AttributeList index to the internal array index. Adding one happens
960 /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)961 static unsigned attrIdxToArrayIdx(unsigned Index) {
962 return Index + 1;
963 }
964
AttributeListImpl(ArrayRef<AttributeSet> Sets)965 AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
966 : NumAttrSets(Sets.size()) {
967 assert(!Sets.empty() && "pointless AttributeListImpl");
968
969 // There's memory after the node where we can store the entries in.
970 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
971
972 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
973 // summary bitsets.
974 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
975 if (!I.isStringAttribute())
976 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
977
978 for (const auto &Set : Sets)
979 for (const auto &I : Set)
980 if (!I.isStringAttribute())
981 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
982 }
983
Profile(FoldingSetNodeID & ID) const984 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
985 Profile(ID, makeArrayRef(begin(), end()));
986 }
987
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)988 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
989 ArrayRef<AttributeSet> Sets) {
990 for (const auto &Set : Sets)
991 ID.AddPointer(Set.SetNode);
992 }
993
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const994 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
995 unsigned *Index) const {
996 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
997 return false;
998
999 if (Index) {
1000 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1001 if (begin()[I].hasAttribute(Kind)) {
1002 *Index = I - 1;
1003 break;
1004 }
1005 }
1006 }
1007
1008 return true;
1009 }
1010
1011
1012 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1013 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1014 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1015 }
1016 #endif
1017
1018 //===----------------------------------------------------------------------===//
1019 // AttributeList Construction and Mutation Methods
1020 //===----------------------------------------------------------------------===//
1021
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)1022 AttributeList AttributeList::getImpl(LLVMContext &C,
1023 ArrayRef<AttributeSet> AttrSets) {
1024 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1025
1026 LLVMContextImpl *pImpl = C.pImpl;
1027 FoldingSetNodeID ID;
1028 AttributeListImpl::Profile(ID, AttrSets);
1029
1030 void *InsertPoint;
1031 AttributeListImpl *PA =
1032 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1033
1034 // If we didn't find any existing attributes of the same shape then
1035 // create a new one and insert it.
1036 if (!PA) {
1037 // Coallocate entries after the AttributeListImpl itself.
1038 void *Mem = pImpl->Alloc.Allocate(
1039 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1040 alignof(AttributeListImpl));
1041 PA = new (Mem) AttributeListImpl(AttrSets);
1042 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1043 }
1044
1045 // Return the AttributesList that we found or created.
1046 return AttributeList(PA);
1047 }
1048
1049 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)1050 AttributeList::get(LLVMContext &C,
1051 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1052 // If there are no attributes then return a null AttributesList pointer.
1053 if (Attrs.empty())
1054 return {};
1055
1056 assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1057 "Misordered Attributes list!");
1058 assert(llvm::all_of(Attrs,
1059 [](const std::pair<unsigned, Attribute> &Pair) {
1060 return Pair.second.isValid();
1061 }) &&
1062 "Pointless attribute!");
1063
1064 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1065 // list.
1066 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1067 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1068 E = Attrs.end(); I != E; ) {
1069 unsigned Index = I->first;
1070 SmallVector<Attribute, 4> AttrVec;
1071 while (I != E && I->first == Index) {
1072 AttrVec.push_back(I->second);
1073 ++I;
1074 }
1075
1076 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1077 }
1078
1079 return get(C, AttrPairVec);
1080 }
1081
1082 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1083 AttributeList::get(LLVMContext &C,
1084 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1085 // If there are no attributes then return a null AttributesList pointer.
1086 if (Attrs.empty())
1087 return {};
1088
1089 assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1090 "Misordered Attributes list!");
1091 assert(llvm::none_of(Attrs,
1092 [](const std::pair<unsigned, AttributeSet> &Pair) {
1093 return !Pair.second.hasAttributes();
1094 }) &&
1095 "Pointless attribute!");
1096
1097 unsigned MaxIndex = Attrs.back().first;
1098 // If the MaxIndex is FunctionIndex and there are other indices in front
1099 // of it, we need to use the largest of those to get the right size.
1100 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1101 MaxIndex = Attrs[Attrs.size() - 2].first;
1102
1103 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1104 for (const auto &Pair : Attrs)
1105 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1106
1107 return getImpl(C, AttrVec);
1108 }
1109
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)1110 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1111 AttributeSet RetAttrs,
1112 ArrayRef<AttributeSet> ArgAttrs) {
1113 // Scan from the end to find the last argument with attributes. Most
1114 // arguments don't have attributes, so it's nice if we can have fewer unique
1115 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1116 unsigned NumSets = 0;
1117 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1118 if (ArgAttrs[I - 1].hasAttributes()) {
1119 NumSets = I + 2;
1120 break;
1121 }
1122 }
1123 if (NumSets == 0) {
1124 // Check function and return attributes if we didn't have argument
1125 // attributes.
1126 if (RetAttrs.hasAttributes())
1127 NumSets = 2;
1128 else if (FnAttrs.hasAttributes())
1129 NumSets = 1;
1130 }
1131
1132 // If all attribute sets were empty, we can use the empty attribute list.
1133 if (NumSets == 0)
1134 return {};
1135
1136 SmallVector<AttributeSet, 8> AttrSets;
1137 AttrSets.reserve(NumSets);
1138 // If we have any attributes, we always have function attributes.
1139 AttrSets.push_back(FnAttrs);
1140 if (NumSets > 1)
1141 AttrSets.push_back(RetAttrs);
1142 if (NumSets > 2) {
1143 // Drop the empty argument attribute sets at the end.
1144 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1145 llvm::append_range(AttrSets, ArgAttrs);
1146 }
1147
1148 return getImpl(C, AttrSets);
1149 }
1150
get(LLVMContext & C,unsigned Index,AttributeSet Attrs)1151 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1152 AttributeSet Attrs) {
1153 if (!Attrs.hasAttributes())
1154 return {};
1155 Index = attrIdxToArrayIdx(Index);
1156 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1157 AttrSets[Index] = Attrs;
1158 return getImpl(C, AttrSets);
1159 }
1160
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1161 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1162 const AttrBuilder &B) {
1163 return get(C, Index, AttributeSet::get(C, B));
1164 }
1165
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1166 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1167 ArrayRef<Attribute::AttrKind> Kinds) {
1168 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1169 for (const auto K : Kinds)
1170 Attrs.emplace_back(Index, Attribute::get(C, K));
1171 return get(C, Attrs);
1172 }
1173
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)1174 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1175 ArrayRef<Attribute::AttrKind> Kinds,
1176 ArrayRef<uint64_t> Values) {
1177 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1178 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1179 auto VI = Values.begin();
1180 for (const auto K : Kinds)
1181 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1182 return get(C, Attrs);
1183 }
1184
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1185 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1186 ArrayRef<StringRef> Kinds) {
1187 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1188 for (const auto &K : Kinds)
1189 Attrs.emplace_back(Index, Attribute::get(C, K));
1190 return get(C, Attrs);
1191 }
1192
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1193 AttributeList AttributeList::get(LLVMContext &C,
1194 ArrayRef<AttributeList> Attrs) {
1195 if (Attrs.empty())
1196 return {};
1197 if (Attrs.size() == 1)
1198 return Attrs[0];
1199
1200 unsigned MaxSize = 0;
1201 for (const auto &List : Attrs)
1202 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1203
1204 // If every list was empty, there is no point in merging the lists.
1205 if (MaxSize == 0)
1206 return {};
1207
1208 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1209 for (unsigned I = 0; I < MaxSize; ++I) {
1210 AttrBuilder CurBuilder(C);
1211 for (const auto &List : Attrs)
1212 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1213 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1214 }
1215
1216 return getImpl(C, NewAttrSets);
1217 }
1218
1219 AttributeList
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1220 AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1221 Attribute::AttrKind Kind) const {
1222 if (hasAttributeAtIndex(Index, Kind))
1223 return *this;
1224 AttributeSet Attrs = getAttributes(Index);
1225 // TODO: Insert at correct position and avoid sort.
1226 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1227 NewAttrs.push_back(Attribute::get(C, Kind));
1228 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1229 }
1230
addAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1231 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1232 StringRef Kind,
1233 StringRef Value) const {
1234 AttrBuilder B(C);
1235 B.addAttribute(Kind, Value);
1236 return addAttributesAtIndex(C, Index, B);
1237 }
1238
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute A) const1239 AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1240 Attribute A) const {
1241 AttrBuilder B(C);
1242 B.addAttribute(A);
1243 return addAttributesAtIndex(C, Index, B);
1244 }
1245
setAttributesAtIndex(LLVMContext & C,unsigned Index,AttributeSet Attrs) const1246 AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1247 unsigned Index,
1248 AttributeSet Attrs) const {
1249 Index = attrIdxToArrayIdx(Index);
1250 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1251 if (Index >= AttrSets.size())
1252 AttrSets.resize(Index + 1);
1253 AttrSets[Index] = Attrs;
1254 return AttributeList::getImpl(C, AttrSets);
1255 }
1256
addAttributesAtIndex(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1257 AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1258 unsigned Index,
1259 const AttrBuilder &B) const {
1260 if (!B.hasAttributes())
1261 return *this;
1262
1263 if (!pImpl)
1264 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1265
1266 AttrBuilder Merged(C, getAttributes(Index));
1267 Merged.merge(B);
1268 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1269 }
1270
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const1271 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1272 ArrayRef<unsigned> ArgNos,
1273 Attribute A) const {
1274 assert(llvm::is_sorted(ArgNos));
1275
1276 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1277 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1278 if (MaxIndex >= AttrSets.size())
1279 AttrSets.resize(MaxIndex + 1);
1280
1281 for (unsigned ArgNo : ArgNos) {
1282 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1283 AttrBuilder B(C, AttrSets[Index]);
1284 B.addAttribute(A);
1285 AttrSets[Index] = AttributeSet::get(C, B);
1286 }
1287
1288 return getImpl(C, AttrSets);
1289 }
1290
1291 AttributeList
removeAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1292 AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1293 Attribute::AttrKind Kind) const {
1294 if (!hasAttributeAtIndex(Index, Kind))
1295 return *this;
1296
1297 Index = attrIdxToArrayIdx(Index);
1298 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1299 assert(Index < AttrSets.size());
1300
1301 AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1302
1303 return getImpl(C, AttrSets);
1304 }
1305
removeAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind) const1306 AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1307 unsigned Index,
1308 StringRef Kind) const {
1309 if (!hasAttributeAtIndex(Index, Kind))
1310 return *this;
1311
1312 Index = attrIdxToArrayIdx(Index);
1313 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1314 assert(Index < AttrSets.size());
1315
1316 AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1317
1318 return getImpl(C, AttrSets);
1319 }
1320
removeAttributesAtIndex(LLVMContext & C,unsigned Index,const AttributeMask & AttrsToRemove) const1321 AttributeList AttributeList::removeAttributesAtIndex(
1322 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1323 AttributeSet Attrs = getAttributes(Index);
1324 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1325 // If nothing was removed, return the original list.
1326 if (Attrs == NewAttrs)
1327 return *this;
1328 return setAttributesAtIndex(C, Index, NewAttrs);
1329 }
1330
1331 AttributeList
removeAttributesAtIndex(LLVMContext & C,unsigned WithoutIndex) const1332 AttributeList::removeAttributesAtIndex(LLVMContext &C,
1333 unsigned WithoutIndex) const {
1334 if (!pImpl)
1335 return {};
1336 WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
1337 if (WithoutIndex >= getNumAttrSets())
1338 return *this;
1339 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1340 AttrSets[WithoutIndex] = AttributeSet();
1341 return getImpl(C, AttrSets);
1342 }
1343
addDereferenceableRetAttr(LLVMContext & C,uint64_t Bytes) const1344 AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1345 uint64_t Bytes) const {
1346 AttrBuilder B(C);
1347 B.addDereferenceableAttr(Bytes);
1348 return addRetAttributes(C, B);
1349 }
1350
addDereferenceableParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1351 AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1352 unsigned Index,
1353 uint64_t Bytes) const {
1354 AttrBuilder B(C);
1355 B.addDereferenceableAttr(Bytes);
1356 return addParamAttributes(C, Index, B);
1357 }
1358
1359 AttributeList
addDereferenceableOrNullParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1360 AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1361 uint64_t Bytes) const {
1362 AttrBuilder B(C);
1363 B.addDereferenceableOrNullAttr(Bytes);
1364 return addParamAttributes(C, Index, B);
1365 }
1366
1367 AttributeList
addAllocSizeParamAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)1368 AttributeList::addAllocSizeParamAttr(LLVMContext &C, unsigned Index,
1369 unsigned ElemSizeArg,
1370 const Optional<unsigned> &NumElemsArg) {
1371 AttrBuilder B(C);
1372 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1373 return addParamAttributes(C, Index, B);
1374 }
1375
1376 //===----------------------------------------------------------------------===//
1377 // AttributeList Accessor Methods
1378 //===----------------------------------------------------------------------===//
1379
getParamAttrs(unsigned ArgNo) const1380 AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1381 return getAttributes(ArgNo + FirstArgIndex);
1382 }
1383
getRetAttrs() const1384 AttributeSet AttributeList::getRetAttrs() const {
1385 return getAttributes(ReturnIndex);
1386 }
1387
getFnAttrs() const1388 AttributeSet AttributeList::getFnAttrs() const {
1389 return getAttributes(FunctionIndex);
1390 }
1391
hasAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1392 bool AttributeList::hasAttributeAtIndex(unsigned Index,
1393 Attribute::AttrKind Kind) const {
1394 return getAttributes(Index).hasAttribute(Kind);
1395 }
1396
hasAttributeAtIndex(unsigned Index,StringRef Kind) const1397 bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1398 return getAttributes(Index).hasAttribute(Kind);
1399 }
1400
hasAttributesAtIndex(unsigned Index) const1401 bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1402 return getAttributes(Index).hasAttributes();
1403 }
1404
hasFnAttr(Attribute::AttrKind Kind) const1405 bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1406 return pImpl && pImpl->hasFnAttribute(Kind);
1407 }
1408
hasFnAttr(StringRef Kind) const1409 bool AttributeList::hasFnAttr(StringRef Kind) const {
1410 return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1411 }
1412
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1413 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1414 unsigned *Index) const {
1415 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1416 }
1417
getAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1418 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1419 Attribute::AttrKind Kind) const {
1420 return getAttributes(Index).getAttribute(Kind);
1421 }
1422
getAttributeAtIndex(unsigned Index,StringRef Kind) const1423 Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1424 StringRef Kind) const {
1425 return getAttributes(Index).getAttribute(Kind);
1426 }
1427
getRetAlignment() const1428 MaybeAlign AttributeList::getRetAlignment() const {
1429 return getAttributes(ReturnIndex).getAlignment();
1430 }
1431
getParamAlignment(unsigned ArgNo) const1432 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1433 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1434 }
1435
getParamStackAlignment(unsigned ArgNo) const1436 MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1437 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1438 }
1439
getParamByValType(unsigned Index) const1440 Type *AttributeList::getParamByValType(unsigned Index) const {
1441 return getAttributes(Index+FirstArgIndex).getByValType();
1442 }
1443
getParamStructRetType(unsigned Index) const1444 Type *AttributeList::getParamStructRetType(unsigned Index) const {
1445 return getAttributes(Index + FirstArgIndex).getStructRetType();
1446 }
1447
getParamByRefType(unsigned Index) const1448 Type *AttributeList::getParamByRefType(unsigned Index) const {
1449 return getAttributes(Index + FirstArgIndex).getByRefType();
1450 }
1451
getParamPreallocatedType(unsigned Index) const1452 Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1453 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1454 }
1455
getParamInAllocaType(unsigned Index) const1456 Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1457 return getAttributes(Index + FirstArgIndex).getInAllocaType();
1458 }
1459
getParamElementType(unsigned Index) const1460 Type *AttributeList::getParamElementType(unsigned Index) const {
1461 return getAttributes(Index + FirstArgIndex).getElementType();
1462 }
1463
getFnStackAlignment() const1464 MaybeAlign AttributeList::getFnStackAlignment() const {
1465 return getFnAttrs().getStackAlignment();
1466 }
1467
getRetStackAlignment() const1468 MaybeAlign AttributeList::getRetStackAlignment() const {
1469 return getRetAttrs().getStackAlignment();
1470 }
1471
getRetDereferenceableBytes() const1472 uint64_t AttributeList::getRetDereferenceableBytes() const {
1473 return getRetAttrs().getDereferenceableBytes();
1474 }
1475
getParamDereferenceableBytes(unsigned Index) const1476 uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1477 return getParamAttrs(Index).getDereferenceableBytes();
1478 }
1479
getRetDereferenceableOrNullBytes() const1480 uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1481 return getRetAttrs().getDereferenceableOrNullBytes();
1482 }
1483
1484 uint64_t
getParamDereferenceableOrNullBytes(unsigned Index) const1485 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1486 return getParamAttrs(Index).getDereferenceableOrNullBytes();
1487 }
1488
getUWTableKind() const1489 UWTableKind AttributeList::getUWTableKind() const {
1490 return getFnAttrs().getUWTableKind();
1491 }
1492
getAllocKind() const1493 AllocFnKind AttributeList::getAllocKind() const {
1494 return getFnAttrs().getAllocKind();
1495 }
1496
getAsString(unsigned Index,bool InAttrGrp) const1497 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1498 return getAttributes(Index).getAsString(InAttrGrp);
1499 }
1500
getAttributes(unsigned Index) const1501 AttributeSet AttributeList::getAttributes(unsigned Index) const {
1502 Index = attrIdxToArrayIdx(Index);
1503 if (!pImpl || Index >= getNumAttrSets())
1504 return {};
1505 return pImpl->begin()[Index];
1506 }
1507
hasParentContext(LLVMContext & C) const1508 bool AttributeList::hasParentContext(LLVMContext &C) const {
1509 assert(!isEmpty() && "an empty attribute list has no parent context");
1510 FoldingSetNodeID ID;
1511 pImpl->Profile(ID);
1512 void *Unused;
1513 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1514 }
1515
begin() const1516 AttributeList::iterator AttributeList::begin() const {
1517 return pImpl ? pImpl->begin() : nullptr;
1518 }
1519
end() const1520 AttributeList::iterator AttributeList::end() const {
1521 return pImpl ? pImpl->end() : nullptr;
1522 }
1523
1524 //===----------------------------------------------------------------------===//
1525 // AttributeList Introspection Methods
1526 //===----------------------------------------------------------------------===//
1527
getNumAttrSets() const1528 unsigned AttributeList::getNumAttrSets() const {
1529 return pImpl ? pImpl->NumAttrSets : 0;
1530 }
1531
print(raw_ostream & O) const1532 void AttributeList::print(raw_ostream &O) const {
1533 O << "AttributeList[\n";
1534
1535 for (unsigned i : indexes()) {
1536 if (!getAttributes(i).hasAttributes())
1537 continue;
1538 O << " { ";
1539 switch (i) {
1540 case AttrIndex::ReturnIndex:
1541 O << "return";
1542 break;
1543 case AttrIndex::FunctionIndex:
1544 O << "function";
1545 break;
1546 default:
1547 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1548 }
1549 O << " => " << getAsString(i) << " }\n";
1550 }
1551
1552 O << "]\n";
1553 }
1554
1555 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1556 LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
1557 #endif
1558
1559 //===----------------------------------------------------------------------===//
1560 // AttrBuilder Method Implementations
1561 //===----------------------------------------------------------------------===//
1562
AttrBuilder(LLVMContext & Ctx,AttributeSet AS)1563 AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
1564 append_range(Attrs, AS);
1565 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
1566 }
1567
clear()1568 void AttrBuilder::clear() { Attrs.clear(); }
1569
1570 /// Attribute comparator that only compares attribute keys. Enum attributes are
1571 /// sorted before string attributes.
1572 struct AttributeComparator {
operator ()AttributeComparator1573 bool operator()(Attribute A0, Attribute A1) const {
1574 bool A0IsString = A0.isStringAttribute();
1575 bool A1IsString = A1.isStringAttribute();
1576 if (A0IsString) {
1577 if (A1IsString)
1578 return A0.getKindAsString() < A1.getKindAsString();
1579 else
1580 return false;
1581 }
1582 if (A1IsString)
1583 return true;
1584 return A0.getKindAsEnum() < A1.getKindAsEnum();
1585 }
operator ()AttributeComparator1586 bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
1587 if (A0.isStringAttribute())
1588 return false;
1589 return A0.getKindAsEnum() < Kind;
1590 }
operator ()AttributeComparator1591 bool operator()(Attribute A0, StringRef Kind) const {
1592 if (A0.isStringAttribute())
1593 return A0.getKindAsString() < Kind;
1594 return true;
1595 }
1596 };
1597
1598 template <typename K>
addAttributeImpl(SmallVectorImpl<Attribute> & Attrs,K Kind,Attribute Attr)1599 static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
1600 Attribute Attr) {
1601 auto It = lower_bound(Attrs, Kind, AttributeComparator());
1602 if (It != Attrs.end() && It->hasAttribute(Kind))
1603 std::swap(*It, Attr);
1604 else
1605 Attrs.insert(It, Attr);
1606 }
1607
addAttribute(Attribute Attr)1608 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1609 if (Attr.isStringAttribute())
1610 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1611 else
1612 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
1613 return *this;
1614 }
1615
addAttribute(Attribute::AttrKind Kind)1616 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
1617 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
1618 return *this;
1619 }
1620
addAttribute(StringRef A,StringRef V)1621 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1622 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
1623 return *this;
1624 }
1625
removeAttribute(Attribute::AttrKind Val)1626 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1627 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1628 auto It = lower_bound(Attrs, Val, AttributeComparator());
1629 if (It != Attrs.end() && It->hasAttribute(Val))
1630 Attrs.erase(It);
1631 return *this;
1632 }
1633
removeAttribute(StringRef A)1634 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1635 auto It = lower_bound(Attrs, A, AttributeComparator());
1636 if (It != Attrs.end() && It->hasAttribute(A))
1637 Attrs.erase(It);
1638 return *this;
1639 }
1640
getRawIntAttr(Attribute::AttrKind Kind) const1641 uint64_t AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
1642 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
1643 Attribute A = getAttribute(Kind);
1644 return A.isValid() ? A.getValueAsInt() : 0;
1645 }
1646
addRawIntAttr(Attribute::AttrKind Kind,uint64_t Value)1647 AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
1648 uint64_t Value) {
1649 return addAttribute(Attribute::get(Ctx, Kind, Value));
1650 }
1651
getAllocSizeArgs() const1652 std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
1653 return unpackAllocSizeArgs(getRawIntAttr(Attribute::AllocSize));
1654 }
1655
getVScaleRangeMin() const1656 unsigned AttrBuilder::getVScaleRangeMin() const {
1657 return unpackVScaleRangeArgs(getRawIntAttr(Attribute::VScaleRange)).first;
1658 }
1659
getVScaleRangeMax() const1660 Optional<unsigned> AttrBuilder::getVScaleRangeMax() const {
1661 return unpackVScaleRangeArgs(getRawIntAttr(Attribute::VScaleRange)).second;
1662 }
1663
addAlignmentAttr(MaybeAlign Align)1664 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1665 if (!Align)
1666 return *this;
1667
1668 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1669 return addRawIntAttr(Attribute::Alignment, Align->value());
1670 }
1671
addStackAlignmentAttr(MaybeAlign Align)1672 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1673 // Default alignment, allow the target to define how to align it.
1674 if (!Align)
1675 return *this;
1676
1677 assert(*Align <= 0x100 && "Alignment too large.");
1678 return addRawIntAttr(Attribute::StackAlignment, Align->value());
1679 }
1680
addDereferenceableAttr(uint64_t Bytes)1681 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1682 if (Bytes == 0) return *this;
1683
1684 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
1685 }
1686
addDereferenceableOrNullAttr(uint64_t Bytes)1687 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1688 if (Bytes == 0)
1689 return *this;
1690
1691 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
1692 }
1693
addAllocSizeAttr(unsigned ElemSize,const Optional<unsigned> & NumElems)1694 AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1695 const Optional<unsigned> &NumElems) {
1696 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1697 }
1698
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1699 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1700 // (0, 0) is our "not present" value, so we need to check for it here.
1701 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1702 return addRawIntAttr(Attribute::AllocSize, RawArgs);
1703 }
1704
addVScaleRangeAttr(unsigned MinValue,Optional<unsigned> MaxValue)1705 AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
1706 Optional<unsigned> MaxValue) {
1707 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
1708 }
1709
addVScaleRangeAttrFromRawRepr(uint64_t RawArgs)1710 AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
1711 // (0, 0) is not present hence ignore this case
1712 if (RawArgs == 0)
1713 return *this;
1714
1715 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1716 }
1717
addUWTableAttr(UWTableKind Kind)1718 AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
1719 if (Kind == UWTableKind::None)
1720 return *this;
1721 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
1722 }
1723
addAllocKindAttr(AllocFnKind Kind)1724 AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
1725 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
1726 }
1727
getTypeAttr(Attribute::AttrKind Kind) const1728 Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
1729 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
1730 Attribute A = getAttribute(Kind);
1731 return A.isValid() ? A.getValueAsType() : nullptr;
1732 }
1733
addTypeAttr(Attribute::AttrKind Kind,Type * Ty)1734 AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
1735 return addAttribute(Attribute::get(Ctx, Kind, Ty));
1736 }
1737
addByValAttr(Type * Ty)1738 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
1739 return addTypeAttr(Attribute::ByVal, Ty);
1740 }
1741
addStructRetAttr(Type * Ty)1742 AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
1743 return addTypeAttr(Attribute::StructRet, Ty);
1744 }
1745
addByRefAttr(Type * Ty)1746 AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
1747 return addTypeAttr(Attribute::ByRef, Ty);
1748 }
1749
addPreallocatedAttr(Type * Ty)1750 AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
1751 return addTypeAttr(Attribute::Preallocated, Ty);
1752 }
1753
addInAllocaAttr(Type * Ty)1754 AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
1755 return addTypeAttr(Attribute::InAlloca, Ty);
1756 }
1757
merge(const AttrBuilder & B)1758 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1759 // TODO: Could make this O(n) as we're merging two sorted lists.
1760 for (const auto &I : B.attrs())
1761 addAttribute(I);
1762
1763 return *this;
1764 }
1765
remove(const AttributeMask & AM)1766 AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
1767 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
1768 return *this;
1769 }
1770
overlaps(const AttributeMask & AM) const1771 bool AttrBuilder::overlaps(const AttributeMask &AM) const {
1772 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
1773 }
1774
getAttribute(Attribute::AttrKind A) const1775 Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
1776 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
1777 auto It = lower_bound(Attrs, A, AttributeComparator());
1778 if (It != Attrs.end() && It->hasAttribute(A))
1779 return *It;
1780 return {};
1781 }
1782
getAttribute(StringRef A) const1783 Attribute AttrBuilder::getAttribute(StringRef A) const {
1784 auto It = lower_bound(Attrs, A, AttributeComparator());
1785 if (It != Attrs.end() && It->hasAttribute(A))
1786 return *It;
1787 return {};
1788 }
1789
contains(Attribute::AttrKind A) const1790 bool AttrBuilder::contains(Attribute::AttrKind A) const {
1791 return getAttribute(A).isValid();
1792 }
1793
contains(StringRef A) const1794 bool AttrBuilder::contains(StringRef A) const {
1795 return getAttribute(A).isValid();
1796 }
1797
hasAlignmentAttr() const1798 bool AttrBuilder::hasAlignmentAttr() const {
1799 return getRawIntAttr(Attribute::Alignment) != 0;
1800 }
1801
operator ==(const AttrBuilder & B) const1802 bool AttrBuilder::operator==(const AttrBuilder &B) const {
1803 return Attrs == B.Attrs;
1804 }
1805
1806 //===----------------------------------------------------------------------===//
1807 // AttributeFuncs Function Defintions
1808 //===----------------------------------------------------------------------===//
1809
1810 /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty,AttributeSafetyKind ASK)1811 AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
1812 AttributeSafetyKind ASK) {
1813 AttributeMask Incompatible;
1814
1815 if (!Ty->isIntegerTy()) {
1816 // Attributes that only apply to integers.
1817 if (ASK & ASK_SAFE_TO_DROP)
1818 Incompatible.addAttribute(Attribute::AllocAlign);
1819 if (ASK & ASK_UNSAFE_TO_DROP)
1820 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
1821 }
1822
1823 if (!Ty->isPointerTy()) {
1824 // Attributes that only apply to pointers.
1825 if (ASK & ASK_SAFE_TO_DROP)
1826 Incompatible.addAttribute(Attribute::NoAlias)
1827 .addAttribute(Attribute::NoCapture)
1828 .addAttribute(Attribute::NonNull)
1829 .addAttribute(Attribute::ReadNone)
1830 .addAttribute(Attribute::ReadOnly)
1831 .addAttribute(Attribute::Dereferenceable)
1832 .addAttribute(Attribute::DereferenceableOrNull);
1833 if (ASK & ASK_UNSAFE_TO_DROP)
1834 Incompatible.addAttribute(Attribute::Nest)
1835 .addAttribute(Attribute::SwiftError)
1836 .addAttribute(Attribute::Preallocated)
1837 .addAttribute(Attribute::InAlloca)
1838 .addAttribute(Attribute::ByVal)
1839 .addAttribute(Attribute::StructRet)
1840 .addAttribute(Attribute::ByRef)
1841 .addAttribute(Attribute::ElementType)
1842 .addAttribute(Attribute::AllocatedPointer);
1843 }
1844
1845 // Attributes that only apply to pointers or vectors of pointers.
1846 if (!Ty->isPtrOrPtrVectorTy()) {
1847 if (ASK & ASK_SAFE_TO_DROP)
1848 Incompatible.addAttribute(Attribute::Alignment);
1849 }
1850
1851 // Some attributes can apply to all "values" but there are no `void` values.
1852 if (Ty->isVoidTy()) {
1853 if (ASK & ASK_SAFE_TO_DROP)
1854 Incompatible.addAttribute(Attribute::NoUndef);
1855 }
1856
1857 return Incompatible;
1858 }
1859
getUBImplyingAttributes()1860 AttributeMask AttributeFuncs::getUBImplyingAttributes() {
1861 AttributeMask AM;
1862 AM.addAttribute(Attribute::NoUndef);
1863 AM.addAttribute(Attribute::Dereferenceable);
1864 AM.addAttribute(Attribute::DereferenceableOrNull);
1865 return AM;
1866 }
1867
1868 template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)1869 static bool isEqual(const Function &Caller, const Function &Callee) {
1870 return Caller.getFnAttribute(AttrClass::getKind()) ==
1871 Callee.getFnAttribute(AttrClass::getKind());
1872 }
1873
1874 /// Compute the logical AND of the attributes of the caller and the
1875 /// callee.
1876 ///
1877 /// This function sets the caller's attribute to false if the callee's attribute
1878 /// is false.
1879 template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)1880 static void setAND(Function &Caller, const Function &Callee) {
1881 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
1882 !AttrClass::isSet(Callee, AttrClass::getKind()))
1883 AttrClass::set(Caller, AttrClass::getKind(), false);
1884 }
1885
1886 /// Compute the logical OR of the attributes of the caller and the
1887 /// callee.
1888 ///
1889 /// This function sets the caller's attribute to true if the callee's attribute
1890 /// is true.
1891 template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)1892 static void setOR(Function &Caller, const Function &Callee) {
1893 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
1894 AttrClass::isSet(Callee, AttrClass::getKind()))
1895 AttrClass::set(Caller, AttrClass::getKind(), true);
1896 }
1897
1898 /// If the inlined function had a higher stack protection level than the
1899 /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)1900 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1901 // If the calling function has *no* stack protection level (e.g. it was built
1902 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
1903 // change it as that could change the program's semantics.
1904 if (!Caller.hasStackProtectorFnAttr())
1905 return;
1906
1907 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1908 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1909 // clutter to the IR.
1910 AttributeMask OldSSPAttr;
1911 OldSSPAttr.addAttribute(Attribute::StackProtect)
1912 .addAttribute(Attribute::StackProtectStrong)
1913 .addAttribute(Attribute::StackProtectReq);
1914
1915 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1916 Caller.removeFnAttrs(OldSSPAttr);
1917 Caller.addFnAttr(Attribute::StackProtectReq);
1918 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
1919 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1920 Caller.removeFnAttrs(OldSSPAttr);
1921 Caller.addFnAttr(Attribute::StackProtectStrong);
1922 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
1923 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
1924 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
1925 Caller.addFnAttr(Attribute::StackProtect);
1926 }
1927
1928 /// If the inlined function required stack probes, then ensure that
1929 /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)1930 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
1931 if (!Caller.hasFnAttribute("probe-stack") &&
1932 Callee.hasFnAttribute("probe-stack")) {
1933 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
1934 }
1935 }
1936
1937 /// If the inlined function defines the size of guard region
1938 /// on the stack, then ensure that the calling function defines a guard region
1939 /// that is no larger.
1940 static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)1941 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
1942 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
1943 if (CalleeAttr.isValid()) {
1944 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
1945 if (CallerAttr.isValid()) {
1946 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
1947 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
1948 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
1949
1950 if (CallerStackProbeSize > CalleeStackProbeSize) {
1951 Caller.addFnAttr(CalleeAttr);
1952 }
1953 } else {
1954 Caller.addFnAttr(CalleeAttr);
1955 }
1956 }
1957 }
1958
1959 /// If the inlined function defines a min legal vector width, then ensure
1960 /// the calling function has the same or larger min legal vector width. If the
1961 /// caller has the attribute, but the callee doesn't, we need to remove the
1962 /// attribute from the caller since we can't make any guarantees about the
1963 /// caller's requirements.
1964 /// This function is called after the inlining decision has been made so we have
1965 /// to merge the attribute this way. Heuristics that would use
1966 /// min-legal-vector-width to determine inline compatibility would need to be
1967 /// handled as part of inline cost analysis.
1968 static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)1969 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
1970 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
1971 if (CallerAttr.isValid()) {
1972 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
1973 if (CalleeAttr.isValid()) {
1974 uint64_t CallerVectorWidth, CalleeVectorWidth;
1975 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
1976 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
1977 if (CallerVectorWidth < CalleeVectorWidth)
1978 Caller.addFnAttr(CalleeAttr);
1979 } else {
1980 // If the callee doesn't have the attribute then we don't know anything
1981 // and must drop the attribute from the caller.
1982 Caller.removeFnAttr("min-legal-vector-width");
1983 }
1984 }
1985 }
1986
1987 /// If the inlined function has null_pointer_is_valid attribute,
1988 /// set this attribute in the caller post inlining.
1989 static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)1990 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
1991 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
1992 Caller.addFnAttr(Attribute::NullPointerIsValid);
1993 }
1994 }
1995
1996 struct EnumAttr {
isSetEnumAttr1997 static bool isSet(const Function &Fn,
1998 Attribute::AttrKind Kind) {
1999 return Fn.hasFnAttribute(Kind);
2000 }
2001
setEnumAttr2002 static void set(Function &Fn,
2003 Attribute::AttrKind Kind, bool Val) {
2004 if (Val)
2005 Fn.addFnAttr(Kind);
2006 else
2007 Fn.removeFnAttr(Kind);
2008 }
2009 };
2010
2011 struct StrBoolAttr {
isSetStrBoolAttr2012 static bool isSet(const Function &Fn,
2013 StringRef Kind) {
2014 auto A = Fn.getFnAttribute(Kind);
2015 return A.getValueAsString().equals("true");
2016 }
2017
setStrBoolAttr2018 static void set(Function &Fn,
2019 StringRef Kind, bool Val) {
2020 Fn.addFnAttr(Kind, Val ? "true" : "false");
2021 }
2022 };
2023
2024 #define GET_ATTR_NAMES
2025 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2026 struct ENUM_NAME##Attr : EnumAttr { \
2027 static enum Attribute::AttrKind getKind() { \
2028 return llvm::Attribute::ENUM_NAME; \
2029 } \
2030 };
2031 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2032 struct ENUM_NAME##Attr : StrBoolAttr { \
2033 static StringRef getKind() { return #DISPLAY_NAME; } \
2034 };
2035 #include "llvm/IR/Attributes.inc"
2036
2037 #define GET_ATTR_COMPAT_FUNC
2038 #include "llvm/IR/Attributes.inc"
2039
areInlineCompatible(const Function & Caller,const Function & Callee)2040 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2041 const Function &Callee) {
2042 return hasCompatibleFnAttrs(Caller, Callee);
2043 }
2044
areOutlineCompatible(const Function & A,const Function & B)2045 bool AttributeFuncs::areOutlineCompatible(const Function &A,
2046 const Function &B) {
2047 return hasCompatibleFnAttrs(A, B);
2048 }
2049
mergeAttributesForInlining(Function & Caller,const Function & Callee)2050 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2051 const Function &Callee) {
2052 mergeFnAttrs(Caller, Callee);
2053 }
2054
mergeAttributesForOutlining(Function & Base,const Function & ToMerge)2055 void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2056 const Function &ToMerge) {
2057
2058 // We merge functions so that they meet the most general case.
2059 // For example, if the NoNansFPMathAttr is set in one function, but not in
2060 // the other, in the merged function we can say that the NoNansFPMathAttr
2061 // is not set.
2062 // However if we have the SpeculativeLoadHardeningAttr set true in one
2063 // function, but not the other, we make sure that the function retains
2064 // that aspect in the merged function.
2065 mergeFnAttrs(Base, ToMerge);
2066 }
2067
updateMinLegalVectorWidthAttr(Function & Fn,uint64_t Width)2068 void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2069 uint64_t Width) {
2070 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2071 if (Attr.isValid()) {
2072 uint64_t OldWidth;
2073 Attr.getValueAsString().getAsInteger(0, OldWidth);
2074 if (Width > OldWidth)
2075 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2076 }
2077 }
2078