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/Twine.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/Debug.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/MathExtras.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include <algorithm>
36 #include <cassert>
37 #include <climits>
38 #include <cstddef>
39 #include <cstdint>
40 #include <limits>
41 #include <string>
42 #include <tuple>
43 #include <utility>
44
45 using namespace llvm;
46
47 //===----------------------------------------------------------------------===//
48 // Attribute Construction Methods
49 //===----------------------------------------------------------------------===//
50
51 // allocsize has two integer arguments, but because they're both 32 bits, we can
52 // pack them into one 64-bit value, at the cost of making said value
53 // nonsensical.
54 //
55 // In order to do this, we need to reserve one value of the second (optional)
56 // allocsize argument to signify "not present."
57 static const unsigned AllocSizeNumElemsNotPresent = -1;
58
packAllocSizeArgs(unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)59 static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
60 const Optional<unsigned> &NumElemsArg) {
61 assert((!NumElemsArg.hasValue() ||
62 *NumElemsArg != AllocSizeNumElemsNotPresent) &&
63 "Attempting to pack a reserved value");
64
65 return uint64_t(ElemSizeArg) << 32 |
66 NumElemsArg.getValueOr(AllocSizeNumElemsNotPresent);
67 }
68
69 static std::pair<unsigned, Optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)70 unpackAllocSizeArgs(uint64_t Num) {
71 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
72 unsigned ElemSizeArg = Num >> 32;
73
74 Optional<unsigned> NumElemsArg;
75 if (NumElems != AllocSizeNumElemsNotPresent)
76 NumElemsArg = NumElems;
77 return std::make_pair(ElemSizeArg, NumElemsArg);
78 }
79
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)80 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
81 uint64_t Val) {
82 LLVMContextImpl *pImpl = Context.pImpl;
83 FoldingSetNodeID ID;
84 ID.AddInteger(Kind);
85 if (Val) ID.AddInteger(Val);
86
87 void *InsertPoint;
88 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
89
90 if (!PA) {
91 // If we didn't find any existing attributes of the same shape then create a
92 // new one and insert it.
93 if (!Val)
94 PA = new EnumAttributeImpl(Kind);
95 else
96 PA = new IntAttributeImpl(Kind, Val);
97 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
98 }
99
100 // Return the Attribute that we found or created.
101 return Attribute(PA);
102 }
103
get(LLVMContext & Context,StringRef Kind,StringRef Val)104 Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
105 LLVMContextImpl *pImpl = Context.pImpl;
106 FoldingSetNodeID ID;
107 ID.AddString(Kind);
108 if (!Val.empty()) ID.AddString(Val);
109
110 void *InsertPoint;
111 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
112
113 if (!PA) {
114 // If we didn't find any existing attributes of the same shape then create a
115 // new one and insert it.
116 PA = new StringAttributeImpl(Kind, Val);
117 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
118 }
119
120 // Return the Attribute that we found or created.
121 return Attribute(PA);
122 }
123
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)124 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
125 Type *Ty) {
126 LLVMContextImpl *pImpl = Context.pImpl;
127 FoldingSetNodeID ID;
128 ID.AddInteger(Kind);
129 ID.AddPointer(Ty);
130
131 void *InsertPoint;
132 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
133
134 if (!PA) {
135 // If we didn't find any existing attributes of the same shape then create a
136 // new one and insert it.
137 PA = new TypeAttributeImpl(Kind, Ty);
138 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
139 }
140
141 // Return the Attribute that we found or created.
142 return Attribute(PA);
143 }
144
getWithAlignment(LLVMContext & Context,Align A)145 Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
146 assert(A <= 0x40000000 && "Alignment too large.");
147 return get(Context, Alignment, A.value());
148 }
149
getWithStackAlignment(LLVMContext & Context,Align A)150 Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
151 assert(A <= 0x100 && "Alignment too large.");
152 return get(Context, StackAlignment, A.value());
153 }
154
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)155 Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
156 uint64_t Bytes) {
157 assert(Bytes && "Bytes must be non-zero.");
158 return get(Context, Dereferenceable, Bytes);
159 }
160
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)161 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
162 uint64_t Bytes) {
163 assert(Bytes && "Bytes must be non-zero.");
164 return get(Context, DereferenceableOrNull, Bytes);
165 }
166
getWithByValType(LLVMContext & Context,Type * Ty)167 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
168 return get(Context, ByVal, Ty);
169 }
170
171 Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)172 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
173 const Optional<unsigned> &NumElemsArg) {
174 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
175 "Invalid allocsize arguments -- given allocsize(0, 0)");
176 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
177 }
178
179 //===----------------------------------------------------------------------===//
180 // Attribute Accessor Methods
181 //===----------------------------------------------------------------------===//
182
isEnumAttribute() const183 bool Attribute::isEnumAttribute() const {
184 return pImpl && pImpl->isEnumAttribute();
185 }
186
isIntAttribute() const187 bool Attribute::isIntAttribute() const {
188 return pImpl && pImpl->isIntAttribute();
189 }
190
isStringAttribute() const191 bool Attribute::isStringAttribute() const {
192 return pImpl && pImpl->isStringAttribute();
193 }
194
isTypeAttribute() const195 bool Attribute::isTypeAttribute() const {
196 return pImpl && pImpl->isTypeAttribute();
197 }
198
getKindAsEnum() const199 Attribute::AttrKind Attribute::getKindAsEnum() const {
200 if (!pImpl) return None;
201 assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
202 "Invalid attribute type to get the kind as an enum!");
203 return pImpl->getKindAsEnum();
204 }
205
getValueAsInt() const206 uint64_t Attribute::getValueAsInt() const {
207 if (!pImpl) return 0;
208 assert(isIntAttribute() &&
209 "Expected the attribute to be an integer attribute!");
210 return pImpl->getValueAsInt();
211 }
212
getKindAsString() const213 StringRef Attribute::getKindAsString() const {
214 if (!pImpl) return {};
215 assert(isStringAttribute() &&
216 "Invalid attribute type to get the kind as a string!");
217 return pImpl->getKindAsString();
218 }
219
getValueAsString() const220 StringRef Attribute::getValueAsString() const {
221 if (!pImpl) return {};
222 assert(isStringAttribute() &&
223 "Invalid attribute type to get the value as a string!");
224 return pImpl->getValueAsString();
225 }
226
getValueAsType() const227 Type *Attribute::getValueAsType() const {
228 if (!pImpl) return {};
229 assert(isTypeAttribute() &&
230 "Invalid attribute type to get the value as a type!");
231 return pImpl->getValueAsType();
232 }
233
234
hasAttribute(AttrKind Kind) const235 bool Attribute::hasAttribute(AttrKind Kind) const {
236 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
237 }
238
hasAttribute(StringRef Kind) const239 bool Attribute::hasAttribute(StringRef Kind) const {
240 if (!isStringAttribute()) return false;
241 return pImpl && pImpl->hasAttribute(Kind);
242 }
243
getAlignment() const244 MaybeAlign Attribute::getAlignment() const {
245 assert(hasAttribute(Attribute::Alignment) &&
246 "Trying to get alignment from non-alignment attribute!");
247 return MaybeAlign(pImpl->getValueAsInt());
248 }
249
getStackAlignment() const250 MaybeAlign Attribute::getStackAlignment() const {
251 assert(hasAttribute(Attribute::StackAlignment) &&
252 "Trying to get alignment from non-alignment attribute!");
253 return MaybeAlign(pImpl->getValueAsInt());
254 }
255
getDereferenceableBytes() const256 uint64_t Attribute::getDereferenceableBytes() const {
257 assert(hasAttribute(Attribute::Dereferenceable) &&
258 "Trying to get dereferenceable bytes from "
259 "non-dereferenceable attribute!");
260 return pImpl->getValueAsInt();
261 }
262
getDereferenceableOrNullBytes() const263 uint64_t Attribute::getDereferenceableOrNullBytes() const {
264 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
265 "Trying to get dereferenceable bytes from "
266 "non-dereferenceable attribute!");
267 return pImpl->getValueAsInt();
268 }
269
getAllocSizeArgs() const270 std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
271 assert(hasAttribute(Attribute::AllocSize) &&
272 "Trying to get allocsize args from non-allocsize attribute");
273 return unpackAllocSizeArgs(pImpl->getValueAsInt());
274 }
275
getAsString(bool InAttrGrp) const276 std::string Attribute::getAsString(bool InAttrGrp) const {
277 if (!pImpl) return {};
278
279 if (hasAttribute(Attribute::SanitizeAddress))
280 return "sanitize_address";
281 if (hasAttribute(Attribute::SanitizeHWAddress))
282 return "sanitize_hwaddress";
283 if (hasAttribute(Attribute::SanitizeMemTag))
284 return "sanitize_memtag";
285 if (hasAttribute(Attribute::AlwaysInline))
286 return "alwaysinline";
287 if (hasAttribute(Attribute::ArgMemOnly))
288 return "argmemonly";
289 if (hasAttribute(Attribute::Builtin))
290 return "builtin";
291 if (hasAttribute(Attribute::Convergent))
292 return "convergent";
293 if (hasAttribute(Attribute::SwiftError))
294 return "swifterror";
295 if (hasAttribute(Attribute::SwiftSelf))
296 return "swiftself";
297 if (hasAttribute(Attribute::InaccessibleMemOnly))
298 return "inaccessiblememonly";
299 if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
300 return "inaccessiblemem_or_argmemonly";
301 if (hasAttribute(Attribute::InAlloca))
302 return "inalloca";
303 if (hasAttribute(Attribute::InlineHint))
304 return "inlinehint";
305 if (hasAttribute(Attribute::InReg))
306 return "inreg";
307 if (hasAttribute(Attribute::JumpTable))
308 return "jumptable";
309 if (hasAttribute(Attribute::MinSize))
310 return "minsize";
311 if (hasAttribute(Attribute::Naked))
312 return "naked";
313 if (hasAttribute(Attribute::Nest))
314 return "nest";
315 if (hasAttribute(Attribute::NoAlias))
316 return "noalias";
317 if (hasAttribute(Attribute::NoBuiltin))
318 return "nobuiltin";
319 if (hasAttribute(Attribute::NoCapture))
320 return "nocapture";
321 if (hasAttribute(Attribute::NoDuplicate))
322 return "noduplicate";
323 if (hasAttribute(Attribute::NoFree))
324 return "nofree";
325 if (hasAttribute(Attribute::NoImplicitFloat))
326 return "noimplicitfloat";
327 if (hasAttribute(Attribute::NoInline))
328 return "noinline";
329 if (hasAttribute(Attribute::NonLazyBind))
330 return "nonlazybind";
331 if (hasAttribute(Attribute::NonNull))
332 return "nonnull";
333 if (hasAttribute(Attribute::NoRedZone))
334 return "noredzone";
335 if (hasAttribute(Attribute::NoReturn))
336 return "noreturn";
337 if (hasAttribute(Attribute::NoSync))
338 return "nosync";
339 if (hasAttribute(Attribute::WillReturn))
340 return "willreturn";
341 if (hasAttribute(Attribute::NoCfCheck))
342 return "nocf_check";
343 if (hasAttribute(Attribute::NoRecurse))
344 return "norecurse";
345 if (hasAttribute(Attribute::NoUnwind))
346 return "nounwind";
347 if (hasAttribute(Attribute::OptForFuzzing))
348 return "optforfuzzing";
349 if (hasAttribute(Attribute::OptimizeNone))
350 return "optnone";
351 if (hasAttribute(Attribute::OptimizeForSize))
352 return "optsize";
353 if (hasAttribute(Attribute::ReadNone))
354 return "readnone";
355 if (hasAttribute(Attribute::ReadOnly))
356 return "readonly";
357 if (hasAttribute(Attribute::WriteOnly))
358 return "writeonly";
359 if (hasAttribute(Attribute::Returned))
360 return "returned";
361 if (hasAttribute(Attribute::ReturnsTwice))
362 return "returns_twice";
363 if (hasAttribute(Attribute::SExt))
364 return "signext";
365 if (hasAttribute(Attribute::SpeculativeLoadHardening))
366 return "speculative_load_hardening";
367 if (hasAttribute(Attribute::Speculatable))
368 return "speculatable";
369 if (hasAttribute(Attribute::StackProtect))
370 return "ssp";
371 if (hasAttribute(Attribute::StackProtectReq))
372 return "sspreq";
373 if (hasAttribute(Attribute::StackProtectStrong))
374 return "sspstrong";
375 if (hasAttribute(Attribute::SafeStack))
376 return "safestack";
377 if (hasAttribute(Attribute::ShadowCallStack))
378 return "shadowcallstack";
379 if (hasAttribute(Attribute::StrictFP))
380 return "strictfp";
381 if (hasAttribute(Attribute::StructRet))
382 return "sret";
383 if (hasAttribute(Attribute::SanitizeThread))
384 return "sanitize_thread";
385 if (hasAttribute(Attribute::SanitizeMemory))
386 return "sanitize_memory";
387 if (hasAttribute(Attribute::UWTable))
388 return "uwtable";
389 if (hasAttribute(Attribute::ZExt))
390 return "zeroext";
391 if (hasAttribute(Attribute::Cold))
392 return "cold";
393 if (hasAttribute(Attribute::ImmArg))
394 return "immarg";
395
396 if (hasAttribute(Attribute::ByVal)) {
397 std::string Result;
398 Result += "byval";
399 if (Type *Ty = getValueAsType()) {
400 raw_string_ostream OS(Result);
401 Result += '(';
402 Ty->print(OS, false, true);
403 OS.flush();
404 Result += ')';
405 }
406 return Result;
407 }
408
409 // FIXME: These should be output like this:
410 //
411 // align=4
412 // alignstack=8
413 //
414 if (hasAttribute(Attribute::Alignment)) {
415 std::string Result;
416 Result += "align";
417 Result += (InAttrGrp) ? "=" : " ";
418 Result += utostr(getValueAsInt());
419 return Result;
420 }
421
422 auto AttrWithBytesToString = [&](const char *Name) {
423 std::string Result;
424 Result += Name;
425 if (InAttrGrp) {
426 Result += "=";
427 Result += utostr(getValueAsInt());
428 } else {
429 Result += "(";
430 Result += utostr(getValueAsInt());
431 Result += ")";
432 }
433 return Result;
434 };
435
436 if (hasAttribute(Attribute::StackAlignment))
437 return AttrWithBytesToString("alignstack");
438
439 if (hasAttribute(Attribute::Dereferenceable))
440 return AttrWithBytesToString("dereferenceable");
441
442 if (hasAttribute(Attribute::DereferenceableOrNull))
443 return AttrWithBytesToString("dereferenceable_or_null");
444
445 if (hasAttribute(Attribute::AllocSize)) {
446 unsigned ElemSize;
447 Optional<unsigned> NumElems;
448 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
449
450 std::string Result = "allocsize(";
451 Result += utostr(ElemSize);
452 if (NumElems.hasValue()) {
453 Result += ',';
454 Result += utostr(*NumElems);
455 }
456 Result += ')';
457 return Result;
458 }
459
460 // Convert target-dependent attributes to strings of the form:
461 //
462 // "kind"
463 // "kind" = "value"
464 //
465 if (isStringAttribute()) {
466 std::string Result;
467 Result += (Twine('"') + getKindAsString() + Twine('"')).str();
468
469 std::string AttrVal = pImpl->getValueAsString();
470 if (AttrVal.empty()) return Result;
471
472 // Since some attribute strings contain special characters that cannot be
473 // printable, those have to be escaped to make the attribute value printable
474 // as is. e.g. "\01__gnu_mcount_nc"
475 {
476 raw_string_ostream OS(Result);
477 OS << "=\"";
478 printEscapedString(AttrVal, OS);
479 OS << "\"";
480 }
481 return Result;
482 }
483
484 llvm_unreachable("Unknown attribute");
485 }
486
operator <(Attribute A) const487 bool Attribute::operator<(Attribute A) const {
488 if (!pImpl && !A.pImpl) return false;
489 if (!pImpl) return true;
490 if (!A.pImpl) return false;
491 return *pImpl < *A.pImpl;
492 }
493
494 //===----------------------------------------------------------------------===//
495 // AttributeImpl Definition
496 //===----------------------------------------------------------------------===//
497
498 // Pin the vtables to this file.
499 AttributeImpl::~AttributeImpl() = default;
500
anchor()501 void EnumAttributeImpl::anchor() {}
502
anchor()503 void IntAttributeImpl::anchor() {}
504
anchor()505 void StringAttributeImpl::anchor() {}
506
anchor()507 void TypeAttributeImpl::anchor() {}
508
hasAttribute(Attribute::AttrKind A) const509 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
510 if (isStringAttribute()) return false;
511 return getKindAsEnum() == A;
512 }
513
hasAttribute(StringRef Kind) const514 bool AttributeImpl::hasAttribute(StringRef Kind) const {
515 if (!isStringAttribute()) return false;
516 return getKindAsString() == Kind;
517 }
518
getKindAsEnum() const519 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
520 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
521 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
522 }
523
getValueAsInt() const524 uint64_t AttributeImpl::getValueAsInt() const {
525 assert(isIntAttribute());
526 return static_cast<const IntAttributeImpl *>(this)->getValue();
527 }
528
getKindAsString() const529 StringRef AttributeImpl::getKindAsString() const {
530 assert(isStringAttribute());
531 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
532 }
533
getValueAsString() const534 StringRef AttributeImpl::getValueAsString() const {
535 assert(isStringAttribute());
536 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
537 }
538
getValueAsType() const539 Type *AttributeImpl::getValueAsType() const {
540 assert(isTypeAttribute());
541 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
542 }
543
operator <(const AttributeImpl & AI) const544 bool AttributeImpl::operator<(const AttributeImpl &AI) const {
545 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
546 // relative to their enum value) and then strings.
547 if (isEnumAttribute()) {
548 if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();
549 if (AI.isIntAttribute()) return true;
550 if (AI.isStringAttribute()) return true;
551 if (AI.isTypeAttribute()) return true;
552 }
553
554 if (isTypeAttribute()) {
555 if (AI.isEnumAttribute()) return false;
556 if (AI.isTypeAttribute()) {
557 assert(getKindAsEnum() != AI.getKindAsEnum() &&
558 "Comparison of types would be unstable");
559 return getKindAsEnum() < AI.getKindAsEnum();
560 }
561 if (AI.isIntAttribute()) return true;
562 if (AI.isStringAttribute()) return true;
563 }
564
565 if (isIntAttribute()) {
566 if (AI.isEnumAttribute()) return false;
567 if (AI.isTypeAttribute()) return false;
568 if (AI.isIntAttribute()) {
569 if (getKindAsEnum() == AI.getKindAsEnum())
570 return getValueAsInt() < AI.getValueAsInt();
571 return getKindAsEnum() < AI.getKindAsEnum();
572 }
573 if (AI.isStringAttribute()) return true;
574 }
575
576 assert(isStringAttribute());
577 if (AI.isEnumAttribute()) return false;
578 if (AI.isTypeAttribute()) return false;
579 if (AI.isIntAttribute()) return false;
580 if (getKindAsString() == AI.getKindAsString())
581 return getValueAsString() < AI.getValueAsString();
582 return getKindAsString() < AI.getKindAsString();
583 }
584
585 //===----------------------------------------------------------------------===//
586 // AttributeSet Definition
587 //===----------------------------------------------------------------------===//
588
get(LLVMContext & C,const AttrBuilder & B)589 AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
590 return AttributeSet(AttributeSetNode::get(C, B));
591 }
592
get(LLVMContext & C,ArrayRef<Attribute> Attrs)593 AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
594 return AttributeSet(AttributeSetNode::get(C, Attrs));
595 }
596
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const597 AttributeSet AttributeSet::addAttribute(LLVMContext &C,
598 Attribute::AttrKind Kind) const {
599 if (hasAttribute(Kind)) return *this;
600 AttrBuilder B;
601 B.addAttribute(Kind);
602 return addAttributes(C, AttributeSet::get(C, B));
603 }
604
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const605 AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
606 StringRef Value) const {
607 AttrBuilder B;
608 B.addAttribute(Kind, Value);
609 return addAttributes(C, AttributeSet::get(C, B));
610 }
611
addAttributes(LLVMContext & C,const AttributeSet AS) const612 AttributeSet AttributeSet::addAttributes(LLVMContext &C,
613 const AttributeSet AS) const {
614 if (!hasAttributes())
615 return AS;
616
617 if (!AS.hasAttributes())
618 return *this;
619
620 AttrBuilder B(AS);
621 for (const auto &I : *this)
622 B.addAttribute(I);
623
624 return get(C, B);
625 }
626
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const627 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
628 Attribute::AttrKind Kind) const {
629 if (!hasAttribute(Kind)) return *this;
630 AttrBuilder B(*this);
631 B.removeAttribute(Kind);
632 return get(C, B);
633 }
634
removeAttribute(LLVMContext & C,StringRef Kind) const635 AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
636 StringRef Kind) const {
637 if (!hasAttribute(Kind)) return *this;
638 AttrBuilder B(*this);
639 B.removeAttribute(Kind);
640 return get(C, B);
641 }
642
removeAttributes(LLVMContext & C,const AttrBuilder & Attrs) const643 AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
644 const AttrBuilder &Attrs) const {
645 AttrBuilder B(*this);
646 B.remove(Attrs);
647 return get(C, B);
648 }
649
getNumAttributes() const650 unsigned AttributeSet::getNumAttributes() const {
651 return SetNode ? SetNode->getNumAttributes() : 0;
652 }
653
hasAttribute(Attribute::AttrKind Kind) const654 bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
655 return SetNode ? SetNode->hasAttribute(Kind) : false;
656 }
657
hasAttribute(StringRef Kind) const658 bool AttributeSet::hasAttribute(StringRef Kind) const {
659 return SetNode ? SetNode->hasAttribute(Kind) : false;
660 }
661
getAttribute(Attribute::AttrKind Kind) const662 Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
663 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
664 }
665
getAttribute(StringRef Kind) const666 Attribute AttributeSet::getAttribute(StringRef Kind) const {
667 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
668 }
669
getAlignment() const670 MaybeAlign AttributeSet::getAlignment() const {
671 return SetNode ? SetNode->getAlignment() : None;
672 }
673
getStackAlignment() const674 MaybeAlign AttributeSet::getStackAlignment() const {
675 return SetNode ? SetNode->getStackAlignment() : None;
676 }
677
getDereferenceableBytes() const678 uint64_t AttributeSet::getDereferenceableBytes() const {
679 return SetNode ? SetNode->getDereferenceableBytes() : 0;
680 }
681
getDereferenceableOrNullBytes() const682 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
683 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
684 }
685
getByValType() const686 Type *AttributeSet::getByValType() const {
687 return SetNode ? SetNode->getByValType() : nullptr;
688 }
689
getAllocSizeArgs() const690 std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
691 return SetNode ? SetNode->getAllocSizeArgs()
692 : std::pair<unsigned, Optional<unsigned>>(0, 0);
693 }
694
getAsString(bool InAttrGrp) const695 std::string AttributeSet::getAsString(bool InAttrGrp) const {
696 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
697 }
698
begin() const699 AttributeSet::iterator AttributeSet::begin() const {
700 return SetNode ? SetNode->begin() : nullptr;
701 }
702
end() const703 AttributeSet::iterator AttributeSet::end() const {
704 return SetNode ? SetNode->end() : nullptr;
705 }
706
707 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const708 LLVM_DUMP_METHOD void AttributeSet::dump() const {
709 dbgs() << "AS =\n";
710 dbgs() << " { ";
711 dbgs() << getAsString(true) << " }\n";
712 }
713 #endif
714
715 //===----------------------------------------------------------------------===//
716 // AttributeSetNode Definition
717 //===----------------------------------------------------------------------===//
718
AttributeSetNode(ArrayRef<Attribute> Attrs)719 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
720 : NumAttrs(Attrs.size()) {
721 // There's memory after the node where we can store the entries in.
722 llvm::copy(Attrs, getTrailingObjects<Attribute>());
723
724 static_assert(Attribute::EndAttrKinds <=
725 sizeof(AvailableAttrs) * CHAR_BIT,
726 "Too many attributes");
727
728 for (const auto &I : *this) {
729 if (!I.isStringAttribute()) {
730 Attribute::AttrKind Kind = I.getKindAsEnum();
731 AvailableAttrs[Kind / 8] |= 1ULL << (Kind % 8);
732 }
733 }
734 }
735
get(LLVMContext & C,ArrayRef<Attribute> Attrs)736 AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
737 ArrayRef<Attribute> Attrs) {
738 if (Attrs.empty())
739 return nullptr;
740
741 // Otherwise, build a key to look up the existing attributes.
742 LLVMContextImpl *pImpl = C.pImpl;
743 FoldingSetNodeID ID;
744
745 SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
746 llvm::sort(SortedAttrs);
747
748 for (const auto &Attr : SortedAttrs)
749 Attr.Profile(ID);
750
751 void *InsertPoint;
752 AttributeSetNode *PA =
753 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
754
755 // If we didn't find any existing attributes of the same shape then create a
756 // new one and insert it.
757 if (!PA) {
758 // Coallocate entries after the AttributeSetNode itself.
759 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
760 PA = new (Mem) AttributeSetNode(SortedAttrs);
761 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
762 }
763
764 // Return the AttributeSetNode that we found or created.
765 return PA;
766 }
767
get(LLVMContext & C,const AttrBuilder & B)768 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
769 // Add target-independent attributes.
770 SmallVector<Attribute, 8> Attrs;
771 for (Attribute::AttrKind Kind = Attribute::None;
772 Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
773 if (!B.contains(Kind))
774 continue;
775
776 Attribute Attr;
777 switch (Kind) {
778 case Attribute::ByVal:
779 Attr = Attribute::getWithByValType(C, B.getByValType());
780 break;
781 case Attribute::Alignment:
782 assert(B.getAlignment() && "Alignment must be set");
783 Attr = Attribute::getWithAlignment(C, *B.getAlignment());
784 break;
785 case Attribute::StackAlignment:
786 assert(B.getStackAlignment() && "StackAlignment must be set");
787 Attr = Attribute::getWithStackAlignment(C, *B.getStackAlignment());
788 break;
789 case Attribute::Dereferenceable:
790 Attr = Attribute::getWithDereferenceableBytes(
791 C, B.getDereferenceableBytes());
792 break;
793 case Attribute::DereferenceableOrNull:
794 Attr = Attribute::getWithDereferenceableOrNullBytes(
795 C, B.getDereferenceableOrNullBytes());
796 break;
797 case Attribute::AllocSize: {
798 auto A = B.getAllocSizeArgs();
799 Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
800 break;
801 }
802 default:
803 Attr = Attribute::get(C, Kind);
804 }
805 Attrs.push_back(Attr);
806 }
807
808 // Add target-dependent (string) attributes.
809 for (const auto &TDA : B.td_attrs())
810 Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second));
811
812 return get(C, Attrs);
813 }
814
hasAttribute(StringRef Kind) const815 bool AttributeSetNode::hasAttribute(StringRef Kind) const {
816 for (const auto &I : *this)
817 if (I.hasAttribute(Kind))
818 return true;
819 return false;
820 }
821
getAttribute(Attribute::AttrKind Kind) const822 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
823 if (hasAttribute(Kind)) {
824 for (const auto &I : *this)
825 if (I.hasAttribute(Kind))
826 return I;
827 }
828 return {};
829 }
830
getAttribute(StringRef Kind) const831 Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
832 for (const auto &I : *this)
833 if (I.hasAttribute(Kind))
834 return I;
835 return {};
836 }
837
getAlignment() const838 MaybeAlign AttributeSetNode::getAlignment() const {
839 for (const auto &I : *this)
840 if (I.hasAttribute(Attribute::Alignment))
841 return I.getAlignment();
842 return None;
843 }
844
getStackAlignment() const845 MaybeAlign AttributeSetNode::getStackAlignment() const {
846 for (const auto &I : *this)
847 if (I.hasAttribute(Attribute::StackAlignment))
848 return I.getStackAlignment();
849 return None;
850 }
851
getByValType() const852 Type *AttributeSetNode::getByValType() const {
853 for (const auto &I : *this)
854 if (I.hasAttribute(Attribute::ByVal))
855 return I.getValueAsType();
856 return 0;
857 }
858
getDereferenceableBytes() const859 uint64_t AttributeSetNode::getDereferenceableBytes() const {
860 for (const auto &I : *this)
861 if (I.hasAttribute(Attribute::Dereferenceable))
862 return I.getDereferenceableBytes();
863 return 0;
864 }
865
getDereferenceableOrNullBytes() const866 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
867 for (const auto &I : *this)
868 if (I.hasAttribute(Attribute::DereferenceableOrNull))
869 return I.getDereferenceableOrNullBytes();
870 return 0;
871 }
872
873 std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs() const874 AttributeSetNode::getAllocSizeArgs() const {
875 for (const auto &I : *this)
876 if (I.hasAttribute(Attribute::AllocSize))
877 return I.getAllocSizeArgs();
878 return std::make_pair(0, 0);
879 }
880
getAsString(bool InAttrGrp) const881 std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
882 std::string Str;
883 for (iterator I = begin(), E = end(); I != E; ++I) {
884 if (I != begin())
885 Str += ' ';
886 Str += I->getAsString(InAttrGrp);
887 }
888 return Str;
889 }
890
891 //===----------------------------------------------------------------------===//
892 // AttributeListImpl Definition
893 //===----------------------------------------------------------------------===//
894
895 /// Map from AttributeList index to the internal array index. Adding one happens
896 /// to work, but it relies on unsigned integer wrapping. MSVC warns about
897 /// unsigned wrapping in constexpr functions, so write out the conditional. LLVM
898 /// folds it to add anyway.
attrIdxToArrayIdx(unsigned Index)899 static constexpr unsigned attrIdxToArrayIdx(unsigned Index) {
900 return Index == AttributeList::FunctionIndex ? 0 : Index + 1;
901 }
902
AttributeListImpl(LLVMContext & C,ArrayRef<AttributeSet> Sets)903 AttributeListImpl::AttributeListImpl(LLVMContext &C,
904 ArrayRef<AttributeSet> Sets)
905 : Context(C), NumAttrSets(Sets.size()) {
906 assert(!Sets.empty() && "pointless AttributeListImpl");
907
908 // There's memory after the node where we can store the entries in.
909 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
910
911 // Initialize AvailableFunctionAttrs summary bitset.
912 static_assert(Attribute::EndAttrKinds <=
913 sizeof(AvailableFunctionAttrs) * CHAR_BIT,
914 "Too many attributes");
915 static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U,
916 "function should be stored in slot 0");
917 for (const auto &I : Sets[0]) {
918 if (!I.isStringAttribute()) {
919 Attribute::AttrKind Kind = I.getKindAsEnum();
920 AvailableFunctionAttrs[Kind / 8] |= 1ULL << (Kind % 8);
921 }
922 }
923 }
924
Profile(FoldingSetNodeID & ID) const925 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
926 Profile(ID, makeArrayRef(begin(), end()));
927 }
928
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)929 void AttributeListImpl::Profile(FoldingSetNodeID &ID,
930 ArrayRef<AttributeSet> Sets) {
931 for (const auto &Set : Sets)
932 ID.AddPointer(Set.SetNode);
933 }
934
935 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const936 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
937 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
938 }
939 #endif
940
941 //===----------------------------------------------------------------------===//
942 // AttributeList Construction and Mutation Methods
943 //===----------------------------------------------------------------------===//
944
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)945 AttributeList AttributeList::getImpl(LLVMContext &C,
946 ArrayRef<AttributeSet> AttrSets) {
947 assert(!AttrSets.empty() && "pointless AttributeListImpl");
948
949 LLVMContextImpl *pImpl = C.pImpl;
950 FoldingSetNodeID ID;
951 AttributeListImpl::Profile(ID, AttrSets);
952
953 void *InsertPoint;
954 AttributeListImpl *PA =
955 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
956
957 // If we didn't find any existing attributes of the same shape then
958 // create a new one and insert it.
959 if (!PA) {
960 // Coallocate entries after the AttributeListImpl itself.
961 void *Mem = ::operator new(
962 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()));
963 PA = new (Mem) AttributeListImpl(C, AttrSets);
964 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
965 }
966
967 // Return the AttributesList that we found or created.
968 return AttributeList(PA);
969 }
970
971 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)972 AttributeList::get(LLVMContext &C,
973 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
974 // If there are no attributes then return a null AttributesList pointer.
975 if (Attrs.empty())
976 return {};
977
978 assert(std::is_sorted(Attrs.begin(), Attrs.end(),
979 [](const std::pair<unsigned, Attribute> &LHS,
980 const std::pair<unsigned, Attribute> &RHS) {
981 return LHS.first < RHS.first;
982 }) && "Misordered Attributes list!");
983 assert(llvm::none_of(Attrs,
984 [](const std::pair<unsigned, Attribute> &Pair) {
985 return Pair.second.hasAttribute(Attribute::None);
986 }) &&
987 "Pointless attribute!");
988
989 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
990 // list.
991 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
992 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
993 E = Attrs.end(); I != E; ) {
994 unsigned Index = I->first;
995 SmallVector<Attribute, 4> AttrVec;
996 while (I != E && I->first == Index) {
997 AttrVec.push_back(I->second);
998 ++I;
999 }
1000
1001 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1002 }
1003
1004 return get(C, AttrPairVec);
1005 }
1006
1007 AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1008 AttributeList::get(LLVMContext &C,
1009 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1010 // If there are no attributes then return a null AttributesList pointer.
1011 if (Attrs.empty())
1012 return {};
1013
1014 assert(std::is_sorted(Attrs.begin(), Attrs.end(),
1015 [](const std::pair<unsigned, AttributeSet> &LHS,
1016 const std::pair<unsigned, AttributeSet> &RHS) {
1017 return LHS.first < RHS.first;
1018 }) &&
1019 "Misordered Attributes list!");
1020 assert(llvm::none_of(Attrs,
1021 [](const std::pair<unsigned, AttributeSet> &Pair) {
1022 return !Pair.second.hasAttributes();
1023 }) &&
1024 "Pointless attribute!");
1025
1026 unsigned MaxIndex = Attrs.back().first;
1027 // If the MaxIndex is FunctionIndex and there are other indices in front
1028 // of it, we need to use the largest of those to get the right size.
1029 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1030 MaxIndex = Attrs[Attrs.size() - 2].first;
1031
1032 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1033 for (const auto &Pair : Attrs)
1034 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1035
1036 return getImpl(C, AttrVec);
1037 }
1038
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)1039 AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1040 AttributeSet RetAttrs,
1041 ArrayRef<AttributeSet> ArgAttrs) {
1042 // Scan from the end to find the last argument with attributes. Most
1043 // arguments don't have attributes, so it's nice if we can have fewer unique
1044 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1045 unsigned NumSets = 0;
1046 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1047 if (ArgAttrs[I - 1].hasAttributes()) {
1048 NumSets = I + 2;
1049 break;
1050 }
1051 }
1052 if (NumSets == 0) {
1053 // Check function and return attributes if we didn't have argument
1054 // attributes.
1055 if (RetAttrs.hasAttributes())
1056 NumSets = 2;
1057 else if (FnAttrs.hasAttributes())
1058 NumSets = 1;
1059 }
1060
1061 // If all attribute sets were empty, we can use the empty attribute list.
1062 if (NumSets == 0)
1063 return {};
1064
1065 SmallVector<AttributeSet, 8> AttrSets;
1066 AttrSets.reserve(NumSets);
1067 // If we have any attributes, we always have function attributes.
1068 AttrSets.push_back(FnAttrs);
1069 if (NumSets > 1)
1070 AttrSets.push_back(RetAttrs);
1071 if (NumSets > 2) {
1072 // Drop the empty argument attribute sets at the end.
1073 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1074 AttrSets.insert(AttrSets.end(), ArgAttrs.begin(), ArgAttrs.end());
1075 }
1076
1077 return getImpl(C, AttrSets);
1078 }
1079
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1080 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1081 const AttrBuilder &B) {
1082 if (!B.hasAttributes())
1083 return {};
1084 Index = attrIdxToArrayIdx(Index);
1085 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1086 AttrSets[Index] = AttributeSet::get(C, B);
1087 return getImpl(C, AttrSets);
1088 }
1089
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1090 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1091 ArrayRef<Attribute::AttrKind> Kinds) {
1092 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1093 for (const auto K : Kinds)
1094 Attrs.emplace_back(Index, Attribute::get(C, K));
1095 return get(C, Attrs);
1096 }
1097
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1098 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1099 ArrayRef<StringRef> Kinds) {
1100 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1101 for (const auto &K : Kinds)
1102 Attrs.emplace_back(Index, Attribute::get(C, K));
1103 return get(C, Attrs);
1104 }
1105
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1106 AttributeList AttributeList::get(LLVMContext &C,
1107 ArrayRef<AttributeList> Attrs) {
1108 if (Attrs.empty())
1109 return {};
1110 if (Attrs.size() == 1)
1111 return Attrs[0];
1112
1113 unsigned MaxSize = 0;
1114 for (const auto &List : Attrs)
1115 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1116
1117 // If every list was empty, there is no point in merging the lists.
1118 if (MaxSize == 0)
1119 return {};
1120
1121 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1122 for (unsigned I = 0; I < MaxSize; ++I) {
1123 AttrBuilder CurBuilder;
1124 for (const auto &List : Attrs)
1125 CurBuilder.merge(List.getAttributes(I - 1));
1126 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1127 }
1128
1129 return getImpl(C, NewAttrSets);
1130 }
1131
addAttribute(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1132 AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1133 Attribute::AttrKind Kind) const {
1134 if (hasAttribute(Index, Kind)) return *this;
1135 AttrBuilder B;
1136 B.addAttribute(Kind);
1137 return addAttributes(C, Index, B);
1138 }
1139
addAttribute(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1140 AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1141 StringRef Kind,
1142 StringRef Value) const {
1143 AttrBuilder B;
1144 B.addAttribute(Kind, Value);
1145 return addAttributes(C, Index, B);
1146 }
1147
addAttribute(LLVMContext & C,unsigned Index,Attribute A) const1148 AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1149 Attribute A) const {
1150 AttrBuilder B;
1151 B.addAttribute(A);
1152 return addAttributes(C, Index, B);
1153 }
1154
addAttributes(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1155 AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
1156 const AttrBuilder &B) const {
1157 if (!B.hasAttributes())
1158 return *this;
1159
1160 if (!pImpl)
1161 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1162
1163 #ifndef NDEBUG
1164 // FIXME it is not obvious how this should work for alignment. For now, say
1165 // we can't change a known alignment.
1166 const MaybeAlign OldAlign = getAttributes(Index).getAlignment();
1167 const MaybeAlign NewAlign = B.getAlignment();
1168 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
1169 "Attempt to change alignment!");
1170 #endif
1171
1172 Index = attrIdxToArrayIdx(Index);
1173 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1174 if (Index >= AttrSets.size())
1175 AttrSets.resize(Index + 1);
1176
1177 AttrBuilder Merged(AttrSets[Index]);
1178 Merged.merge(B);
1179 AttrSets[Index] = AttributeSet::get(C, Merged);
1180
1181 return getImpl(C, AttrSets);
1182 }
1183
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const1184 AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1185 ArrayRef<unsigned> ArgNos,
1186 Attribute A) const {
1187 assert(std::is_sorted(ArgNos.begin(), ArgNos.end()));
1188
1189 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1190 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1191 if (MaxIndex >= AttrSets.size())
1192 AttrSets.resize(MaxIndex + 1);
1193
1194 for (unsigned ArgNo : ArgNos) {
1195 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1196 AttrBuilder B(AttrSets[Index]);
1197 B.addAttribute(A);
1198 AttrSets[Index] = AttributeSet::get(C, B);
1199 }
1200
1201 return getImpl(C, AttrSets);
1202 }
1203
removeAttribute(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1204 AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
1205 Attribute::AttrKind Kind) const {
1206 if (!hasAttribute(Index, Kind)) return *this;
1207
1208 Index = attrIdxToArrayIdx(Index);
1209 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1210 assert(Index < AttrSets.size());
1211
1212 AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1213
1214 return getImpl(C, AttrSets);
1215 }
1216
removeAttribute(LLVMContext & C,unsigned Index,StringRef Kind) const1217 AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
1218 StringRef Kind) const {
1219 if (!hasAttribute(Index, Kind)) return *this;
1220
1221 Index = attrIdxToArrayIdx(Index);
1222 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1223 assert(Index < AttrSets.size());
1224
1225 AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1226
1227 return getImpl(C, AttrSets);
1228 }
1229
1230 AttributeList
removeAttributes(LLVMContext & C,unsigned Index,const AttrBuilder & AttrsToRemove) const1231 AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
1232 const AttrBuilder &AttrsToRemove) const {
1233 if (!pImpl)
1234 return {};
1235
1236 Index = attrIdxToArrayIdx(Index);
1237 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1238 if (Index >= AttrSets.size())
1239 AttrSets.resize(Index + 1);
1240
1241 AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove);
1242
1243 return getImpl(C, AttrSets);
1244 }
1245
removeAttributes(LLVMContext & C,unsigned WithoutIndex) const1246 AttributeList AttributeList::removeAttributes(LLVMContext &C,
1247 unsigned WithoutIndex) const {
1248 if (!pImpl)
1249 return {};
1250 WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
1251 if (WithoutIndex >= getNumAttrSets())
1252 return *this;
1253 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1254 AttrSets[WithoutIndex] = AttributeSet();
1255 return getImpl(C, AttrSets);
1256 }
1257
addDereferenceableAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1258 AttributeList AttributeList::addDereferenceableAttr(LLVMContext &C,
1259 unsigned Index,
1260 uint64_t Bytes) const {
1261 AttrBuilder B;
1262 B.addDereferenceableAttr(Bytes);
1263 return addAttributes(C, Index, B);
1264 }
1265
1266 AttributeList
addDereferenceableOrNullAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1267 AttributeList::addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
1268 uint64_t Bytes) const {
1269 AttrBuilder B;
1270 B.addDereferenceableOrNullAttr(Bytes);
1271 return addAttributes(C, Index, B);
1272 }
1273
1274 AttributeList
addAllocSizeAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)1275 AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index,
1276 unsigned ElemSizeArg,
1277 const Optional<unsigned> &NumElemsArg) {
1278 AttrBuilder B;
1279 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1280 return addAttributes(C, Index, B);
1281 }
1282
1283 //===----------------------------------------------------------------------===//
1284 // AttributeList Accessor Methods
1285 //===----------------------------------------------------------------------===//
1286
getContext() const1287 LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); }
1288
getParamAttributes(unsigned ArgNo) const1289 AttributeSet AttributeList::getParamAttributes(unsigned ArgNo) const {
1290 return getAttributes(ArgNo + FirstArgIndex);
1291 }
1292
getRetAttributes() const1293 AttributeSet AttributeList::getRetAttributes() const {
1294 return getAttributes(ReturnIndex);
1295 }
1296
getFnAttributes() const1297 AttributeSet AttributeList::getFnAttributes() const {
1298 return getAttributes(FunctionIndex);
1299 }
1300
hasAttribute(unsigned Index,Attribute::AttrKind Kind) const1301 bool AttributeList::hasAttribute(unsigned Index,
1302 Attribute::AttrKind Kind) const {
1303 return getAttributes(Index).hasAttribute(Kind);
1304 }
1305
hasAttribute(unsigned Index,StringRef Kind) const1306 bool AttributeList::hasAttribute(unsigned Index, StringRef Kind) const {
1307 return getAttributes(Index).hasAttribute(Kind);
1308 }
1309
hasAttributes(unsigned Index) const1310 bool AttributeList::hasAttributes(unsigned Index) const {
1311 return getAttributes(Index).hasAttributes();
1312 }
1313
hasFnAttribute(Attribute::AttrKind Kind) const1314 bool AttributeList::hasFnAttribute(Attribute::AttrKind Kind) const {
1315 return pImpl && pImpl->hasFnAttribute(Kind);
1316 }
1317
hasFnAttribute(StringRef Kind) const1318 bool AttributeList::hasFnAttribute(StringRef Kind) const {
1319 return hasAttribute(AttributeList::FunctionIndex, Kind);
1320 }
1321
hasParamAttribute(unsigned ArgNo,Attribute::AttrKind Kind) const1322 bool AttributeList::hasParamAttribute(unsigned ArgNo,
1323 Attribute::AttrKind Kind) const {
1324 return hasAttribute(ArgNo + FirstArgIndex, Kind);
1325 }
1326
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1327 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1328 unsigned *Index) const {
1329 if (!pImpl) return false;
1330
1331 for (unsigned I = index_begin(), E = index_end(); I != E; ++I) {
1332 if (hasAttribute(I, Attr)) {
1333 if (Index)
1334 *Index = I;
1335 return true;
1336 }
1337 }
1338
1339 return false;
1340 }
1341
getAttribute(unsigned Index,Attribute::AttrKind Kind) const1342 Attribute AttributeList::getAttribute(unsigned Index,
1343 Attribute::AttrKind Kind) const {
1344 return getAttributes(Index).getAttribute(Kind);
1345 }
1346
getAttribute(unsigned Index,StringRef Kind) const1347 Attribute AttributeList::getAttribute(unsigned Index, StringRef Kind) const {
1348 return getAttributes(Index).getAttribute(Kind);
1349 }
1350
getRetAlignment() const1351 MaybeAlign AttributeList::getRetAlignment() const {
1352 return getAttributes(ReturnIndex).getAlignment();
1353 }
1354
getParamAlignment(unsigned ArgNo) const1355 MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1356 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1357 }
1358
getParamByValType(unsigned Index) const1359 Type *AttributeList::getParamByValType(unsigned Index) const {
1360 return getAttributes(Index+FirstArgIndex).getByValType();
1361 }
1362
getStackAlignment(unsigned Index) const1363 MaybeAlign AttributeList::getStackAlignment(unsigned Index) const {
1364 return getAttributes(Index).getStackAlignment();
1365 }
1366
getDereferenceableBytes(unsigned Index) const1367 uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const {
1368 return getAttributes(Index).getDereferenceableBytes();
1369 }
1370
getDereferenceableOrNullBytes(unsigned Index) const1371 uint64_t AttributeList::getDereferenceableOrNullBytes(unsigned Index) const {
1372 return getAttributes(Index).getDereferenceableOrNullBytes();
1373 }
1374
1375 std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs(unsigned Index) const1376 AttributeList::getAllocSizeArgs(unsigned Index) const {
1377 return getAttributes(Index).getAllocSizeArgs();
1378 }
1379
getAsString(unsigned Index,bool InAttrGrp) const1380 std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1381 return getAttributes(Index).getAsString(InAttrGrp);
1382 }
1383
getAttributes(unsigned Index) const1384 AttributeSet AttributeList::getAttributes(unsigned Index) const {
1385 Index = attrIdxToArrayIdx(Index);
1386 if (!pImpl || Index >= getNumAttrSets())
1387 return {};
1388 return pImpl->begin()[Index];
1389 }
1390
begin() const1391 AttributeList::iterator AttributeList::begin() const {
1392 return pImpl ? pImpl->begin() : nullptr;
1393 }
1394
end() const1395 AttributeList::iterator AttributeList::end() const {
1396 return pImpl ? pImpl->end() : nullptr;
1397 }
1398
1399 //===----------------------------------------------------------------------===//
1400 // AttributeList Introspection Methods
1401 //===----------------------------------------------------------------------===//
1402
getNumAttrSets() const1403 unsigned AttributeList::getNumAttrSets() const {
1404 return pImpl ? pImpl->NumAttrSets : 0;
1405 }
1406
1407 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1408 LLVM_DUMP_METHOD void AttributeList::dump() const {
1409 dbgs() << "PAL[\n";
1410
1411 for (unsigned i = index_begin(), e = index_end(); i != e; ++i) {
1412 if (getAttributes(i).hasAttributes())
1413 dbgs() << " { " << i << " => " << getAsString(i) << " }\n";
1414 }
1415
1416 dbgs() << "]\n";
1417 }
1418 #endif
1419
1420 //===----------------------------------------------------------------------===//
1421 // AttrBuilder Method Implementations
1422 //===----------------------------------------------------------------------===//
1423
1424 // FIXME: Remove this ctor, use AttributeSet.
AttrBuilder(AttributeList AL,unsigned Index)1425 AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) {
1426 AttributeSet AS = AL.getAttributes(Index);
1427 for (const auto &A : AS)
1428 addAttribute(A);
1429 }
1430
AttrBuilder(AttributeSet AS)1431 AttrBuilder::AttrBuilder(AttributeSet AS) {
1432 for (const auto &A : AS)
1433 addAttribute(A);
1434 }
1435
clear()1436 void AttrBuilder::clear() {
1437 Attrs.reset();
1438 TargetDepAttrs.clear();
1439 Alignment.reset();
1440 StackAlignment.reset();
1441 DerefBytes = DerefOrNullBytes = 0;
1442 AllocSizeArgs = 0;
1443 ByValType = nullptr;
1444 }
1445
addAttribute(Attribute::AttrKind Val)1446 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
1447 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1448 assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment &&
1449 Val != Attribute::Dereferenceable && Val != Attribute::AllocSize &&
1450 "Adding integer attribute without adding a value!");
1451 Attrs[Val] = true;
1452 return *this;
1453 }
1454
addAttribute(Attribute Attr)1455 AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1456 if (Attr.isStringAttribute()) {
1457 addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
1458 return *this;
1459 }
1460
1461 Attribute::AttrKind Kind = Attr.getKindAsEnum();
1462 Attrs[Kind] = true;
1463
1464 if (Kind == Attribute::Alignment)
1465 Alignment = Attr.getAlignment();
1466 else if (Kind == Attribute::StackAlignment)
1467 StackAlignment = Attr.getStackAlignment();
1468 else if (Kind == Attribute::ByVal)
1469 ByValType = Attr.getValueAsType();
1470 else if (Kind == Attribute::Dereferenceable)
1471 DerefBytes = Attr.getDereferenceableBytes();
1472 else if (Kind == Attribute::DereferenceableOrNull)
1473 DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
1474 else if (Kind == Attribute::AllocSize)
1475 AllocSizeArgs = Attr.getValueAsInt();
1476 return *this;
1477 }
1478
addAttribute(StringRef A,StringRef V)1479 AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1480 TargetDepAttrs[A] = V;
1481 return *this;
1482 }
1483
removeAttribute(Attribute::AttrKind Val)1484 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1485 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1486 Attrs[Val] = false;
1487
1488 if (Val == Attribute::Alignment)
1489 Alignment.reset();
1490 else if (Val == Attribute::StackAlignment)
1491 StackAlignment.reset();
1492 else if (Val == Attribute::ByVal)
1493 ByValType = nullptr;
1494 else if (Val == Attribute::Dereferenceable)
1495 DerefBytes = 0;
1496 else if (Val == Attribute::DereferenceableOrNull)
1497 DerefOrNullBytes = 0;
1498 else if (Val == Attribute::AllocSize)
1499 AllocSizeArgs = 0;
1500
1501 return *this;
1502 }
1503
removeAttributes(AttributeList A,uint64_t Index)1504 AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) {
1505 remove(A.getAttributes(Index));
1506 return *this;
1507 }
1508
removeAttribute(StringRef A)1509 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1510 auto I = TargetDepAttrs.find(A);
1511 if (I != TargetDepAttrs.end())
1512 TargetDepAttrs.erase(I);
1513 return *this;
1514 }
1515
getAllocSizeArgs() const1516 std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
1517 return unpackAllocSizeArgs(AllocSizeArgs);
1518 }
1519
addAlignmentAttr(MaybeAlign Align)1520 AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1521 if (!Align)
1522 return *this;
1523
1524 assert(*Align <= 0x40000000 && "Alignment too large.");
1525
1526 Attrs[Attribute::Alignment] = true;
1527 Alignment = Align;
1528 return *this;
1529 }
1530
addStackAlignmentAttr(MaybeAlign Align)1531 AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1532 // Default alignment, allow the target to define how to align it.
1533 if (!Align)
1534 return *this;
1535
1536 assert(*Align <= 0x100 && "Alignment too large.");
1537
1538 Attrs[Attribute::StackAlignment] = true;
1539 StackAlignment = Align;
1540 return *this;
1541 }
1542
addDereferenceableAttr(uint64_t Bytes)1543 AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1544 if (Bytes == 0) return *this;
1545
1546 Attrs[Attribute::Dereferenceable] = true;
1547 DerefBytes = Bytes;
1548 return *this;
1549 }
1550
addDereferenceableOrNullAttr(uint64_t Bytes)1551 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1552 if (Bytes == 0)
1553 return *this;
1554
1555 Attrs[Attribute::DereferenceableOrNull] = true;
1556 DerefOrNullBytes = Bytes;
1557 return *this;
1558 }
1559
addAllocSizeAttr(unsigned ElemSize,const Optional<unsigned> & NumElems)1560 AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1561 const Optional<unsigned> &NumElems) {
1562 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1563 }
1564
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1565 AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1566 // (0, 0) is our "not present" value, so we need to check for it here.
1567 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1568
1569 Attrs[Attribute::AllocSize] = true;
1570 // Reuse existing machinery to store this as a single 64-bit integer so we can
1571 // save a few bytes over using a pair<unsigned, Optional<unsigned>>.
1572 AllocSizeArgs = RawArgs;
1573 return *this;
1574 }
1575
addByValAttr(Type * Ty)1576 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
1577 Attrs[Attribute::ByVal] = true;
1578 ByValType = Ty;
1579 return *this;
1580 }
1581
merge(const AttrBuilder & B)1582 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1583 // FIXME: What if both have alignments, but they don't match?!
1584 if (!Alignment)
1585 Alignment = B.Alignment;
1586
1587 if (!StackAlignment)
1588 StackAlignment = B.StackAlignment;
1589
1590 if (!DerefBytes)
1591 DerefBytes = B.DerefBytes;
1592
1593 if (!DerefOrNullBytes)
1594 DerefOrNullBytes = B.DerefOrNullBytes;
1595
1596 if (!AllocSizeArgs)
1597 AllocSizeArgs = B.AllocSizeArgs;
1598
1599 if (!ByValType)
1600 ByValType = B.ByValType;
1601
1602 Attrs |= B.Attrs;
1603
1604 for (auto I : B.td_attrs())
1605 TargetDepAttrs[I.first] = I.second;
1606
1607 return *this;
1608 }
1609
remove(const AttrBuilder & B)1610 AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
1611 // FIXME: What if both have alignments, but they don't match?!
1612 if (B.Alignment)
1613 Alignment.reset();
1614
1615 if (B.StackAlignment)
1616 StackAlignment.reset();
1617
1618 if (B.DerefBytes)
1619 DerefBytes = 0;
1620
1621 if (B.DerefOrNullBytes)
1622 DerefOrNullBytes = 0;
1623
1624 if (B.AllocSizeArgs)
1625 AllocSizeArgs = 0;
1626
1627 if (B.ByValType)
1628 ByValType = nullptr;
1629
1630 Attrs &= ~B.Attrs;
1631
1632 for (auto I : B.td_attrs())
1633 TargetDepAttrs.erase(I.first);
1634
1635 return *this;
1636 }
1637
overlaps(const AttrBuilder & B) const1638 bool AttrBuilder::overlaps(const AttrBuilder &B) const {
1639 // First check if any of the target independent attributes overlap.
1640 if ((Attrs & B.Attrs).any())
1641 return true;
1642
1643 // Then check if any target dependent ones do.
1644 for (const auto &I : td_attrs())
1645 if (B.contains(I.first))
1646 return true;
1647
1648 return false;
1649 }
1650
contains(StringRef A) const1651 bool AttrBuilder::contains(StringRef A) const {
1652 return TargetDepAttrs.find(A) != TargetDepAttrs.end();
1653 }
1654
hasAttributes() const1655 bool AttrBuilder::hasAttributes() const {
1656 return !Attrs.none() || !TargetDepAttrs.empty();
1657 }
1658
hasAttributes(AttributeList AL,uint64_t Index) const1659 bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const {
1660 AttributeSet AS = AL.getAttributes(Index);
1661
1662 for (const auto &Attr : AS) {
1663 if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
1664 if (contains(Attr.getKindAsEnum()))
1665 return true;
1666 } else {
1667 assert(Attr.isStringAttribute() && "Invalid attribute kind!");
1668 return contains(Attr.getKindAsString());
1669 }
1670 }
1671
1672 return false;
1673 }
1674
hasAlignmentAttr() const1675 bool AttrBuilder::hasAlignmentAttr() const {
1676 return Alignment != 0;
1677 }
1678
operator ==(const AttrBuilder & B)1679 bool AttrBuilder::operator==(const AttrBuilder &B) {
1680 if (Attrs != B.Attrs)
1681 return false;
1682
1683 for (td_const_iterator I = TargetDepAttrs.begin(),
1684 E = TargetDepAttrs.end(); I != E; ++I)
1685 if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())
1686 return false;
1687
1688 return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
1689 DerefBytes == B.DerefBytes && ByValType == B.ByValType;
1690 }
1691
1692 //===----------------------------------------------------------------------===//
1693 // AttributeFuncs Function Defintions
1694 //===----------------------------------------------------------------------===//
1695
1696 /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty)1697 AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
1698 AttrBuilder Incompatible;
1699
1700 if (!Ty->isIntegerTy())
1701 // Attribute that only apply to integers.
1702 Incompatible.addAttribute(Attribute::SExt)
1703 .addAttribute(Attribute::ZExt);
1704
1705 if (!Ty->isPointerTy())
1706 // Attribute that only apply to pointers.
1707 Incompatible.addAttribute(Attribute::ByVal)
1708 .addAttribute(Attribute::Nest)
1709 .addAttribute(Attribute::NoAlias)
1710 .addAttribute(Attribute::NoCapture)
1711 .addAttribute(Attribute::NonNull)
1712 .addDereferenceableAttr(1) // the int here is ignored
1713 .addDereferenceableOrNullAttr(1) // the int here is ignored
1714 .addAttribute(Attribute::ReadNone)
1715 .addAttribute(Attribute::ReadOnly)
1716 .addAttribute(Attribute::StructRet)
1717 .addAttribute(Attribute::InAlloca);
1718
1719 return Incompatible;
1720 }
1721
1722 template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)1723 static bool isEqual(const Function &Caller, const Function &Callee) {
1724 return Caller.getFnAttribute(AttrClass::getKind()) ==
1725 Callee.getFnAttribute(AttrClass::getKind());
1726 }
1727
1728 /// Compute the logical AND of the attributes of the caller and the
1729 /// callee.
1730 ///
1731 /// This function sets the caller's attribute to false if the callee's attribute
1732 /// is false.
1733 template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)1734 static void setAND(Function &Caller, const Function &Callee) {
1735 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
1736 !AttrClass::isSet(Callee, AttrClass::getKind()))
1737 AttrClass::set(Caller, AttrClass::getKind(), false);
1738 }
1739
1740 /// Compute the logical OR of the attributes of the caller and the
1741 /// callee.
1742 ///
1743 /// This function sets the caller's attribute to true if the callee's attribute
1744 /// is true.
1745 template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)1746 static void setOR(Function &Caller, const Function &Callee) {
1747 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
1748 AttrClass::isSet(Callee, AttrClass::getKind()))
1749 AttrClass::set(Caller, AttrClass::getKind(), true);
1750 }
1751
1752 /// If the inlined function had a higher stack protection level than the
1753 /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)1754 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1755 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1756 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1757 // clutter to the IR.
1758 AttrBuilder OldSSPAttr;
1759 OldSSPAttr.addAttribute(Attribute::StackProtect)
1760 .addAttribute(Attribute::StackProtectStrong)
1761 .addAttribute(Attribute::StackProtectReq);
1762
1763 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1764 Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
1765 Caller.addFnAttr(Attribute::StackProtectReq);
1766 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
1767 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1768 Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
1769 Caller.addFnAttr(Attribute::StackProtectStrong);
1770 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
1771 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
1772 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
1773 Caller.addFnAttr(Attribute::StackProtect);
1774 }
1775
1776 /// If the inlined function required stack probes, then ensure that
1777 /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)1778 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
1779 if (!Caller.hasFnAttribute("probe-stack") &&
1780 Callee.hasFnAttribute("probe-stack")) {
1781 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
1782 }
1783 }
1784
1785 /// If the inlined function defines the size of guard region
1786 /// on the stack, then ensure that the calling function defines a guard region
1787 /// that is no larger.
1788 static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)1789 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
1790 if (Callee.hasFnAttribute("stack-probe-size")) {
1791 uint64_t CalleeStackProbeSize;
1792 Callee.getFnAttribute("stack-probe-size")
1793 .getValueAsString()
1794 .getAsInteger(0, CalleeStackProbeSize);
1795 if (Caller.hasFnAttribute("stack-probe-size")) {
1796 uint64_t CallerStackProbeSize;
1797 Caller.getFnAttribute("stack-probe-size")
1798 .getValueAsString()
1799 .getAsInteger(0, CallerStackProbeSize);
1800 if (CallerStackProbeSize > CalleeStackProbeSize) {
1801 Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size"));
1802 }
1803 } else {
1804 Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size"));
1805 }
1806 }
1807 }
1808
1809 /// If the inlined function defines a min legal vector width, then ensure
1810 /// the calling function has the same or larger min legal vector width. If the
1811 /// caller has the attribute, but the callee doesn't, we need to remove the
1812 /// attribute from the caller since we can't make any guarantees about the
1813 /// caller's requirements.
1814 /// This function is called after the inlining decision has been made so we have
1815 /// to merge the attribute this way. Heuristics that would use
1816 /// min-legal-vector-width to determine inline compatibility would need to be
1817 /// handled as part of inline cost analysis.
1818 static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)1819 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
1820 if (Caller.hasFnAttribute("min-legal-vector-width")) {
1821 if (Callee.hasFnAttribute("min-legal-vector-width")) {
1822 uint64_t CallerVectorWidth;
1823 Caller.getFnAttribute("min-legal-vector-width")
1824 .getValueAsString()
1825 .getAsInteger(0, CallerVectorWidth);
1826 uint64_t CalleeVectorWidth;
1827 Callee.getFnAttribute("min-legal-vector-width")
1828 .getValueAsString()
1829 .getAsInteger(0, CalleeVectorWidth);
1830 if (CallerVectorWidth < CalleeVectorWidth)
1831 Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width"));
1832 } else {
1833 // If the callee doesn't have the attribute then we don't know anything
1834 // and must drop the attribute from the caller.
1835 Caller.removeFnAttr("min-legal-vector-width");
1836 }
1837 }
1838 }
1839
1840 /// If the inlined function has "null-pointer-is-valid=true" attribute,
1841 /// set this attribute in the caller post inlining.
1842 static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)1843 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
1844 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
1845 Caller.addFnAttr(Callee.getFnAttribute("null-pointer-is-valid"));
1846 }
1847 }
1848
1849 #define GET_ATTR_COMPAT_FUNC
1850 #include "AttributesCompatFunc.inc"
1851
areInlineCompatible(const Function & Caller,const Function & Callee)1852 bool AttributeFuncs::areInlineCompatible(const Function &Caller,
1853 const Function &Callee) {
1854 return hasCompatibleFnAttrs(Caller, Callee);
1855 }
1856
mergeAttributesForInlining(Function & Caller,const Function & Callee)1857 void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
1858 const Function &Callee) {
1859 mergeFnAttrs(Caller, Callee);
1860 }
1861