Browse Source

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
Jonas Maebe 3 years ago
parent
commit
68b5ca633c
2 changed files with 16 additions and 3 deletions
  1. 6 3
      compiler/ncgvmt.pas
  2. 10 0
      compiler/systems.pas

+ 6 - 3
compiler/ncgvmt.pas

@@ -1229,11 +1229,14 @@ implementation
 {$if defined(cpuhighleveltarget)}
 {$if defined(cpuhighleveltarget)}
         usehighlevelwrapper:=true;
         usehighlevelwrapper:=true;
 {$else defined(cpuhighleveltarget)}
 {$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
           usehighlevelwrapper:=true
         else
         else
-{$endif defined(powerpc64)}
           usehighlevelwrapper:=false;
           usehighlevelwrapper:=false;
 {$endif defined(cpuhighleveltarget)}
 {$endif defined(cpuhighleveltarget)}
         for i:=0 to _class.ImplementedInterfaces.count-1 do
         for i:=0 to _class.ImplementedInterfaces.count-1 do

+ 10 - 0
compiler/systems.pas

@@ -448,6 +448,16 @@ interface
          on the caller side rather than on the callee side }
          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];
        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,
        { pointer checking (requires special code in FPC_CHECKPOINTER,
          and can never work for libc-based targets or any other program
          and can never work for libc-based targets or any other program
          linking to an external library)
          linking to an external library)