Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/IR/Globals.cpp
35233 views
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
621