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)