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/ADT/Twine.h"
27 #include "llvm/Config/llvm-config.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/IR/LLVMContext.h"
30 #include "llvm/IR/Type.h"
31 #include "llvm/Support/Compiler.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/MathExtras.h"
35 #include "llvm/Support/raw_ostream.h"
36 #include <algorithm>
37 #include <cassert>
38 #include <climits>
39 #include <cstddef>
40 #include <cstdint>
41 #include <limits>
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 Optional<unsigned> & NumElemsArg)60 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
61 const Optional<unsigned> &NumElemsArg) {
62 assert((!NumElemsArg.hasValue() ||
63 *NumElemsArg != AllocSizeNumElemsNotPresent) &&
64 "Attempting to pack a reserved value");
65
66 return uint64_t(ElemSizeArg) << 32 |
67 NumElemsArg.getValueOr(AllocSizeNumElemsNotPresent);
68 }
69
70 static std::pair<unsigned, Optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)71 unpackAllocSizeArgs(uint64_t Num) {
72 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
73 unsigned ElemSizeArg = Num >> 32;
74
75 Optional<unsigned> NumElemsArg;
76 if (NumElems != AllocSizeNumElemsNotPresent)
77 NumElemsArg = NumElems;
78 return std::make_pair(ElemSizeArg, NumElemsArg);
79 }
80
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)81 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
82 uint64_t Val) {
83 LLVMContextImpl *pImpl = Context.pImpl;
84 FoldingSetNodeID ID;
85 ID.AddInteger(Kind);
86 if (Val) ID.AddInteger(Val);
87
88 void *InsertPoint;
89 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
90
91 if (!PA) {
92 // If we didn't find any existing attributes of the same shape then create a
93 // new one and insert it.
94 if (!Val)
95 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
96 else
97 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
98 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
99 }
100
101 // Return the Attribute that we found or created.
102 return Attribute(PA);
103 }
104
get(LLVMContext & Context,StringRef Kind,StringRef Val)105 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
106 LLVMContextImpl *pImpl = Context.pImpl;
107 FoldingSetNodeID ID;
108 ID.AddString(Kind);
109 if (!Val.empty()) ID.AddString(Val);
110
111 void *InsertPoint;
112 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
113
114 if (!PA) {
115 // If we didn't find any existing attributes of the same shape then create a
116 // new one and insert it.
117 void *Mem =
118 pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
119 alignof(StringAttributeImpl));
120 PA = new (Mem) StringAttributeImpl(Kind, Val);
121 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
122 }
123
124 // Return the Attribute that we found or created.
125 return Attribute(PA);
126 }
127
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)128 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
129 Type *Ty) {
130 LLVMContextImpl *pImpl = Context.pImpl;
131 FoldingSetNodeID ID;
132 ID.AddInteger(Kind);
133 ID.AddPointer(Ty);
134
135 void *InsertPoint;
136 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
137
138 if (!PA) {
139 // If we didn't find any existing attributes of the same shape then create a
140 // new one and insert it.
141 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
142 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
143 }
144
145 // Return the Attribute that we found or created.
146 return Attribute(PA);
147 }
148
getWithAlignment(LLVMContext & Context,Align A)149 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
150 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
151 return get(Context, Alignment, A.value());
152 }
153
getWithStackAlignment(LLVMContext & Context,Align A)154 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
155 assert(A <= 0x100 && "Alignment too large.");
156 return get(Context, StackAlignment, A.value());
157 }
158
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)159 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
160 uint64_t Bytes) {
161 assert(Bytes && "Bytes must be non-zero.");
162 return get(Context, Dereferenceable, Bytes);
163 }
164
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)165 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
166 uint64_t Bytes) {
167 assert(Bytes && "Bytes must be non-zero.");
168 return get(Context, DereferenceableOrNull, Bytes);
169 }
170
getWithByValType(LLVMContext & Context,Type * Ty)171 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
172 return get(Context, ByVal, Ty);
173 }
174
getWithStructRetType(LLVMContext & Context,Type * Ty)175 Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
176 return get(Context, StructRet, Ty);
177 }
178
getWithByRefType(LLVMContext & Context,Type * Ty)179 Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
180 return get(Context, ByRef, Ty);
181 }
182
getWithPreallocatedType(LLVMContext & Context,Type * Ty)183 Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
184 return get(Context, Preallocated, Ty);
185 }
186
187 Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)188 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
189 const Optional<unsigned> &NumElemsArg) {
190 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
191 "Invalid allocsize arguments -- given allocsize(0, 0)");
192 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
193 }
194
getAttrKindFromName(StringRef AttrName)195 Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
196 return StringSwitch<Attribute::AttrKind>(AttrName)
197 #define GET_ATTR_NAMES
198 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
199 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
200 #include "llvm/IR/Attributes.inc"
201 .Default(Attribute::None);
202 }
203
getNameFromAttrKind(Attribute::AttrKind AttrKind)204 StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
205 switch (AttrKind) {
206 #define GET_ATTR_NAMES
207 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
208 case Attribute::ENUM_NAME: \
209 return #DISPLAY_NAME;
210 #include "llvm/IR/Attributes.inc"
211 case Attribute::None:
212 return "none";
213 default:
214 llvm_unreachable("invalid Kind");
215 }
216 }
217
doesAttrKindHaveArgument(Attribute::AttrKind AttrKind)218 bool Attribute::doesAttrKindHaveArgument(Attribute::AttrKind AttrKind) {
219 return AttrKind == Attribute::Alignment ||
220 AttrKind == Attribute::StackAlignment ||
221 AttrKind == Attribute::Dereferenceable ||
222 AttrKind == Attribute::AllocSize ||
223 AttrKind == Attribute::DereferenceableOrNull;
224 }
225
isExistingAttribute(StringRef Name)226 bool Attribute::isExistingAttribute(StringRef Name) {
227 return StringSwitch<bool>(Name)
228 #define GET_ATTR_NAMES
229 #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
230 #include "llvm/IR/Attributes.inc"
231 .Default(false);
232 }
233
234 //===----------------------------------------------------------------------===//
235 // Attribute Accessor Methods
236 //===----------------------------------------------------------------------===//
237
isEnumAttribute() const238 bool Attribute::isEnumAttribute() const {
239 return pImpl && pImpl->isEnumAttribute();
240 }
241
isIntAttribute() const242 bool Attribute::isIntAttribute() const {
243 return pImpl && pImpl->isIntAttribute();
244 }
245
isStringAttribute() const246 bool Attribute::isStringAttribute() const {
247 return pImpl && pImpl->isStringAttribute();
248 }
249
isTypeAttribute() const250 bool Attribute::isTypeAttribute() const {
251 return pImpl && pImpl->isTypeAttribute();
252 }
253
getKindAsEnum() const254 Attribute::AttrKind Attribute::getKindAsEnum() const {
255 if (!pImpl) return None;
256 assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
257 "Invalid attribute type to get the kind as an enum!");
258 return pImpl->getKindAsEnum();
259 }
260
getValueAsInt() const261 uint64_t Attribute::getValueAsInt() const {
262 if (!pImpl) return 0;
263 assert(isIntAttribute() &&
264 "Expected the attribute to be an integer attribute!");
265 return pImpl->getValueAsInt();
266 }
267
getKindAsString() const268 StringRef Attribute::getKindAsString() const {
269 if (!pImpl) return {};
270 assert(isStringAttribute() &&
271 "Invalid attribute type to get the kind as a string!");
272 return pImpl->getKindAsString();
273 }
274
getValueAsString() const275 StringRef Attribute::getValueAsString() const {
276 if (!pImpl) return {};
277 assert(isStringAttribute() &&
278 "Invalid attribute type to get the value as a string!");
279 return pImpl->getValueAsString();
280 }
281
getValueAsType() const282 Type *Attribute::getValueAsType() const {
283 if (!pImpl) return {};
284 assert(isTypeAttribute() &&
285 "Invalid attribute type to get the value as a type!");
286 return pImpl->getValueAsType();
287 }
288
289
hasAttribute(AttrKind Kind) const290 bool Attribute::hasAttribute(AttrKind Kind) const {
291 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
292 }
293
hasAttribute(StringRef Kind) const294 bool Attribute::hasAttribute(StringRef Kind) const {
295 if (!isStringAttribute()) return false;
296 return pImpl && pImpl->hasAttribute(Kind);
297 }
298
getAlignment() const299 MaybeAlign Attribute::getAlignment() const {
300 assert(hasAttribute(Attribute::Alignment) &&
301 "Trying to get alignment from non-alignment attribute!");
302 return MaybeAlign(pImpl->getValueAsInt());
303 }
304
getStackAlignment() const305 MaybeAlign Attribute::getStackAlignment() const {
306 assert(hasAttribute(Attribute::StackAlignment) &&
307 "Trying to get alignment from non-alignment attribute!");
308 return MaybeAlign(pImpl->getValueAsInt());
309 }
310
getDereferenceableBytes() const311 uint64_t Attribute::getDereferenceableBytes() const {
312 assert(hasAttribute(Attribute::Dereferenceable) &&
313 "Trying to get dereferenceable bytes from "
314 "non-dereferenceable attribute!");
315 return pImpl->getValueAsInt();
316 }
317
getDereferenceableOrNullBytes() const318 uint64_t Attribute::getDereferenceableOrNullBytes() const {
319 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
320 "Trying to get dereferenceable bytes from "
321 "non-dereferenceable attribute!");
322 return pImpl->getValueAsInt();
323 }
324
getAllocSizeArgs() const325 std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
326 assert(hasAttribute(Attribute::AllocSize) &&
327 "Trying to get allocsize args from non-allocsize attribute");
328 return unpackAllocSizeArgs(pImpl->getValueAsInt());
329 }
330
getAsString(bool InAttrGrp) const331 std::string Attribute::getAsString(bool InAttrGrp) const {
332 if (!pImpl) return {};
333
334 if (hasAttribute(Attribute::SanitizeAddress))
335 return "sanitize_address";
336 if (hasAttribute(Attribute::SanitizeHWAddress))
337 return "sanitize_hwaddress";
338 if (hasAttribute(Attribute::SanitizeMemTag))
339 return "sanitize_memtag";
340 if (hasAttribute(Attribute::AlwaysInline))
341 return "alwaysinline";
342 if (hasAttribute(Attribute::ArgMemOnly))
343 return "argmemonly";
344 if (hasAttribute(Attribute::Builtin))
345 return "builtin";
346 if (hasAttribute(Attribute::Convergent))
347 return "convergent";
348 if (hasAttribute(Attribute::SwiftError))
349 return "swifterror";
350 if (hasAttribute(Attribute::SwiftSelf))
351 return "swiftself";
352 if (hasAttribute(Attribute::InaccessibleMemOnly))
353 return "inaccessiblememonly";
354 if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
355 return "inaccessiblemem_or_argmemonly";
356 if (hasAttribute(Attribute::InAlloca))
357 return "inalloca";
358 if (hasAttribute(Attribute::InlineHint))
359 return "inlinehint";
360 if (hasAttribute(Attribute::InReg))
361 return "inreg";
362 if (hasAttribute(Attribute::JumpTable))
363 return "jumptable";
364 if (hasAttribute(Attribute::MinSize))
365 return "minsize";
366 if (hasAttribute(Attribute::Naked))
367 return "naked";
368 if (hasAttribute(Attribute::Nest))
369 return "nest";
370 if (hasAttribute(Attribute::NoAlias))
371 return "noalias";
372 if (hasAttribute(Attribute::NoBuiltin))
373 return "nobuiltin";
374 if (hasAttribute(Attribute::NoCapture))
375 return "nocapture";
376 if (hasAttribute(Attribute::NoDuplicate))
377 return "noduplicate";
378 if (hasAttribute(Attribute::NoFree))
379 return "nofree";
380 if (hasAttribute(Attribute::NoImplicitFloat))
381 return "noimplicitfloat";
382 if (hasAttribute(Attribute::NoInline))
383 return "noinline";
384 if (hasAttribute(Attribute::NonLazyBind))
385 return "nonlazybind";
386 if (hasAttribute(Attribute::NoMerge))
387 return "nomerge";
388 if (hasAttribute(Attribute::NonNull))
389 return "nonnull";
390 if (hasAttribute(Attribute::NoRedZone))
391 return "noredzone";
392 if (hasAttribute(Attribute::NoReturn))
393 return "noreturn";
394 if (hasAttribute(Attribute::NoSync))
395 return "nosync";
396 if (hasAttribute(Attribute::NullPointerIsValid))
397 return "null_pointer_is_valid";
398 if (hasAttribute(Attribute::WillReturn))
399 return "willreturn";
400 if (hasAttribute(Attribute::NoCfCheck))
401 return "nocf_check";
402 if (hasAttribute(Attribute::NoRecurse))
403 return "norecurse";
404 if (hasAttribute(Attribute::NoUnwind))
405 return "nounwind";
406 if (hasAttribute(Attribute::OptForFuzzing))
407 return "optforfuzzing";
408 if (hasAttribute(Attribute::OptimizeNone))
409 return "optnone";
410 if (hasAttribute(Attribute::OptimizeForSize))
411 return "optsize";
412 if (hasAttribute(Attribute::ReadNone))
413 return "readnone";
414 if (hasAttribute(Attribute::ReadOnly))
415 return "readonly";
416 if (hasAttribute(Attribute::WriteOnly))
417 return "writeonly";
418 if (hasAttribute(Attribute::Returned))
419 return "returned";
420 if (hasAttribute(Attribute::ReturnsTwice))
421 return "returns_twice";
422 if (hasAttribute(Attribute::SExt))
423 return "signext";
424 if (hasAttribute(Attribute::SpeculativeLoadHardening))
425 return "speculative_load_hardening";
426 if (hasAttribute(Attribute::Speculatable))
427 return "speculatable";
428 if (hasAttribute(Attribute::StackProtect))
429 return "ssp";
430 if (hasAttribute(Attribute::StackProtectReq))
431 return "sspreq";
432 if (hasAttribute(Attribute::StackProtectStrong))
433 return "sspstrong";
434 if (hasAttribute(Attribute::SafeStack))
435 return "safestack";
436 if (hasAttribute(Attribute::ShadowCallStack))
437 return "shadowcallstack";
438 if (hasAttribute(Attribute::StrictFP))
439 return "strictfp";
440 if (hasAttribute(Attribute::SanitizeThread))
441 return "sanitize_thread";
442 if (hasAttribute(Attribute::SanitizeMemory))
443 return "sanitize_memory";
444 if (hasAttribute(Attribute::UWTable))
445 return "uwtable";
446 if (hasAttribute(Attribute::ZExt))
447 return "zeroext";
448 if (hasAttribute(Attribute::Cold))
449 return "cold";
450 if (hasAttribute(Attribute::ImmArg))
451 return "immarg";
452 if (hasAttribute(Attribute::NoUndef))
453 return "noundef";
454 if (hasAttribute(Attribute::MustProgress))
455 return "mustprogress";
456
457 const bool IsByVal = hasAttribute(Attribute::ByVal);
458 if (IsByVal || hasAttribute(Attribute::StructRet)) {
459 std::string Result;
460 Result += IsByVal ? "byval" : "sret";
461 if (Type *Ty = getValueAsType()) {
462 raw_string_ostream OS(Result);
463 Result += '(';
464 Ty->print(OS, false, true);
465 OS.flush();
466 Result += ')';
467 }
468 return Result;
469 }
470
471 const bool IsByRef = hasAttribute(Attribute::ByRef);
472 if (IsByRef || hasAttribute(Attribute::Preallocated)) {
473 std::string Result = IsByRef ? "byref" : "preallocated";
474 raw_string_ostream OS(Result);
475 Result += '(';
476 getValueAsType()->print(OS, false, true);
477 OS.flush();
478 Result += ')';
479 return Result;
480 }
481
482 // FIXME: These should be output like this:
483 //
484 // align=4
485 // alignstack=8
486 //
487 if (hasAttribute(Attribute::Alignment)) {
488 std::string Result;
489 Result += "align";
490 Result += (InAttrGrp) ? "=" : " ";
491 Result += utostr(getValueAsInt());
492 return Result;
493 }
494
495 auto AttrWithBytesToString = [&](const char *Name) {
496 std::string Result;
497 Result += Name;
498 if (InAttrGrp) {
499 Result += "=";
500 Result += utostr(getValueAsInt());
501 } else {
502 Result += "(";
503 Result += utostr(getValueAsInt());
504 Result += ")";
505 }
506 return Result;
507 };
508
509 if (hasAttribute(Attribute::StackAlignment))
510 return AttrWithBytesToString("alignstack");
511
512 if (hasAttribute(Attribute::Dereferenceable))
513 return AttrWithBytesToString("dereferenceable");
514
515 if (hasAttribute(Attribute::DereferenceableOrNull))
516 return AttrWithBytesToString("dereferenceable_or_null");
517
518 if (hasAttribute(Attribute::AllocSize)) {
519 unsigned ElemSize;
520 Optional<unsigned> NumElems;
521 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
522
523 std::string Result = "allocsize(";
524 Result += utostr(ElemSize);
525 if (NumElems.hasValue()) {
526 Result += ',';
527 Result += utostr(*NumElems);
528 }
529 Result += ')';
530 return Result;
531 }
532
533 // Convert target-dependent attributes to strings of the form:
534 //
535 // "kind"
536 // "kind" = "value"
537 //
538 if (isStringAttribute()) {
539 std::string Result;
540 {
541 raw_string_ostream OS(Result);
542 OS << '"' << getKindAsString() << '"';
543
544 // Since some attribute strings contain special characters that cannot be
545 // printable, those have to be escaped to make the attribute value
546 // printable as is. e.g. "\01__gnu_mcount_nc"
547 const auto &AttrVal = pImpl->getValueAsString();
548 if (!AttrVal.empty()) {
549 OS << "=\"";
550 printEscapedString(AttrVal, OS);
551 OS << "\"";
552 }
553 }
554 return Result;
555 }
556
557 llvm_unreachable("Unknown attribute");
558 }
559
operator <(Attribute A) const560 bool Attribute::operator<(Attribute A) const {
561 if (!pImpl && !A.pImpl) return false;
562 if (!pImpl) return true;
563 if (!A.pImpl) return false;
564 return *pImpl < *A.pImpl;
565 }
566
Profile(FoldingSetNodeID & ID) const567 void Attribute::Profile(FoldingSetNodeID &ID) const {
568 ID.AddPointer(pImpl);
569 }
570
571 //===----------------------------------------------------------------------===//
572 // AttributeImpl Definition
573 //===----------------------------------------------------------------------===//
574
hasAttribute(Attribute::AttrKind A) const575 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
576 if (isStringAttribute()) return false;
577 return getKindAsEnum() == A;
578 }
579
hasAttribute(StringRef Kind) const580 bool AttributeImpl::hasAttribute(StringRef Kind) const {
581 if (!isStringAttribute()) return false;
582 return getKindAsString() == Kind;
583 }
584
getKindAsEnum() const585 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
586 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
587 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
588 }
589
getValueAsInt() const590 uint64_t AttributeImpl::getValueAsInt() const {
591 assert(isIntAttribute());
592 return static_cast<const IntAttributeImpl *>(this)->getValue();
593 }
594
getKindAsString() const595 StringRef AttributeImpl::getKindAsString() const {
596 assert(isStringAttribute());
597 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
598 }
599
getValueAsString() const600 StringRef AttributeImpl::getValueAsString() const {
601 assert(isStringAttribute());
602 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
603 }
604
getValueAsType() const605 Type *AttributeImpl::getValueAsType() const {
606 assert(isTypeAttribute());
607 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
608 }
609
operator <(const AttributeImpl & AI) const610 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
611 if (this == &AI)
612 return false;
613 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
614 // relative to their enum value) and then strings.
615 if (isEnumAttribute()) {
616 if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();
617 if (AI.isIntAttribute()) return true;
618 if (AI.isStringAttribute()) return true;
619 if (AI.isTypeAttribute()) return true;
620 }
621
622 if (isTypeAttribute()) {
623 if (AI.isEnumAttribute()) return false;
624 if (AI.isTypeAttribute()) {
625 assert(getKindAsEnum() != AI.getKindAsEnum() &&
626 "Comparison of types would be unstable");
627 return getKindAsEnum() < AI.getKindAsEnum();
628 }
629 if (AI.isIntAttribute()) return true;
630 if (AI.isStringAttribute()) return true;
631 }
632
633 if (isIntAttribute()) {
634 if (AI.isEnumAttribute()) return false;
635 if (AI.isTypeAttribute()) return false;
636 if (AI.isIntAttribute()) {
637 if (getKindAsEnum() == AI.getKindAsEnum())
638 return getValueAsInt() < AI.getValueAsInt();
639 return getKindAsEnum() < AI.getKindAsEnum();
640 }
641 if (AI.isStringAttribute()) return true;
642 }
643
644 assert(isStringAttribute());
645 if (AI.isEnumAttribute()) return false;
646 if (AI.isTypeAttribute()) return false;
647 if (AI.isIntAttribute()) return false;
648 if (getKindAsString() == AI.getKindAsString())
649 return getValueAsString() < AI.getValueAsString();
650 return getKindAsString() < AI.getKindAsString();
651 }
652
653 //===----------------------------------------------------------------------===//
654 // AttributeSet Definition
655 //===----------------------------------------------------------------------===//
656
get(LLVMContext & C,const AttrBuilder & B)657 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
658 return AttributeSet(AttributeSetNode::get(C, B));
659 }
660
get(LLVMContext & C,ArrayRef<Attribute> Attrs)661 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
662 return AttributeSet(AttributeSetNode::get(C, Attrs));
663 }
664
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const665 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
666 Attribute::AttrKind Kind) const {
667 if (hasAttribute(Kind)) return *this;
668 AttrBuilder B;
669 B.addAttribute(Kind);
670 return addAttributes(C, AttributeSet::get(C, B));
671 }
672
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const673 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
674 StringRef Value) const {
675 AttrBuilder B;
676 B.addAttribute(Kind, Value);
677 return addAttributes(C, AttributeSet::get(C, B));
678 }
679
addAttributes(LLVMContext & C,const AttributeSet AS) const680 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
681 const AttributeSet AS) const {
682 if (!hasAttributes())
683 return AS;
684
685 if (!AS.hasAttributes())
686 return *this;
687
688 AttrBuilder B(AS);
689 for (const auto &I : *this)
690 B.addAttribute(I);
691
692 return get(C, B);
693 }
694
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const695 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
696 Attribute::AttrKind Kind) const {
697 if (!hasAttribute(Kind)) return *this;
698 AttrBuilder B(*this);
699 B.removeAttribute(Kind);
700 return get(C, B);
701 }
702
removeAttribute(LLVMContext & C,StringRef Kind) const703 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
704 StringRef Kind) const {
705 if (!hasAttribute(Kind)) return *this;
706 AttrBuilder B(*this);
707 B.removeAttribute(Kind);
708 return get(C, B);
709 }
710
removeAttributes(LLVMContext & C,const AttrBuilder & Attrs) const711 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
712 const AttrBuilder &Attrs) const {
713 AttrBuilder B(*this);
714 B.remove(Attrs);
715 return get(C, B);
716 }
717
getNumAttributes() const718 unsigned AttributeSet::getNumAttributes() const {
719 return SetNode ? SetNode->getNumAttributes() : 0;
720 }
721
hasAttribute(Attribute::AttrKind Kind) const722 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
723 return SetNode ? SetNode->hasAttribute(Kind) : false;
724 }
725
hasAttribute(StringRef Kind) const726 bool AttributeSet::hasAttribute(StringRef Kind) const {
727 return SetNode ? SetNode->hasAttribute(Kind) : false;
728 }
729
getAttribute(Attribute::AttrKind Kind) const730 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
731 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
732 }
733
getAttribute(StringRef Kind) const734 Attribute AttributeSet::getAttribute(StringRef Kind) const {
735 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
736 }
737
getAlignment() const738 MaybeAlign AttributeSet::getAlignment() const {
739 return SetNode ? SetNode->getAlignment() : None;
740 }
741
getStackAlignment() const742 MaybeAlign AttributeSet::getStackAlignment() const {
743 return SetNode ? SetNode->getStackAlignment() : None;
744 }
745
getDereferenceableBytes() const746 uint64_t AttributeSet::getDereferenceableBytes() const {
747 return SetNode ? SetNode->getDereferenceableBytes() : 0;
748 }
749
getDereferenceableOrNullBytes() const750 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
751 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
752 }
753
getByRefType() const754 Type *AttributeSet::getByRefType() const {
755 return SetNode ? SetNode->getByRefType() : nullptr;
756 }
757
getByValType() const758 Type *AttributeSet::getByValType() const {
759 return SetNode ? SetNode->getByValType() : nullptr;
760 }
761
getStructRetType() const762 Type *AttributeSet::getStructRetType() const {
763 return SetNode ? SetNode->getStructRetType() : nullptr;
764 }
765
getPreallocatedType() const766 Type *AttributeSet::getPreallocatedType() const {
767 return SetNode ? SetNode->getPreallocatedType() : nullptr;
768 }
769
getAllocSizeArgs() const770 std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
771 return SetNode ? SetNode->getAllocSizeArgs()
772 : std::pair<unsigned, Optional<unsigned>>(0, 0);
773 }
774
getAsString(bool InAttrGrp) const775 std::string AttributeSet::getAsString(bool InAttrGrp) const {
776 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
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 // Add target-independent attributes.
851 SmallVector<Attribute, 8> Attrs;
852 for (Attribute::AttrKind Kind = Attribute::None;
853 Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
854 if (!B.contains(Kind))
855 continue;
856
857 Attribute Attr;
858 switch (Kind) {
859 case Attribute::ByVal:
860 Attr = Attribute::getWithByValType(C, B.getByValType());
861 break;
862 case Attribute::StructRet:
863 Attr = Attribute::getWithStructRetType(C, B.getStructRetType());
864 break;
865 case Attribute::ByRef:
866 Attr = Attribute::getWithByRefType(C, B.getByRefType());
867 break;
868 case Attribute::Preallocated:
869 Attr = Attribute::getWithPreallocatedType(C, B.getPreallocatedType());
870 break;
871 case Attribute::Alignment:
872 assert(B.getAlignment() && "Alignment must be set");
873 Attr = Attribute::getWithAlignment(C, *B.getAlignment());
874 break;
875 case Attribute::StackAlignment:
876 assert(B.getStackAlignment() && "StackAlignment must be set");
877 Attr = Attribute::getWithStackAlignment(C, *B.getStackAlignment());
878 break;
879 case Attribute::Dereferenceable:
880 Attr = Attribute::getWithDereferenceableBytes(
881 C, B.getDereferenceableBytes());
882 break;
883 case Attribute::DereferenceableOrNull:
884 Attr = Attribute::getWithDereferenceableOrNullBytes(
885 C, B.getDereferenceableOrNullBytes());
886 break;
887 case Attribute::AllocSize: {
888 auto A = B.getAllocSizeArgs();
889 Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
890 break;
891 }
892 default:
893 Attr = Attribute::get(C, Kind);
894 }
895 Attrs.push_back(Attr);
896 }
897
898 // Add target-dependent (string) attributes.
899 for (const auto &TDA : B.td_attrs())
900 Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second));
901
902 return getSorted(C, Attrs);
903 }
904
hasAttribute(StringRef Kind) const905 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
906 return StringAttrs.count(Kind);
907 }
908
909 Optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const910 AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
911 // Do a quick presence check.
912 if (!hasAttribute(Kind))
913 return None;
914
915 // Attributes in a set are sorted by enum value, followed by string
916 // attributes. Binary search the one we want.
917 const Attribute *I =
918 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
919 [](Attribute A, Attribute::AttrKind Kind) {
920 return A.getKindAsEnum() < Kind;
921 });
922 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
923 return *I;
924 }
925
getAttribute(Attribute::AttrKind Kind) const926 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
927 if (auto A = findEnumAttribute(Kind))
928 return *A;
929 return {};
930 }
931
getAttribute(StringRef Kind) const932 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
933 return StringAttrs.lookup(Kind);
934 }
935
getAlignment() const936 MaybeAlign AttributeSetNode::getAlignment() const {
937 if (auto A = findEnumAttribute(Attribute::Alignment))
938 return A->getAlignment();
939 return None;
940 }
941
getStackAlignment() const942 MaybeAlign AttributeSetNode::getStackAlignment() const {
943 if (auto A = findEnumAttribute(Attribute::StackAlignment))
944 return A->getStackAlignment();
945 return None;
946 }
947
getByValType() const948 Type *AttributeSetNode::getByValType() const {
949 if (auto A = findEnumAttribute(Attribute::ByVal))
950 return A->getValueAsType();
951 return nullptr;
952 }
953
getStructRetType() const954 Type *AttributeSetNode::getStructRetType() const {
955 if (auto A = findEnumAttribute(Attribute::StructRet))
956 return A->getValueAsType();
957 return nullptr;
958 }
959
getByRefType() const960 Type *AttributeSetNode::getByRefType() const {
961 if (auto A = findEnumAttribute(Attribute::ByRef))
962 return A->getValueAsType();
963 return nullptr;
964 }
965
getPreallocatedType() const966 Type *AttributeSetNode::getPreallocatedType() const {
967 if (auto A = findEnumAttribute(Attribute::Preallocated))
968 return A->getValueAsType();
969 return nullptr;
970 }
971
getDereferenceableBytes() const972 uint64_t AttributeSetNode::getDereferenceableBytes() const {
973 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
974 return A->getDereferenceableBytes();
975 return 0;
976 }
977
getDereferenceableOrNullBytes() const978 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
979 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
980 return A->getDereferenceableOrNullBytes();
981 return 0;
982 }
983
984 std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs() const985 AttributeSetNode::getAllocSizeArgs() const {
986 if (auto A = findEnumAttribute(Attribute::AllocSize))
987 return A->getAllocSizeArgs();
988 return std::make_pair(0, 0);
989 }
990
getAsString(bool InAttrGrp) const991 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
992 std::string Str;
993 for (iterator I = begin(), E = end(); I != E; ++I) {
994 if (I != begin())
995 Str += ' ';
996 Str += I->getAsString(InAttrGrp);
997 }
998 return Str;
999 }
1000
1001 //===----------------------------------------------------------------------===//
1002 // AttributeListImpl Definition
1003 //===----------------------------------------------------------------------===//
1004
1005 /// Map from AttributeList index to the internal array index. Adding one happens
1006 /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)1007 static unsigned attrIdxToArrayIdx(unsigned Index) {
1008 return Index + 1;
1009 }
1010
AttributeListImpl(ArrayRef<AttributeSet> Sets)1011 AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
1012 : NumAttrSets(Sets.size()) {
1013 assert(!Sets.empty() && "pointless AttributeListImpl");
1014
1015 // There's memory after the node where we can store the entries in.
1016 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1017
1018 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1019 // summary bitsets.
1020 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1021 if (!I.isStringAttribute())
1022 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1023
1024 for (const auto &Set : Sets)
1025 for (const auto &I : Set)
1026 if (!I.isStringAttribute())
1027 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1028 }
1029
Profile(FoldingSetNodeID & ID) const1030 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
1031 Profile(ID, makeArrayRef(begin(), end()));
1032 }
1033
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)1034 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
1035 ArrayRef<AttributeSet> Sets) {
1036 for (const auto &Set : Sets)
1037 ID.AddPointer(Set.SetNode);
1038 }
1039
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const1040 bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
1041 unsigned *Index) const {
1042 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1043 return false;
1044
1045 if (Index) {
1046 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1047 if (begin()[I].hasAttribute(Kind)) {
1048 *Index = I - 1;
1049 break;
1050 }
1051 }
1052 }
1053
1054 return true;
1055 }
1056
1057
1058 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1059 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1060 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1061 }
1062 #endif
1063
1064 //===----------------------------------------------------------------------===//
1065 // AttributeList Construction and Mutation Methods
1066 //===----------------------------------------------------------------------===//
1067
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)1068 AttributeList AttributeList::getImpl(LLVMContext &C,
1069 ArrayRef<AttributeSet> AttrSets) {
1070 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1071
1072 LLVMContextImpl *pImpl = C.pImpl;
1073 FoldingSetNodeID ID;
1074 AttributeListImpl::Profile(ID, AttrSets);
1075
1076 void *InsertPoint;
1077 AttributeListImpl *PA =
1078 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1079
1080 // If we didn't find any existing attributes of the same shape then
1081 // create a new one and insert it.
1082 if (!PA) {
1083 // Coallocate entries after the AttributeListImpl itself.
1084 void *Mem = pImpl->Alloc.Allocate(
1085 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1086 alignof(AttributeListImpl));
1087 PA = new (Mem) AttributeListImpl(AttrSets);
1088 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1089 }
1090
1091 // Return the AttributesList that we found or created.
1092 return AttributeList(PA);
1093 }
1094
1095 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)1096 AttributeList::get(LLVMContext &C,
1097 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1098 // If there are no attributes then return a null AttributesList pointer.
1099 if (Attrs.empty())
1100 return {};
1101
1102 assert(llvm::is_sorted(Attrs,
1103 [](const std::pair<unsigned, Attribute> &LHS,
1104 const std::pair<unsigned, Attribute> &RHS) {
1105 return LHS.first < RHS.first;
1106 }) &&
1107 "Misordered Attributes list!");
1108 assert(llvm::all_of(Attrs,
1109 [](const std::pair<unsigned, Attribute> &Pair) {
1110 return Pair.second.isValid();
1111 }) &&
1112 "Pointless attribute!");
1113
1114 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1115 // list.
1116 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1117 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1118 E = Attrs.end(); I != E; ) {
1119 unsigned Index = I->first;
1120 SmallVector<Attribute, 4> AttrVec;
1121 while (I != E && I->first == Index) {
1122 AttrVec.push_back(I->second);
1123 ++I;
1124 }
1125
1126 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1127 }
1128
1129 return get(C, AttrPairVec);
1130 }
1131
1132 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1133 AttributeList::get(LLVMContext &C,
1134 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1135 // If there are no attributes then return a null AttributesList pointer.
1136 if (Attrs.empty())
1137 return {};
1138
1139 assert(llvm::is_sorted(Attrs,
1140 [](const std::pair<unsigned, AttributeSet> &LHS,
1141 const std::pair<unsigned, AttributeSet> &RHS) {
1142 return LHS.first < RHS.first;
1143 }) &&
1144 "Misordered Attributes list!");
1145 assert(llvm::none_of(Attrs,
1146 [](const std::pair<unsigned, AttributeSet> &Pair) {
1147 return !Pair.second.hasAttributes();
1148 }) &&
1149 "Pointless attribute!");
1150
1151 unsigned MaxIndex = Attrs.back().first;
1152 // If the MaxIndex is FunctionIndex and there are other indices in front
1153 // of it, we need to use the largest of those to get the right size.
1154 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1155 MaxIndex = Attrs[Attrs.size() - 2].first;
1156
1157 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1158 for (const auto &Pair : Attrs)
1159 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1160
1161 return getImpl(C, AttrVec);
1162 }
1163
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)1164 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1165 AttributeSet RetAttrs,
1166 ArrayRef<AttributeSet> ArgAttrs) {
1167 // Scan from the end to find the last argument with attributes. Most
1168 // arguments don't have attributes, so it's nice if we can have fewer unique
1169 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1170 unsigned NumSets = 0;
1171 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1172 if (ArgAttrs[I - 1].hasAttributes()) {
1173 NumSets = I + 2;
1174 break;
1175 }
1176 }
1177 if (NumSets == 0) {
1178 // Check function and return attributes if we didn't have argument
1179 // attributes.
1180 if (RetAttrs.hasAttributes())
1181 NumSets = 2;
1182 else if (FnAttrs.hasAttributes())
1183 NumSets = 1;
1184 }
1185
1186 // If all attribute sets were empty, we can use the empty attribute list.
1187 if (NumSets == 0)
1188 return {};
1189
1190 SmallVector<AttributeSet, 8> AttrSets;
1191 AttrSets.reserve(NumSets);
1192 // If we have any attributes, we always have function attributes.
1193 AttrSets.push_back(FnAttrs);
1194 if (NumSets > 1)
1195 AttrSets.push_back(RetAttrs);
1196 if (NumSets > 2) {
1197 // Drop the empty argument attribute sets at the end.
1198 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1199 AttrSets.insert(AttrSets.end(), ArgAttrs.begin(), ArgAttrs.end());
1200 }
1201
1202 return getImpl(C, AttrSets);
1203 }
1204
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1205 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1206 const AttrBuilder &B) {
1207 if (!B.hasAttributes())
1208 return {};
1209 Index = attrIdxToArrayIdx(Index);
1210 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1211 AttrSets[Index] = AttributeSet::get(C, B);
1212 return getImpl(C, AttrSets);
1213 }
1214
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1215 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1216 ArrayRef<Attribute::AttrKind> Kinds) {
1217 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1218 for (const auto K : Kinds)
1219 Attrs.emplace_back(Index, Attribute::get(C, K));
1220 return get(C, Attrs);
1221 }
1222
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)1223 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1224 ArrayRef<Attribute::AttrKind> Kinds,
1225 ArrayRef<uint64_t> Values) {
1226 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1227 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1228 auto VI = Values.begin();
1229 for (const auto K : Kinds)
1230 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1231 return get(C, Attrs);
1232 }
1233
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1234 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1235 ArrayRef<StringRef> Kinds) {
1236 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1237 for (const auto &K : Kinds)
1238 Attrs.emplace_back(Index, Attribute::get(C, K));
1239 return get(C, Attrs);
1240 }
1241
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1242 AttributeList AttributeList::get(LLVMContext &C,
1243 ArrayRef<AttributeList> Attrs) {
1244 if (Attrs.empty())
1245 return {};
1246 if (Attrs.size() == 1)
1247 return Attrs[0];
1248
1249 unsigned MaxSize = 0;
1250 for (const auto &List : Attrs)
1251 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1252
1253 // If every list was empty, there is no point in merging the lists.
1254 if (MaxSize == 0)
1255 return {};
1256
1257 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1258 for (unsigned I = 0; I < MaxSize; ++I) {
1259 AttrBuilder CurBuilder;
1260 for (const auto &List : Attrs)
1261 CurBuilder.merge(List.getAttributes(I - 1));
1262 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1263 }
1264
1265 return getImpl(C, NewAttrSets);
1266 }
1267
addAttribute(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1268 AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1269 Attribute::AttrKind Kind) const {
1270 if (hasAttribute(Index, Kind)) return *this;
1271 AttrBuilder B;
1272 B.addAttribute(Kind);
1273 return addAttributes(C, Index, B);
1274 }
1275
addAttribute(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1276 AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1277 StringRef Kind,
1278 StringRef Value) const {
1279 AttrBuilder B;
1280 B.addAttribute(Kind, Value);
1281 return addAttributes(C, Index, B);
1282 }
1283
addAttribute(LLVMContext & C,unsigned Index,Attribute A) const1284 AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1285 Attribute A) const {
1286 AttrBuilder B;
1287 B.addAttribute(A);
1288 return addAttributes(C, Index, B);
1289 }
1290
addAttributes(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1291 AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
1292 const AttrBuilder &B) const {
1293 if (!B.hasAttributes())
1294 return *this;
1295
1296 if (!pImpl)
1297 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1298
1299 #ifndef NDEBUG
1300 // FIXME it is not obvious how this should work for alignment. For now, say
1301 // we can't change a known alignment.
1302 const MaybeAlign OldAlign = getAttributes(Index).getAlignment();
1303 const MaybeAlign NewAlign = B.getAlignment();
1304 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
1305 "Attempt to change alignment!");
1306 #endif
1307
1308 Index = attrIdxToArrayIdx(Index);
1309 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1310 if (Index >= AttrSets.size())
1311 AttrSets.resize(Index + 1);
1312
1313 AttrBuilder Merged(AttrSets[Index]);
1314 Merged.merge(B);
1315 AttrSets[Index] = AttributeSet::get(C, Merged);
1316
1317 return getImpl(C, AttrSets);
1318 }
1319
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const1320 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1321 ArrayRef<unsigned> ArgNos,
1322 Attribute A) const {
1323 assert(llvm::is_sorted(ArgNos));
1324
1325 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1326 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1327 if (MaxIndex >= AttrSets.size())
1328 AttrSets.resize(MaxIndex + 1);
1329
1330 for (unsigned ArgNo : ArgNos) {
1331 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1332 AttrBuilder B(AttrSets[Index]);
1333 B.addAttribute(A);
1334 AttrSets[Index] = AttributeSet::get(C, B);
1335 }
1336
1337 return getImpl(C, AttrSets);
1338 }
1339
removeAttribute(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1340 AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
1341 Attribute::AttrKind Kind) const {
1342 if (!hasAttribute(Index, Kind)) return *this;
1343
1344 Index = attrIdxToArrayIdx(Index);
1345 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1346 assert(Index < AttrSets.size());
1347
1348 AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1349
1350 return getImpl(C, AttrSets);
1351 }
1352
removeAttribute(LLVMContext & C,unsigned Index,StringRef Kind) const1353 AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
1354 StringRef Kind) const {
1355 if (!hasAttribute(Index, Kind)) return *this;
1356
1357 Index = attrIdxToArrayIdx(Index);
1358 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1359 assert(Index < AttrSets.size());
1360
1361 AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1362
1363 return getImpl(C, AttrSets);
1364 }
1365
1366 AttributeList
removeAttributes(LLVMContext & C,unsigned Index,const AttrBuilder & AttrsToRemove) const1367 AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
1368 const AttrBuilder &AttrsToRemove) const {
1369 if (!pImpl)
1370 return {};
1371
1372 Index = attrIdxToArrayIdx(Index);
1373 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1374 if (Index >= AttrSets.size())
1375 AttrSets.resize(Index + 1);
1376
1377 AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove);
1378
1379 return getImpl(C, AttrSets);
1380 }
1381
removeAttributes(LLVMContext & C,unsigned WithoutIndex) const1382 AttributeList AttributeList::removeAttributes(LLVMContext &C,
1383 unsigned WithoutIndex) const {
1384 if (!pImpl)
1385 return {};
1386 WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
1387 if (WithoutIndex >= getNumAttrSets())
1388 return *this;
1389 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1390 AttrSets[WithoutIndex] = AttributeSet();
1391 return getImpl(C, AttrSets);
1392 }
1393
addDereferenceableAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1394 AttributeList AttributeList::addDereferenceableAttr(LLVMContext &C,
1395 unsigned Index,
1396 uint64_t Bytes) const {
1397 AttrBuilder B;
1398 B.addDereferenceableAttr(Bytes);
1399 return addAttributes(C, Index, B);
1400 }
1401
1402 AttributeList
addDereferenceableOrNullAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1403 AttributeList::addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
1404 uint64_t Bytes) const {
1405 AttrBuilder B;
1406 B.addDereferenceableOrNullAttr(Bytes);
1407 return addAttributes(C, Index, B);
1408 }
1409
1410 AttributeList
addAllocSizeAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)1411 AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index,
1412 unsigned ElemSizeArg,
1413 const Optional<unsigned> &NumElemsArg) {
1414 AttrBuilder B;
1415 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1416 return addAttributes(C, Index, B);
1417 }
1418
1419 //===----------------------------------------------------------------------===//
1420 // AttributeList Accessor Methods
1421 //===----------------------------------------------------------------------===//
1422
getParamAttributes(unsigned ArgNo) const1423 AttributeSet AttributeList::getParamAttributes(unsigned ArgNo) const {
1424 return getAttributes(ArgNo + FirstArgIndex);
1425 }
1426
getRetAttributes() const1427 AttributeSet AttributeList::getRetAttributes() const {
1428 return getAttributes(ReturnIndex);
1429 }
1430
getFnAttributes() const1431 AttributeSet AttributeList::getFnAttributes() const {
1432 return getAttributes(FunctionIndex);
1433 }
1434
hasAttribute(unsigned Index,Attribute::AttrKind Kind) const1435 bool AttributeList::hasAttribute(unsigned Index,
1436 Attribute::AttrKind Kind) const {
1437 return getAttributes(Index).hasAttribute(Kind);
1438 }
1439
hasAttribute(unsigned Index,StringRef Kind) const1440 bool AttributeList::hasAttribute(unsigned Index, StringRef Kind) const {
1441 return getAttributes(Index).hasAttribute(Kind);
1442 }
1443
hasAttributes(unsigned Index) const1444 bool AttributeList::hasAttributes(unsigned Index) const {
1445 return getAttributes(Index).hasAttributes();
1446 }
1447
hasFnAttribute(Attribute::AttrKind Kind) const1448 bool AttributeList::hasFnAttribute(Attribute::AttrKind Kind) const {
1449 return pImpl && pImpl->hasFnAttribute(Kind);
1450 }
1451
hasFnAttribute(StringRef Kind) const1452 bool AttributeList::hasFnAttribute(StringRef Kind) const {
1453 return hasAttribute(AttributeList::FunctionIndex, Kind);
1454 }
1455
hasParamAttribute(unsigned ArgNo,Attribute::AttrKind Kind) const1456 bool AttributeList::hasParamAttribute(unsigned ArgNo,
1457 Attribute::AttrKind Kind) const {
1458 return hasAttribute(ArgNo + FirstArgIndex, Kind);
1459 }
1460
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1461 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1462 unsigned *Index) const {
1463 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1464 }
1465
getAttribute(unsigned Index,Attribute::AttrKind Kind) const1466 Attribute AttributeList::getAttribute(unsigned Index,
1467 Attribute::AttrKind Kind) const {
1468 return getAttributes(Index).getAttribute(Kind);
1469 }
1470
getAttribute(unsigned Index,StringRef Kind) const1471 Attribute AttributeList::getAttribute(unsigned Index, StringRef Kind) const {
1472 return getAttributes(Index).getAttribute(Kind);
1473 }
1474
getRetAlignment() const1475 MaybeAlign AttributeList::getRetAlignment() const {
1476 return getAttributes(ReturnIndex).getAlignment();
1477 }
1478
getParamAlignment(unsigned ArgNo) const1479 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1480 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1481 }
1482
getParamByValType(unsigned Index) const1483 Type *AttributeList::getParamByValType(unsigned Index) const {
1484 return getAttributes(Index+FirstArgIndex).getByValType();
1485 }
1486
getParamStructRetType(unsigned Index) const1487 Type *AttributeList::getParamStructRetType(unsigned Index) const {
1488 return getAttributes(Index + FirstArgIndex).getStructRetType();
1489 }
1490
getParamByRefType(unsigned Index) const1491 Type *AttributeList::getParamByRefType(unsigned Index) const {
1492 return getAttributes(Index + FirstArgIndex).getByRefType();
1493 }
1494
getParamPreallocatedType(unsigned Index) const1495 Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1496 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1497 }
1498
getStackAlignment(unsigned Index) const1499 MaybeAlign AttributeList::getStackAlignment(unsigned Index) const {
1500 return getAttributes(Index).getStackAlignment();
1501 }
1502
getDereferenceableBytes(unsigned Index) const1503 uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const {
1504 return getAttributes(Index).getDereferenceableBytes();
1505 }
1506
getDereferenceableOrNullBytes(unsigned Index) const1507 uint64_t AttributeList::getDereferenceableOrNullBytes(unsigned Index) const {
1508 return getAttributes(Index).getDereferenceableOrNullBytes();
1509 }
1510
1511 std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs(unsigned Index) const1512 AttributeList::getAllocSizeArgs(unsigned Index) const {
1513 return getAttributes(Index).getAllocSizeArgs();
1514 }
1515
getAsString(unsigned Index,bool InAttrGrp) const1516 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1517 return getAttributes(Index).getAsString(InAttrGrp);
1518 }
1519
getAttributes(unsigned Index) const1520 AttributeSet AttributeList::getAttributes(unsigned Index) const {
1521 Index = attrIdxToArrayIdx(Index);
1522 if (!pImpl || Index >= getNumAttrSets())
1523 return {};
1524 return pImpl->begin()[Index];
1525 }
1526
begin() const1527 AttributeList::iterator AttributeList::begin() const {
1528 return pImpl ? pImpl->begin() : nullptr;
1529 }
1530
end() const1531 AttributeList::iterator AttributeList::end() const {
1532 return pImpl ? pImpl->end() : nullptr;
1533 }
1534
1535 //===----------------------------------------------------------------------===//
1536 // AttributeList Introspection Methods
1537 //===----------------------------------------------------------------------===//
1538
getNumAttrSets() const1539 unsigned AttributeList::getNumAttrSets() const {
1540 return pImpl ? pImpl->NumAttrSets : 0;
1541 }
1542
1543 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1544 LLVM_DUMP_METHOD void AttributeList::dump() const {
1545 dbgs() << "PAL[\n";
1546
1547 for (unsigned i = index_begin(), e = index_end(); i != e; ++i) {
1548 if (getAttributes(i).hasAttributes())
1549 dbgs() << " { " << i << " => " << getAsString(i) << " }\n";
1550 }
1551
1552 dbgs() << "]\n";
1553 }
1554 #endif
1555
1556 //===----------------------------------------------------------------------===//
1557 // AttrBuilder Method Implementations
1558 //===----------------------------------------------------------------------===//
1559
1560 // FIXME: Remove this ctor, use AttributeSet.
AttrBuilder(AttributeList AL,unsigned Index)1561 AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) {
1562 AttributeSet AS = AL.getAttributes(Index);
1563 for (const auto &A : AS)
1564 addAttribute(A);
1565 }
1566
AttrBuilder(AttributeSet AS)1567 AttrBuilder::AttrBuilder(AttributeSet AS) {
1568 for (const auto &A : AS)
1569 addAttribute(A);
1570 }
1571
clear()1572 void AttrBuilder::clear() {
1573 Attrs.reset();
1574 TargetDepAttrs.clear();
1575 Alignment.reset();
1576 StackAlignment.reset();
1577 DerefBytes = DerefOrNullBytes = 0;
1578 AllocSizeArgs = 0;
1579 ByValType = nullptr;
1580 StructRetType = nullptr;
1581 ByRefType = nullptr;
1582 PreallocatedType = nullptr;
1583 }
1584
addAttribute(Attribute Attr)1585 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1586 if (Attr.isStringAttribute()) {
1587 addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
1588 return *this;
1589 }
1590
1591 Attribute::AttrKind Kind = Attr.getKindAsEnum();
1592 Attrs[Kind] = true;
1593
1594 if (Kind == Attribute::Alignment)
1595 Alignment = Attr.getAlignment();
1596 else if (Kind == Attribute::StackAlignment)
1597 StackAlignment = Attr.getStackAlignment();
1598 else if (Kind == Attribute::ByVal)
1599 ByValType = Attr.getValueAsType();
1600 else if (Kind == Attribute::StructRet)
1601 StructRetType = Attr.getValueAsType();
1602 else if (Kind == Attribute::ByRef)
1603 ByRefType = Attr.getValueAsType();
1604 else if (Kind == Attribute::Preallocated)
1605 PreallocatedType = Attr.getValueAsType();
1606 else if (Kind == Attribute::Dereferenceable)
1607 DerefBytes = Attr.getDereferenceableBytes();
1608 else if (Kind == Attribute::DereferenceableOrNull)
1609 DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
1610 else if (Kind == Attribute::AllocSize)
1611 AllocSizeArgs = Attr.getValueAsInt();
1612 return *this;
1613 }
1614
addAttribute(StringRef A,StringRef V)1615 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1616 TargetDepAttrs[std::string(A)] = std::string(V);
1617 return *this;
1618 }
1619
removeAttribute(Attribute::AttrKind Val)1620 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1621 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1622 Attrs[Val] = false;
1623
1624 if (Val == Attribute::Alignment)
1625 Alignment.reset();
1626 else if (Val == Attribute::StackAlignment)
1627 StackAlignment.reset();
1628 else if (Val == Attribute::ByVal)
1629 ByValType = nullptr;
1630 else if (Val == Attribute::StructRet)
1631 StructRetType = nullptr;
1632 else if (Val == Attribute::ByRef)
1633 ByRefType = nullptr;
1634 else if (Val == Attribute::Preallocated)
1635 PreallocatedType = nullptr;
1636 else if (Val == Attribute::Dereferenceable)
1637 DerefBytes = 0;
1638 else if (Val == Attribute::DereferenceableOrNull)
1639 DerefOrNullBytes = 0;
1640 else if (Val == Attribute::AllocSize)
1641 AllocSizeArgs = 0;
1642
1643 return *this;
1644 }
1645
removeAttributes(AttributeList A,uint64_t Index)1646 AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) {
1647 remove(A.getAttributes(Index));
1648 return *this;
1649 }
1650
removeAttribute(StringRef A)1651 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1652 auto I = TargetDepAttrs.find(A);
1653 if (I != TargetDepAttrs.end())
1654 TargetDepAttrs.erase(I);
1655 return *this;
1656 }
1657
getAllocSizeArgs() const1658 std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
1659 return unpackAllocSizeArgs(AllocSizeArgs);
1660 }
1661
addAlignmentAttr(MaybeAlign Align)1662 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1663 if (!Align)
1664 return *this;
1665
1666 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1667
1668 Attrs[Attribute::Alignment] = true;
1669 Alignment = Align;
1670 return *this;
1671 }
1672
addStackAlignmentAttr(MaybeAlign Align)1673 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1674 // Default alignment, allow the target to define how to align it.
1675 if (!Align)
1676 return *this;
1677
1678 assert(*Align <= 0x100 && "Alignment too large.");
1679
1680 Attrs[Attribute::StackAlignment] = true;
1681 StackAlignment = Align;
1682 return *this;
1683 }
1684
addDereferenceableAttr(uint64_t Bytes)1685 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1686 if (Bytes == 0) return *this;
1687
1688 Attrs[Attribute::Dereferenceable] = true;
1689 DerefBytes = Bytes;
1690 return *this;
1691 }
1692
addDereferenceableOrNullAttr(uint64_t Bytes)1693 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1694 if (Bytes == 0)
1695 return *this;
1696
1697 Attrs[Attribute::DereferenceableOrNull] = true;
1698 DerefOrNullBytes = Bytes;
1699 return *this;
1700 }
1701
addAllocSizeAttr(unsigned ElemSize,const Optional<unsigned> & NumElems)1702 AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1703 const Optional<unsigned> &NumElems) {
1704 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1705 }
1706
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1707 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1708 // (0, 0) is our "not present" value, so we need to check for it here.
1709 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1710
1711 Attrs[Attribute::AllocSize] = true;
1712 // Reuse existing machinery to store this as a single 64-bit integer so we can
1713 // save a few bytes over using a pair<unsigned, Optional<unsigned>>.
1714 AllocSizeArgs = RawArgs;
1715 return *this;
1716 }
1717
addByValAttr(Type * Ty)1718 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
1719 Attrs[Attribute::ByVal] = true;
1720 ByValType = Ty;
1721 return *this;
1722 }
1723
addStructRetAttr(Type * Ty)1724 AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
1725 Attrs[Attribute::StructRet] = true;
1726 StructRetType = Ty;
1727 return *this;
1728 }
1729
addByRefAttr(Type * Ty)1730 AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
1731 Attrs[Attribute::ByRef] = true;
1732 ByRefType = Ty;
1733 return *this;
1734 }
1735
addPreallocatedAttr(Type * Ty)1736 AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
1737 Attrs[Attribute::Preallocated] = true;
1738 PreallocatedType = Ty;
1739 return *this;
1740 }
1741
merge(const AttrBuilder & B)1742 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1743 // FIXME: What if both have alignments, but they don't match?!
1744 if (!Alignment)
1745 Alignment = B.Alignment;
1746
1747 if (!StackAlignment)
1748 StackAlignment = B.StackAlignment;
1749
1750 if (!DerefBytes)
1751 DerefBytes = B.DerefBytes;
1752
1753 if (!DerefOrNullBytes)
1754 DerefOrNullBytes = B.DerefOrNullBytes;
1755
1756 if (!AllocSizeArgs)
1757 AllocSizeArgs = B.AllocSizeArgs;
1758
1759 if (!ByValType)
1760 ByValType = B.ByValType;
1761
1762 if (!StructRetType)
1763 StructRetType = B.StructRetType;
1764
1765 if (!ByRefType)
1766 ByRefType = B.ByRefType;
1767
1768 if (!PreallocatedType)
1769 PreallocatedType = B.PreallocatedType;
1770
1771 Attrs |= B.Attrs;
1772
1773 for (const auto &I : B.td_attrs())
1774 TargetDepAttrs[I.first] = I.second;
1775
1776 return *this;
1777 }
1778
remove(const AttrBuilder & B)1779 AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
1780 // FIXME: What if both have alignments, but they don't match?!
1781 if (B.Alignment)
1782 Alignment.reset();
1783
1784 if (B.StackAlignment)
1785 StackAlignment.reset();
1786
1787 if (B.DerefBytes)
1788 DerefBytes = 0;
1789
1790 if (B.DerefOrNullBytes)
1791 DerefOrNullBytes = 0;
1792
1793 if (B.AllocSizeArgs)
1794 AllocSizeArgs = 0;
1795
1796 if (B.ByValType)
1797 ByValType = nullptr;
1798
1799 if (B.StructRetType)
1800 StructRetType = nullptr;
1801
1802 if (B.ByRefType)
1803 ByRefType = nullptr;
1804
1805 if (B.PreallocatedType)
1806 PreallocatedType = nullptr;
1807
1808 Attrs &= ~B.Attrs;
1809
1810 for (const auto &I : B.td_attrs())
1811 TargetDepAttrs.erase(I.first);
1812
1813 return *this;
1814 }
1815
overlaps(const AttrBuilder & B) const1816 bool AttrBuilder::overlaps(const AttrBuilder &B) const {
1817 // First check if any of the target independent attributes overlap.
1818 if ((Attrs & B.Attrs).any())
1819 return true;
1820
1821 // Then check if any target dependent ones do.
1822 for (const auto &I : td_attrs())
1823 if (B.contains(I.first))
1824 return true;
1825
1826 return false;
1827 }
1828
contains(StringRef A) const1829 bool AttrBuilder::contains(StringRef A) const {
1830 return TargetDepAttrs.find(A) != TargetDepAttrs.end();
1831 }
1832
hasAttributes() const1833 bool AttrBuilder::hasAttributes() const {
1834 return !Attrs.none() || !TargetDepAttrs.empty();
1835 }
1836
hasAttributes(AttributeList AL,uint64_t Index) const1837 bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const {
1838 AttributeSet AS = AL.getAttributes(Index);
1839
1840 for (const auto &Attr : AS) {
1841 if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
1842 if (contains(Attr.getKindAsEnum()))
1843 return true;
1844 } else {
1845 assert(Attr.isStringAttribute() && "Invalid attribute kind!");
1846 return contains(Attr.getKindAsString());
1847 }
1848 }
1849
1850 return false;
1851 }
1852
hasAlignmentAttr() const1853 bool AttrBuilder::hasAlignmentAttr() const {
1854 return Alignment != 0;
1855 }
1856
operator ==(const AttrBuilder & B)1857 bool AttrBuilder::operator==(const AttrBuilder &B) {
1858 if (Attrs != B.Attrs)
1859 return false;
1860
1861 for (td_const_iterator I = TargetDepAttrs.begin(),
1862 E = TargetDepAttrs.end(); I != E; ++I)
1863 if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())
1864 return false;
1865
1866 return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
1867 DerefBytes == B.DerefBytes && ByValType == B.ByValType &&
1868 StructRetType == B.StructRetType && ByRefType == B.ByRefType &&
1869 PreallocatedType == B.PreallocatedType;
1870 }
1871
1872 //===----------------------------------------------------------------------===//
1873 // AttributeFuncs Function Defintions
1874 //===----------------------------------------------------------------------===//
1875
1876 /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty)1877 AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
1878 AttrBuilder Incompatible;
1879
1880 if (!Ty->isIntegerTy())
1881 // Attribute that only apply to integers.
1882 Incompatible.addAttribute(Attribute::SExt)
1883 .addAttribute(Attribute::ZExt);
1884
1885 if (!Ty->isPointerTy())
1886 // Attribute that only apply to pointers.
1887 Incompatible.addAttribute(Attribute::Nest)
1888 .addAttribute(Attribute::NoAlias)
1889 .addAttribute(Attribute::NoCapture)
1890 .addAttribute(Attribute::NonNull)
1891 .addAlignmentAttr(1) // the int here is ignored
1892 .addDereferenceableAttr(1) // the int here is ignored
1893 .addDereferenceableOrNullAttr(1) // the int here is ignored
1894 .addAttribute(Attribute::ReadNone)
1895 .addAttribute(Attribute::ReadOnly)
1896 .addAttribute(Attribute::InAlloca)
1897 .addPreallocatedAttr(Ty)
1898 .addByValAttr(Ty)
1899 .addStructRetAttr(Ty)
1900 .addByRefAttr(Ty);
1901
1902 // Some attributes can apply to all "values" but there are no `void` values.
1903 if (Ty->isVoidTy())
1904 Incompatible.addAttribute(Attribute::NoUndef);
1905
1906 return Incompatible;
1907 }
1908
1909 template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)1910 static bool isEqual(const Function &Caller, const Function &Callee) {
1911 return Caller.getFnAttribute(AttrClass::getKind()) ==
1912 Callee.getFnAttribute(AttrClass::getKind());
1913 }
1914
1915 /// Compute the logical AND of the attributes of the caller and the
1916 /// callee.
1917 ///
1918 /// This function sets the caller's attribute to false if the callee's attribute
1919 /// is false.
1920 template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)1921 static void setAND(Function &Caller, const Function &Callee) {
1922 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
1923 !AttrClass::isSet(Callee, AttrClass::getKind()))
1924 AttrClass::set(Caller, AttrClass::getKind(), false);
1925 }
1926
1927 /// Compute the logical OR of the attributes of the caller and the
1928 /// callee.
1929 ///
1930 /// This function sets the caller's attribute to true if the callee's attribute
1931 /// is true.
1932 template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)1933 static void setOR(Function &Caller, const Function &Callee) {
1934 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
1935 AttrClass::isSet(Callee, AttrClass::getKind()))
1936 AttrClass::set(Caller, AttrClass::getKind(), true);
1937 }
1938
1939 /// If the inlined function had a higher stack protection level than the
1940 /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)1941 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1942 #ifndef NDEBUG
1943 if (!Callee.hasFnAttribute(Attribute::AlwaysInline)) {
1944 assert(!(!Callee.hasStackProtectorFnAttr() &&
1945 Caller.hasStackProtectorFnAttr()) &&
1946 "stack protected caller but callee requested no stack protector");
1947 assert(!(!Caller.hasStackProtectorFnAttr() &&
1948 Callee.hasStackProtectorFnAttr()) &&
1949 "stack protected callee but caller requested no stack protector");
1950 }
1951 #endif
1952 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1953 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1954 // clutter to the IR.
1955 AttrBuilder OldSSPAttr;
1956 OldSSPAttr.addAttribute(Attribute::StackProtect)
1957 .addAttribute(Attribute::StackProtectStrong)
1958 .addAttribute(Attribute::StackProtectReq);
1959
1960 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1961 Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
1962 Caller.addFnAttr(Attribute::StackProtectReq);
1963 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
1964 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1965 Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
1966 Caller.addFnAttr(Attribute::StackProtectStrong);
1967 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
1968 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
1969 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
1970 Caller.addFnAttr(Attribute::StackProtect);
1971 }
1972
1973 /// If the inlined function required stack probes, then ensure that
1974 /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)1975 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
1976 if (!Caller.hasFnAttribute("probe-stack") &&
1977 Callee.hasFnAttribute("probe-stack")) {
1978 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
1979 }
1980 }
1981
1982 /// If the inlined function defines the size of guard region
1983 /// on the stack, then ensure that the calling function defines a guard region
1984 /// that is no larger.
1985 static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)1986 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
1987 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
1988 if (CalleeAttr.isValid()) {
1989 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
1990 if (CallerAttr.isValid()) {
1991 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
1992 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
1993 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
1994
1995 if (CallerStackProbeSize > CalleeStackProbeSize) {
1996 Caller.addFnAttr(CalleeAttr);
1997 }
1998 } else {
1999 Caller.addFnAttr(CalleeAttr);
2000 }
2001 }
2002 }
2003
2004 /// If the inlined function defines a min legal vector width, then ensure
2005 /// the calling function has the same or larger min legal vector width. If the
2006 /// caller has the attribute, but the callee doesn't, we need to remove the
2007 /// attribute from the caller since we can't make any guarantees about the
2008 /// caller's requirements.
2009 /// This function is called after the inlining decision has been made so we have
2010 /// to merge the attribute this way. Heuristics that would use
2011 /// min-legal-vector-width to determine inline compatibility would need to be
2012 /// handled as part of inline cost analysis.
2013 static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)2014 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
2015 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2016 if (CallerAttr.isValid()) {
2017 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2018 if (CalleeAttr.isValid()) {
2019 uint64_t CallerVectorWidth, CalleeVectorWidth;
2020 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2021 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2022 if (CallerVectorWidth < CalleeVectorWidth)
2023 Caller.addFnAttr(CalleeAttr);
2024 } else {
2025 // If the callee doesn't have the attribute then we don't know anything
2026 // and must drop the attribute from the caller.
2027 Caller.removeFnAttr("min-legal-vector-width");
2028 }
2029 }
2030 }
2031
2032 /// If the inlined function has null_pointer_is_valid attribute,
2033 /// set this attribute in the caller post inlining.
2034 static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)2035 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2036 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2037 Caller.addFnAttr(Attribute::NullPointerIsValid);
2038 }
2039 }
2040
2041 struct EnumAttr {
isSetEnumAttr2042 static bool isSet(const Function &Fn,
2043 Attribute::AttrKind Kind) {
2044 return Fn.hasFnAttribute(Kind);
2045 }
2046
setEnumAttr2047 static void set(Function &Fn,
2048 Attribute::AttrKind Kind, bool Val) {
2049 if (Val)
2050 Fn.addFnAttr(Kind);
2051 else
2052 Fn.removeFnAttr(Kind);
2053 }
2054 };
2055
2056 struct StrBoolAttr {
isSetStrBoolAttr2057 static bool isSet(const Function &Fn,
2058 StringRef Kind) {
2059 auto A = Fn.getFnAttribute(Kind);
2060 return A.getValueAsString().equals("true");
2061 }
2062
setStrBoolAttr2063 static void set(Function &Fn,
2064 StringRef Kind, bool Val) {
2065 Fn.addFnAttr(Kind, Val ? "true" : "false");
2066 }
2067 };
2068
2069 #define GET_ATTR_NAMES
2070 #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2071 struct ENUM_NAME##Attr : EnumAttr { \
2072 static enum Attribute::AttrKind getKind() { \
2073 return llvm::Attribute::ENUM_NAME; \
2074 } \
2075 };
2076 #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2077 struct ENUM_NAME##Attr : StrBoolAttr { \
2078 static StringRef getKind() { return #DISPLAY_NAME; } \
2079 };
2080 #include "llvm/IR/Attributes.inc"
2081
2082 #define GET_ATTR_COMPAT_FUNC
2083 #include "llvm/IR/Attributes.inc"
2084
areInlineCompatible(const Function & Caller,const Function & Callee)2085 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2086 const Function &Callee) {
2087 return hasCompatibleFnAttrs(Caller, Callee);
2088 }
2089
mergeAttributesForInlining(Function & Caller,const Function & Callee)2090 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2091 const Function &Callee) {
2092 mergeFnAttrs(Caller, Callee);
2093 }
2094