1 //===-- Globals.cpp - Implement the GlobalValue & GlobalVariable class ----===// 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 // This file implements the GlobalValue & GlobalVariable classes for the IR 10 // library. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "LLVMContextImpl.h" 15 #include "llvm/IR/ConstantRange.h" 16 #include "llvm/IR/Constants.h" 17 #include "llvm/IR/DerivedTypes.h" 18 #include "llvm/IR/GlobalAlias.h" 19 #include "llvm/IR/GlobalValue.h" 20 #include "llvm/IR/GlobalVariable.h" 21 #include "llvm/IR/Module.h" 22 #include "llvm/Support/Error.h" 23 #include "llvm/Support/ErrorHandling.h" 24 #include "llvm/Support/MD5.h" 25 #include "llvm/TargetParser/Triple.h" 26 using namespace llvm; 27 28 //===----------------------------------------------------------------------===// 29 // GlobalValue Class 30 //===----------------------------------------------------------------------===// 31 32 // GlobalValue should be a Constant, plus a type, a module, some flags, and an 33 // intrinsic ID. Add an assert to prevent people from accidentally growing 34 // GlobalValue while adding flags. 35 static_assert(sizeof(GlobalValue) == 36 sizeof(Constant) + 2 * sizeof(void *) + 2 * sizeof(unsigned), 37 "unexpected GlobalValue size growth"); 38 39 // GlobalObject adds a comdat. 40 static_assert(sizeof(GlobalObject) == sizeof(GlobalValue) + sizeof(void *), 41 "unexpected GlobalObject size growth"); 42 43 bool GlobalValue::isMaterializable() const { 44 if (const Function *F = dyn_cast<Function>(this)) 45 return F->isMaterializable(); 46 return false; 47 } 48 Error GlobalValue::materialize() { return getParent()->materialize(this); } 49 50 /// Override destroyConstantImpl to make sure it doesn't get called on 51 /// GlobalValue's because they shouldn't be treated like other constants. 52 void GlobalValue::destroyConstantImpl() { 53 llvm_unreachable("You can't GV->destroyConstantImpl()!"); 54 } 55 56 Value *GlobalValue::handleOperandChangeImpl(Value *From, Value *To) { 57 llvm_unreachable("Unsupported class for handleOperandChange()!"); 58 } 59 60 /// copyAttributesFrom - copy all additional attributes (those not needed to 61 /// create a GlobalValue) from the GlobalValue Src to this one. 62 void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { 63 setVisibility(Src->getVisibility()); 64 setUnnamedAddr(Src->getUnnamedAddr()); 65 setThreadLocalMode(Src->getThreadLocalMode()); 66 setDLLStorageClass(Src->getDLLStorageClass()); 67 setDSOLocal(Src->isDSOLocal()); 68 setPartition(Src->getPartition()); 69 if (Src->hasSanitizerMetadata()) 70 setSanitizerMetadata(Src->getSanitizerMetadata()); 71 else 72 removeSanitizerMetadata(); 73 } 74 75 GlobalValue::GUID GlobalValue::getGUID(StringRef GlobalName) { 76 return MD5Hash(GlobalName); 77 } 78 79 void GlobalValue::removeFromParent() { 80 switch (getValueID()) { 81 #define HANDLE_GLOBAL_VALUE(NAME) \ 82 case Value::NAME##Val: \ 83 return static_cast<NAME *>(this)->removeFromParent(); 84 #include "llvm/IR/Value.def" 85 default: 86 break; 87 } 88 llvm_unreachable("not a global"); 89 } 90 91 void GlobalValue::eraseFromParent() { 92 switch (getValueID()) { 93 #define HANDLE_GLOBAL_VALUE(NAME) \ 94 case Value::NAME##Val: \ 95 return static_cast<NAME *>(this)->eraseFromParent(); 96 #include "llvm/IR/Value.def" 97 default: 98 break; 99 } 100 llvm_unreachable("not a global"); 101 } 102 103 GlobalObject::~GlobalObject() { setComdat(nullptr); } 104 105 bool GlobalValue::isInterposable() const { 106 if (isInterposableLinkage(getLinkage())) 107 return true; 108 return getParent() && getParent()->getSemanticInterposition() && 109 !isDSOLocal(); 110 } 111 112 bool GlobalValue::canBenefitFromLocalAlias() const { 113 // See AsmPrinter::getSymbolPreferLocal(). For a deduplicate comdat kind, 114 // references to a discarded local symbol from outside the group are not 115 // allowed, so avoid the local alias. 116 auto isDeduplicateComdat = [](const Comdat *C) { 117 return C && C->getSelectionKind() != Comdat::NoDeduplicate; 118 }; 119 return hasDefaultVisibility() && 120 GlobalObject::isExternalLinkage(getLinkage()) && !isDeclaration() && 121 !isa<GlobalIFunc>(this) && !isDeduplicateComdat(getComdat()); 122 } 123 124 const DataLayout &GlobalValue::getDataLayout() const { 125 return getParent()->getDataLayout(); 126 } 127 128 void GlobalObject::setAlignment(MaybeAlign Align) { 129 assert((!Align || *Align <= MaximumAlignment) && 130 "Alignment is greater than MaximumAlignment!"); 131 unsigned AlignmentData = encode(Align); 132 unsigned OldData = getGlobalValueSubClassData(); 133 setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData); 134 assert(getAlign() == Align && "Alignment representation error!"); 135 } 136 137 void GlobalObject::setAlignment(Align Align) { 138 assert(Align <= MaximumAlignment && 139 "Alignment is greater than MaximumAlignment!"); 140 unsigned AlignmentData = encode(Align); 141 unsigned OldData = getGlobalValueSubClassData(); 142 setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData); 143 assert(getAlign() && *getAlign() == Align && 144 "Alignment representation error!"); 145 } 146 147 void GlobalObject::copyAttributesFrom(const GlobalObject *Src) { 148 GlobalValue::copyAttributesFrom(Src); 149 setAlignment(Src->getAlign()); 150 setSection(Src->getSection()); 151 } 152 153 std::string GlobalValue::getGlobalIdentifier(StringRef Name, 154 GlobalValue::LinkageTypes Linkage, 155 StringRef FileName) { 156 // Value names may be prefixed with a binary '1' to indicate 157 // that the backend should not modify the symbols due to any platform 158 // naming convention. Do not include that '1' in the PGO profile name. 159 Name.consume_front("\1"); 160 161 std::string GlobalName; 162 if (llvm::GlobalValue::isLocalLinkage(Linkage)) { 163 // For local symbols, prepend the main file name to distinguish them. 164 // Do not include the full path in the file name since there's no guarantee 165 // that it will stay the same, e.g., if the files are checked out from 166 // version control in different locations. 167 if (FileName.empty()) 168 GlobalName += "<unknown>"; 169 else 170 GlobalName += FileName; 171 172 GlobalName += GlobalIdentifierDelimiter; 173 } 174 GlobalName += Name; 175 return GlobalName; 176 } 177 178 std::string GlobalValue::getGlobalIdentifier() const { 179 return getGlobalIdentifier(getName(), getLinkage(), 180 getParent()->getSourceFileName()); 181 } 182 183 StringRef GlobalValue::getSection() const { 184 if (auto *GA = dyn_cast<GlobalAlias>(this)) { 185 // In general we cannot compute this at the IR level, but we try. 186 if (const GlobalObject *GO = GA->getAliaseeObject()) 187 return GO->getSection(); 188 return ""; 189 } 190 return cast<GlobalObject>(this)->getSection(); 191 } 192 193 const Comdat *GlobalValue::getComdat() const { 194 if (auto *GA = dyn_cast<GlobalAlias>(this)) { 195 // In general we cannot compute this at the IR level, but we try. 196 if (const GlobalObject *GO = GA->getAliaseeObject()) 197 return const_cast<GlobalObject *>(GO)->getComdat(); 198 return nullptr; 199 } 200 // ifunc and its resolver are separate things so don't use resolver comdat. 201 if (isa<GlobalIFunc>(this)) 202 return nullptr; 203 return cast<GlobalObject>(this)->getComdat(); 204 } 205 206 void GlobalObject::setComdat(Comdat *C) { 207 if (ObjComdat) 208 ObjComdat->removeUser(this); 209 ObjComdat = C; 210 if (C) 211 C->addUser(this); 212 } 213 214 StringRef GlobalValue::getPartition() const { 215 if (!hasPartition()) 216 return ""; 217 return getContext().pImpl->GlobalValuePartitions[this]; 218 } 219 220 void GlobalValue::setPartition(StringRef S) { 221 // Do nothing if we're clearing the partition and it is already empty. 222 if (!hasPartition() && S.empty()) 223 return; 224 225 // Get or create a stable partition name string and put it in the table in the 226 // context. 227 if (!S.empty()) 228 S = getContext().pImpl->Saver.save(S); 229 getContext().pImpl->GlobalValuePartitions[this] = S; 230 231 // Update the HasPartition field. Setting the partition to the empty string 232 // means this global no longer has a partition. 233 HasPartition = !S.empty(); 234 } 235 236 using SanitizerMetadata = GlobalValue::SanitizerMetadata; 237 const SanitizerMetadata &GlobalValue::getSanitizerMetadata() const { 238 assert(hasSanitizerMetadata()); 239 assert(getContext().pImpl->GlobalValueSanitizerMetadata.count(this)); 240 return getContext().pImpl->GlobalValueSanitizerMetadata[this]; 241 } 242 243 void GlobalValue::setSanitizerMetadata(SanitizerMetadata Meta) { 244 getContext().pImpl->GlobalValueSanitizerMetadata[this] = Meta; 245 HasSanitizerMetadata = true; 246 } 247 248 void GlobalValue::removeSanitizerMetadata() { 249 DenseMap<const GlobalValue *, SanitizerMetadata> &MetadataMap = 250 getContext().pImpl->GlobalValueSanitizerMetadata; 251 MetadataMap.erase(this); 252 HasSanitizerMetadata = false; 253 } 254 255 void GlobalValue::setNoSanitizeMetadata() { 256 SanitizerMetadata Meta; 257 Meta.NoAddress = true; 258 Meta.NoHWAddress = true; 259 setSanitizerMetadata(Meta); 260 } 261 262 StringRef GlobalObject::getSectionImpl() const { 263 assert(hasSection()); 264 return getContext().pImpl->GlobalObjectSections[this]; 265 } 266 267 void GlobalObject::setSection(StringRef S) { 268 // Do nothing if we're clearing the section and it is already empty. 269 if (!hasSection() && S.empty()) 270 return; 271 272 // Get or create a stable section name string and put it in the table in the 273 // context. 274 if (!S.empty()) 275 S = getContext().pImpl->Saver.save(S); 276 getContext().pImpl->GlobalObjectSections[this] = S; 277 278 // Update the HasSectionHashEntryBit. Setting the section to the empty string 279 // means this global no longer has a section. 280 setGlobalObjectFlag(HasSectionHashEntryBit, !S.empty()); 281 } 282 283 bool GlobalValue::isNobuiltinFnDef() const { 284 const Function *F = dyn_cast<Function>(this); 285 if (!F || F->empty()) 286 return false; 287 return F->hasFnAttribute(Attribute::NoBuiltin); 288 } 289 290 bool GlobalValue::isDeclaration() const { 291 // Globals are definitions if they have an initializer. 292 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(this)) 293 return GV->getNumOperands() == 0; 294 295 // Functions are definitions if they have a body. 296 if (const Function *F = dyn_cast<Function>(this)) 297 return F->empty() && !F->isMaterializable(); 298 299 // Aliases and ifuncs are always definitions. 300 assert(isa<GlobalAlias>(this) || isa<GlobalIFunc>(this)); 301 return false; 302 } 303 304 bool GlobalObject::canIncreaseAlignment() const { 305 // Firstly, can only increase the alignment of a global if it 306 // is a strong definition. 307 if (!isStrongDefinitionForLinker()) 308 return false; 309 310 // It also has to either not have a section defined, or, not have 311 // alignment specified. (If it is assigned a section, the global 312 // could be densely packed with other objects in the section, and 313 // increasing the alignment could cause padding issues.) 314 if (hasSection() && getAlign()) 315 return false; 316 317 // On ELF platforms, we're further restricted in that we can't 318 // increase the alignment of any variable which might be emitted 319 // into a shared library, and which is exported. If the main 320 // executable accesses a variable found in a shared-lib, the main 321 // exe actually allocates memory for and exports the symbol ITSELF, 322 // overriding the symbol found in the library. That is, at link 323 // time, the observed alignment of the variable is copied into the 324 // executable binary. (A COPY relocation is also generated, to copy 325 // the initial data from the shadowed variable in the shared-lib 326 // into the location in the main binary, before running code.) 327 // 328 // And thus, even though you might think you are defining the 329 // global, and allocating the memory for the global in your object 330 // file, and thus should be able to set the alignment arbitrarily, 331 // that's not actually true. Doing so can cause an ABI breakage; an 332 // executable might have already been built with the previous 333 // alignment of the variable, and then assuming an increased 334 // alignment will be incorrect. 335 336 // Conservatively assume ELF if there's no parent pointer. 337 bool isELF = 338 (!Parent || Triple(Parent->getTargetTriple()).isOSBinFormatELF()); 339 if (isELF && !isDSOLocal()) 340 return false; 341 342 // GV with toc-data attribute is defined in a TOC entry. To mitigate TOC 343 // overflow, the alignment of such symbol should not be increased. Otherwise, 344 // padding is needed thus more TOC entries are wasted. 345 bool isXCOFF = 346 (!Parent || Triple(Parent->getTargetTriple()).isOSBinFormatXCOFF()); 347 if (isXCOFF) 348 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(this)) 349 if (GV->hasAttribute("toc-data")) 350 return false; 351 352 return true; 353 } 354 355 template <typename Operation> 356 static const GlobalObject * 357 findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases, 358 const Operation &Op) { 359 if (auto *GO = dyn_cast<GlobalObject>(C)) { 360 Op(*GO); 361 return GO; 362 } 363 if (auto *GA = dyn_cast<GlobalAlias>(C)) { 364 Op(*GA); 365 if (Aliases.insert(GA).second) 366 return findBaseObject(GA->getOperand(0), Aliases, Op); 367 } 368 if (auto *CE = dyn_cast<ConstantExpr>(C)) { 369 switch (CE->getOpcode()) { 370 case Instruction::Add: { 371 auto *LHS = findBaseObject(CE->getOperand(0), Aliases, Op); 372 auto *RHS = findBaseObject(CE->getOperand(1), Aliases, Op); 373 if (LHS && RHS) 374 return nullptr; 375 return LHS ? LHS : RHS; 376 } 377 case Instruction::Sub: { 378 if (findBaseObject(CE->getOperand(1), Aliases, Op)) 379 return nullptr; 380 return findBaseObject(CE->getOperand(0), Aliases, Op); 381 } 382 case Instruction::IntToPtr: 383 case Instruction::PtrToInt: 384 case Instruction::BitCast: 385 case Instruction::GetElementPtr: 386 return findBaseObject(CE->getOperand(0), Aliases, Op); 387 default: 388 break; 389 } 390 } 391 return nullptr; 392 } 393 394 const GlobalObject *GlobalValue::getAliaseeObject() const { 395 DenseSet<const GlobalAlias *> Aliases; 396 return findBaseObject(this, Aliases, [](const GlobalValue &) {}); 397 } 398 399 bool GlobalValue::isAbsoluteSymbolRef() const { 400 auto *GO = dyn_cast<GlobalObject>(this); 401 if (!GO) 402 return false; 403 404 return GO->getMetadata(LLVMContext::MD_absolute_symbol); 405 } 406 407 std::optional<ConstantRange> GlobalValue::getAbsoluteSymbolRange() const { 408 auto *GO = dyn_cast<GlobalObject>(this); 409 if (!GO) 410 return std::nullopt; 411 412 MDNode *MD = GO->getMetadata(LLVMContext::MD_absolute_symbol); 413 if (!MD) 414 return std::nullopt; 415 416 return getConstantRangeFromMetadata(*MD); 417 } 418 419 bool GlobalValue::canBeOmittedFromSymbolTable() const { 420 if (!hasLinkOnceODRLinkage()) 421 return false; 422 423 // We assume that anyone who sets global unnamed_addr on a non-constant 424 // knows what they're doing. 425 if (hasGlobalUnnamedAddr()) 426 return true; 427 428 // If it is a non constant variable, it needs to be uniqued across shared 429 // objects. 430 if (auto *Var = dyn_cast<GlobalVariable>(this)) 431 if (!Var->isConstant()) 432 return false; 433 434 return hasAtLeastLocalUnnamedAddr(); 435 } 436 437 //===----------------------------------------------------------------------===// 438 // GlobalVariable Implementation 439 //===----------------------------------------------------------------------===// 440 441 GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, 442 Constant *InitVal, const Twine &Name, 443 ThreadLocalMode TLMode, unsigned AddressSpace, 444 bool isExternallyInitialized) 445 : GlobalObject(Ty, Value::GlobalVariableVal, 446 OperandTraits<GlobalVariable>::op_begin(this), 447 InitVal != nullptr, Link, Name, AddressSpace), 448 isConstantGlobal(constant), 449 isExternallyInitializedConstant(isExternallyInitialized) { 450 assert(!Ty->isFunctionTy() && PointerType::isValidElementType(Ty) && 451 "invalid type for global variable"); 452 setThreadLocalMode(TLMode); 453 if (InitVal) { 454 assert(InitVal->getType() == Ty && 455 "Initializer should be the same type as the GlobalVariable!"); 456 Op<0>() = InitVal; 457 } 458 } 459 460 GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, 461 LinkageTypes Link, Constant *InitVal, 462 const Twine &Name, GlobalVariable *Before, 463 ThreadLocalMode TLMode, 464 std::optional<unsigned> AddressSpace, 465 bool isExternallyInitialized) 466 : GlobalVariable(Ty, constant, Link, InitVal, Name, TLMode, 467 AddressSpace 468 ? *AddressSpace 469 : M.getDataLayout().getDefaultGlobalsAddressSpace(), 470 isExternallyInitialized) { 471 if (Before) 472 Before->getParent()->insertGlobalVariable(Before->getIterator(), this); 473 else 474 M.insertGlobalVariable(this); 475 } 476 477 void GlobalVariable::removeFromParent() { 478 getParent()->removeGlobalVariable(this); 479 } 480 481 void GlobalVariable::eraseFromParent() { 482 getParent()->eraseGlobalVariable(this); 483 } 484 485 void GlobalVariable::setInitializer(Constant *InitVal) { 486 if (!InitVal) { 487 if (hasInitializer()) { 488 // Note, the num operands is used to compute the offset of the operand, so 489 // the order here matters. Clearing the operand then clearing the num 490 // operands ensures we have the correct offset to the operand. 491 Op<0>().set(nullptr); 492 setGlobalVariableNumOperands(0); 493 } 494 } else { 495 assert(InitVal->getType() == getValueType() && 496 "Initializer type must match GlobalVariable type"); 497 // Note, the num operands is used to compute the offset of the operand, so 498 // the order here matters. We need to set num operands to 1 first so that 499 // we get the correct offset to the first operand when we set it. 500 if (!hasInitializer()) 501 setGlobalVariableNumOperands(1); 502 Op<0>().set(InitVal); 503 } 504 } 505 506 /// Copy all additional attributes (those not needed to create a GlobalVariable) 507 /// from the GlobalVariable Src to this one. 508 void GlobalVariable::copyAttributesFrom(const GlobalVariable *Src) { 509 GlobalObject::copyAttributesFrom(Src); 510 setExternallyInitialized(Src->isExternallyInitialized()); 511 setAttributes(Src->getAttributes()); 512 if (auto CM = Src->getCodeModel()) 513 setCodeModel(*CM); 514 } 515 516 void GlobalVariable::dropAllReferences() { 517 User::dropAllReferences(); 518 clearMetadata(); 519 } 520 521 void GlobalVariable::setCodeModel(CodeModel::Model CM) { 522 unsigned CodeModelData = static_cast<unsigned>(CM) + 1; 523 unsigned OldData = getGlobalValueSubClassData(); 524 unsigned NewData = (OldData & ~(CodeModelMask << CodeModelShift)) | 525 (CodeModelData << CodeModelShift); 526 setGlobalValueSubClassData(NewData); 527 assert(getCodeModel() == CM && "Code model representation error!"); 528 } 529 530 //===----------------------------------------------------------------------===// 531 // GlobalAlias Implementation 532 //===----------------------------------------------------------------------===// 533 534 GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, 535 const Twine &Name, Constant *Aliasee, 536 Module *ParentModule) 537 : GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name, 538 AddressSpace) { 539 setAliasee(Aliasee); 540 if (ParentModule) 541 ParentModule->insertAlias(this); 542 } 543 544 GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, 545 LinkageTypes Link, const Twine &Name, 546 Constant *Aliasee, Module *ParentModule) { 547 return new GlobalAlias(Ty, AddressSpace, Link, Name, Aliasee, ParentModule); 548 } 549 550 GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, 551 LinkageTypes Linkage, const Twine &Name, 552 Module *Parent) { 553 return create(Ty, AddressSpace, Linkage, Name, nullptr, Parent); 554 } 555 556 GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, 557 LinkageTypes Linkage, const Twine &Name, 558 GlobalValue *Aliasee) { 559 return create(Ty, AddressSpace, Linkage, Name, Aliasee, Aliasee->getParent()); 560 } 561 562 GlobalAlias *GlobalAlias::create(LinkageTypes Link, const Twine &Name, 563 GlobalValue *Aliasee) { 564 return create(Aliasee->getValueType(), Aliasee->getAddressSpace(), Link, Name, 565 Aliasee); 566 } 567 568 GlobalAlias *GlobalAlias::create(const Twine &Name, GlobalValue *Aliasee) { 569 return create(Aliasee->getLinkage(), Name, Aliasee); 570 } 571 572 void GlobalAlias::removeFromParent() { getParent()->removeAlias(this); } 573 574 void GlobalAlias::eraseFromParent() { getParent()->eraseAlias(this); } 575 576 void GlobalAlias::setAliasee(Constant *Aliasee) { 577 assert((!Aliasee || Aliasee->getType() == getType()) && 578 "Alias and aliasee types should match!"); 579 Op<0>().set(Aliasee); 580 } 581 582 const GlobalObject *GlobalAlias::getAliaseeObject() const { 583 DenseSet<const GlobalAlias *> Aliases; 584 return findBaseObject(getOperand(0), Aliases, [](const GlobalValue &) {}); 585 } 586 587 //===----------------------------------------------------------------------===// 588 // GlobalIFunc Implementation 589 //===----------------------------------------------------------------------===// 590 591 GlobalIFunc::GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Link, 592 const Twine &Name, Constant *Resolver, 593 Module *ParentModule) 594 : GlobalObject(Ty, Value::GlobalIFuncVal, &Op<0>(), 1, Link, Name, 595 AddressSpace) { 596 setResolver(Resolver); 597 if (ParentModule) 598 ParentModule->insertIFunc(this); 599 } 600 601 GlobalIFunc *GlobalIFunc::create(Type *Ty, unsigned AddressSpace, 602 LinkageTypes Link, const Twine &Name, 603 Constant *Resolver, Module *ParentModule) { 604 return new GlobalIFunc(Ty, AddressSpace, Link, Name, Resolver, ParentModule); 605 } 606 607 void GlobalIFunc::removeFromParent() { getParent()->removeIFunc(this); } 608 609 void GlobalIFunc::eraseFromParent() { getParent()->eraseIFunc(this); } 610 611 const Function *GlobalIFunc::getResolverFunction() const { 612 return dyn_cast<Function>(getResolver()->stripPointerCastsAndAliases()); 613 } 614 615 void GlobalIFunc::applyAlongResolverPath( 616 function_ref<void(const GlobalValue &)> Op) const { 617 DenseSet<const GlobalAlias *> Aliases; 618 findBaseObject(getResolver(), Aliases, Op); 619 } 620