From 68b5ca633ca71a83c29b78cd3669bf15477cd94f Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 5 Feb 2022 21:34:00 +0100 Subject: [PATCH] ppc platforms: fix missing TOC restoration room PPC platforms that use a TOC can never use a tail call to call a different routine that potentially accesses globals, as it may use a different TOC and then the linker must be able to insert an instruction after the branch to restore the original TOC register value on "return". Even if FPC code itself does not use the TOC register, it's still required since 1) the linker does not know this, and 2) the FPC code might still be called from other code that does use it --- compiler/ncgvmt.pas | 9 ++++++--- compiler/systems.pas | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/compiler/ncgvmt.pas b/compiler/ncgvmt.pas index 4110bd313b..c049ac1f28 100644 --- a/compiler/ncgvmt.pas +++ b/compiler/ncgvmt.pas @@ -1229,11 +1229,14 @@ implementation {$if defined(cpuhighleveltarget)} usehighlevelwrapper:=true; {$else defined(cpuhighleveltarget)} -{$if defined(powerpc64)} - if cs_create_pic in current_settings.moduleswitches then + { on PPC systems that use a TOC the linker needs to be able to insert + an instruction to restore the TOC register after every branch + between code fragments that use a different TOC (which has to be + executed when that "branch" returns). So we can't use tail call + branches to routines potentially using a different TOC there } + if target_info.system in systems_ppc_toc then usehighlevelwrapper:=true else -{$endif defined(powerpc64)} usehighlevelwrapper:=false; {$endif defined(cpuhighleveltarget)} for i:=0 to _class.ImplementedInterfaces.count-1 do diff --git a/compiler/systems.pas b/compiler/systems.pas index 48a231266d..2c6d805971 100644 --- a/compiler/systems.pas +++ b/compiler/systems.pas @@ -448,6 +448,16 @@ interface on the caller side rather than on the callee side } systems_caller_copy_addr_value_para = [system_aarch64_ios,system_aarch64_darwin,system_aarch64_linux,system_aarch64_win64,system_aarch64_freebsd]; + { all PPC systems that use a TOC register to address globals } + { TODO: not used by Darwin, but don't know about others (JM) } + systems_ppc_toc = [ + system_powerpc_linux, + system_powerpc64_linux, + system_powerpc_aix, + system_powerpc64_aix, + system_powerpc_macosclassic + ]; + { pointer checking (requires special code in FPC_CHECKPOINTER, and can never work for libc-based targets or any other program linking to an external library)