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