瀏覽代碼

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 年之前
父節點
當前提交
68b5ca633c
共有 2 個文件被更改,包括 16 次插入3 次删除
  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)}
         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

+ 10 - 0
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)