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