@@ -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 */
34693475void PPCAIXAsmPrinter::emitGlobalIFunc (Module &M, const GlobalIFunc &GI) {
34703476 // Set the Subtarget to that of the resolver.
0 commit comments