@@ -3398,7 +3398,8 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
33983398 // Query if the given function is local to the load module.
33993399 auto IsLocalFunc = [](const Function *F) -> IsLocal {
34003400 bool Result = F->isStrongDefinitionForLinker () && F->isDSOLocal ();
3401- LLVM_DEBUG (dbgs () << F->getName () << " is " << (Result ? " local\n " : " not local\n " ));
3401+ LLVM_DEBUG (dbgs () << F->getName () << " is "
3402+ << (Result ? " local\n " : " not local\n " ));
34023403 return Result ? IsLocal::True : IsLocal::False;
34033404 };
34043405
@@ -3489,12 +3490,13 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
34893490 * .vbyte 4, 0
34903491 * .csect .foo[PR],5
34913492 * .ref ifunc_sec.foo[RW]
3492- * lwz 12, L..foo_desc(2) # load foo's descriptor address
3493- * lwz 11, 8(12) # load the env pointer if target might be a non-C/C++ function
3494- * lwz 12, 0(12) # load foo.addr
3493+ * lwz 12, L..foo_desc(2) # load foo's descriptor address
3494+ * lwz 11, 8(12) # load the env pointer (for non-C/C++ functions)
3495+ * lwz 12, 0(12) # load foo.addr
34953496 * mtctr 12
3496- * bctr # branch to CR without setting LR so that callee returns to the caller of .foo
3497- * # -- End function
3497+ * bctr # branch to CR without setting LR so that callee
3498+ * # returns to the caller of .foo
3499+ * # -- End function
34983500 */
34993501void PPCAIXAsmPrinter::emitGlobalIFunc (Module &M, const GlobalIFunc &GI) {
35003502 // Set the Subtarget to that of the resolver.
@@ -3571,23 +3573,41 @@ void PPCAIXAsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
35713573 if (TOCRestoreNeededForCallToImplementation (GI)) {
35723574 reportFatalUsageError (
35733575 " unimplemented: TOC register save/restore needed for ifunc \" " +
3574- Twine (GI.getName ()) + " \" , because couldn't prove all candidates are "
3575- " static or hidden/protected visibility definitions" );
3576+ Twine (GI.getName ()) + " \" , because couldn't prove all candidates "
3577+ " are static or hidden/protected visibility definitions" );
35763578 return ;
35773579 }
35783580
3579- // lwz 12, L..foo_desc(2)
35803581 auto FnDescTOCEntryType = getTOCEntryTypeForLinkage (GI.getLinkage ());
35813582 auto *FnDescTOCEntrySym =
35823583 lookUpOrCreateTOCEntry (CurrentFnDescSym, FnDescTOCEntryType);
3583- auto *Exp = MCSymbolRefExpr::create (FnDescTOCEntrySym, OutContext);
3584- // Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);// TODO: need this?
3585- // need this uncommented
3586- OutStreamer->emitInstruction (MCInstBuilder (IsPPC64 ? PPC::LD : PPC::LWZ)
3587- .addReg (PPC::X12)
3588- .addExpr (Exp)
3589- .addReg (PPC::X2),
3590- *Subtarget);
3584+
3585+ if (TM.getCodeModel () == CodeModel::Large) {
3586+ // addis 12, L..foo_desc@u(2)
3587+ // lwz 12, L..foo_desc@l(12)
3588+ auto *Exp_U = symbolWithSpecifier (FnDescTOCEntrySym, PPC::S_U);
3589+ OutStreamer->emitInstruction (MCInstBuilder (PPC::ADDIS)
3590+ .addReg (PPC::X12)
3591+ .addReg (PPC::X2)
3592+ .addExpr (Exp_U),
3593+ *Subtarget);
3594+ auto *Exp_L = symbolWithSpecifier (FnDescTOCEntrySym, PPC::S_L);
3595+ OutStreamer->emitInstruction (MCInstBuilder (IsPPC64 ? PPC::LD : PPC::LWZ)
3596+ .addReg (PPC::X12)
3597+ .addExpr (Exp_L)
3598+ .addReg (PPC::X12),
3599+ *Subtarget);
3600+ } else {
3601+ // lwz 12, L..foo_desc(2)
3602+ auto *Exp = MCSymbolRefExpr::create (FnDescTOCEntrySym, OutContext);
3603+ // Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
3604+ // TODO: do we need to uncomment this?
3605+ OutStreamer->emitInstruction (MCInstBuilder (IsPPC64 ? PPC::LD : PPC::LWZ)
3606+ .addReg (PPC::X12)
3607+ .addExpr (Exp)
3608+ .addReg (PPC::X2),
3609+ *Subtarget);
3610+ }
35913611 // lwz 11, 8(12)
35923612 OutStreamer->emitInstruction (MCInstBuilder (IsPPC64 ? PPC::LD : PPC::LWZ)
35933613 .addReg (PPC::X11)
0 commit comments