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