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