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