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