Skip to content

Commit 896b543

Browse files
author
Wael Yehia
committed
comment changes and logic updates in TOCRestoreNeededForCallToImplementation
1 parent 27da809 commit 896b543

File tree

2 files changed

+26
-19
lines changed

2 files changed

+26
-19
lines changed

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3391,14 +3391,17 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
33913391
return false;
33923392
auto *F = cast<Function>(V);
33933393

3394-
// static functions are local
3394+
// Static functions are local
33953395
if (F->getLinkage() == GlobalValue::InternalLinkage)
33963396
return true;
3397-
// for now, declarations we treat as potentially non-local
3397+
// We treat declarations as non-local because the visibility attribute
3398+
// on a declaration might not match the definition, and AIX linker
3399+
// ignores the visibility on a reference.
33983400
if (F->isDeclarationForLinker())
33993401
return false;
3400-
// hidden visibility definitions cannot be preempted, so treat as local.
3401-
if (F->getVisibility() == GlobalValue::HiddenVisibility)
3402+
// hidden or protected visibility definitions cannot be preempted.
3403+
if (F->getVisibility() == GlobalValue::HiddenVisibility ||
3404+
F->getVisibility() == GlobalValue::ProtectedVisibility)
34023405
return true;
34033406

34043407
return false;
@@ -3417,9 +3420,12 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
34173420
return false;
34183421
}
34193422

3420-
// if one of the return values of the resolver function is not a
3421-
// local function, then we have to conservatively do a TOC save/restore.
34223423
auto *Resolver = GI.getResolverFunction();
3424+
// If the resolver is preemptible then we cannot rely on its implementation.
3425+
if (!isLocalFunc(Resolver))
3426+
return true;
3427+
// If one of the return values of the resolver function is not a
3428+
// local function, then we have to conservatively do a TOC save/restore.
34233429
for (auto &BB : *Resolver) {
34243430
if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
34253431
Value *RV = Ret->getReturnValue();
@@ -3459,12 +3465,12 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
34593465
* .vbyte 4, 0
34603466
* .csect .foo[PR],5
34613467
* .ref ifunc_sec.foo[RW]
3462-
* ld 12, L..foo_desc(2) # load foo's descriptor address
3463-
* ld 11, 16(12) # load the env pointer if target might be a non-C/C++ function, otherwise this load is omitted
3464-
* ld 12, 0(12) # load foo.addr
3468+
* lwz 12, L..foo_desc(2) # load foo's descriptor address
3469+
* lwz 11, 8(12) # load the env pointer if target might be a non-C/C++ function
3470+
* lwz 12, 0(12) # load foo.addr
34653471
* mtctr 12
34663472
* bctr # branch to CR without setting LR so that callee returns to the caller of .foo
3467-
* # -- End function
3473+
* # -- End function
34683474
*/
34693475
void PPCAIXAsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
34703476
// Set the Subtarget to that of the resolver.

llvm/lib/Target/PowerPC/PPCPrepareIFuncsOnAIX.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,18 @@ ModulePass *llvm::createPPCPrepareIFuncsOnAIXPass() {
5151
return new PPCPrepareIFuncsOnAIX();
5252
}
5353

54-
// @foo = ifunc i32 (), ptr @foo_resolver, !associated !0
55-
// define ptr @foo_resolver() {
56-
// ...
54+
// For each ifunc `foo` with a resolver `foo_resolver`, create a global variable
55+
// `__update_foo` in the `ifunc_sec` section, representing the pair:
56+
// { ptr @foo, ptr @foo_resolver }
57+
// The compiler arranges for the constructor function `__init_ifuncs` to be
58+
// included on the link step. The constructor walks the `ifunc_sec` section,
59+
// calling the resolver function and storing the result in foo's descriptor.
60+
// On AIX, the address of a function is the address of its descriptor, so the
61+
// constructor accesses foo's descriptor from the first field of the pair.
5762
//
58-
// %struct.IFUNC_PAIR = type { ptr, ptr }
59-
// @update_foo = internal global %struct.IFUNC_PAIR { ptr @foo, ptr
60-
// @foo_resolver }, section "ifunc_sec", align 8, !associated !1 declare void
61-
// @__init_ifuncs(...)
63+
// Since the global `__update_foo` is unreferenced, it's liveness needs to be
64+
// associated to the liveness of ifunc `foo`
6265
//
63-
// !0 = !{ptr @update_foo}
64-
// !1 = !{ptr @__init_ifuncs}
6566
bool PPCPrepareIFuncsOnAIX::runOnModule(Module &M) {
6667
if (M.ifuncs().empty())
6768
return false;

0 commit comments

Comments
 (0)