Forráskód Böngészése

TOC handling: clean up

Also fix on 32 bits PowerPC
Jonas Maebe 3 éve
szülő
commit
629c1de460

+ 1 - 1
compiler/ncgvmt.pas

@@ -1234,7 +1234,7 @@ implementation
           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
+        if target_info.abi in abis_ppc_toc then
           usehighlevelwrapper:=true
         else
           usehighlevelwrapper:=false;

+ 19 - 3
compiler/powerpc/cgcpu.pas

@@ -911,9 +911,17 @@ const
               end;
           end;
 
-        { save the CR if necessary ( !!! never done currently ) }
-{       still need to find out where this has to be done for SystemV
-        a_reg_alloc(list,R_0);
+        { save current RTOC for restoration after calls if necessary }
+        if (pi_do_call in current_procinfo.flags) and
+           (target_info.abi in abis_ppc_toc) then
+          begin
+            reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
+            a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
+          end;
+
+        { save the CR if/when we ever start using caller-save portions of that
+          register}
+{       a_reg_alloc(list,R_0);
         list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
         list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
           new_reference(STACK_POINTER_REG,LA_CR)));
@@ -1306,6 +1314,14 @@ const
                 a_reg_dealloc(list,href.index);
               end;
           end;
+
+        { save current RTOC for restoration after calls if necessary }
+        if pi_do_call in current_procinfo.flags then
+          begin
+            reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
+            a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
+          end;
+
       end;
 
     procedure tcgppc.g_return_from_proc_mac(list : TAsmList;parasize : tcgint);

+ 38 - 49
compiler/powerpc64/cgcpu.pas

@@ -305,22 +305,6 @@ begin
 end;
 
 
-function get_rtoc_offset: longint;
-begin
-  result:=0;
-  case target_info.abi of
-    abi_powerpc_aix,
-    abi_powerpc_darwin:
-      result:=LA_RTOC_AIX;
-    abi_powerpc_elfv1:
-      result:=LA_RTOC_SYSV;
-    abi_powerpc_elfv2:
-      result:=LA_RTOC_ELFV2;
-    else
-      internalerror(2015021001);
-  end;
-end;
-
 { calling a procedure by address }
 
 procedure tcgppc.a_call_reg(list: TAsmList; reg: tregister);
@@ -330,40 +314,44 @@ var
 begin
   if (target_info.abi<>abi_powerpc_sysv) then
     inherited a_call_reg(list,reg)
-  else if (not (cs_opt_size in current_settings.optimizerswitches)) then begin
-    tempreg := getintregister(list, OS_INT);
-    { load actual function entry (reg contains the reference to the function descriptor)
-    into tempreg }
-    reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
-    a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
-
-    { move actual function pointer to CTR register }
-    list.concat(taicpu.op_reg(A_MTCTR, tempreg));
-
-    { load new TOC pointer from function descriptor into RTOC register }
-    reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
+  else
+    begin
+      if (not (cs_opt_size in current_settings.optimizerswitches)) then
+        begin
+          tempreg := getintregister(list, OS_INT);
+          { load actual function entry (reg contains the reference to the function descriptor)
+          into tempreg }
+          reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
+          a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
+
+          { move actual function pointer to CTR register }
+          list.concat(taicpu.op_reg(A_MTCTR, tempreg));
+
+          { load new TOC pointer from function descriptor into RTOC register }
+          reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
+          a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
+
+          { load new environment pointer from function descriptor into R11 register }
+          reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
+          a_reg_alloc(list, NR_R11);
+          a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
+          { call function }
+          list.concat(taicpu.op_none(A_BCTRL));
+          a_reg_dealloc(list, NR_R11);
+        end
+    else
+      begin
+        { call ptrgl helper routine which expects the pointer to the function descriptor
+        in R11 }
+        a_reg_alloc(list, NR_R11);
+        a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
+        a_call_name_direct(list, A_BL, '.ptrgl', false, false, false);
+        a_reg_dealloc(list, NR_R11);
+      end;
+    { we need to load the old RTOC from stackframe because we changed it}
+    reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
     a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
-
-    { load new environment pointer from function descriptor into R11 register }
-    reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
-    a_reg_alloc(list, NR_R11);
-    a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
-    { call function }
-    list.concat(taicpu.op_none(A_BCTRL));
-    a_reg_dealloc(list, NR_R11);
-  end else begin
-    { call ptrgl helper routine which expects the pointer to the function descriptor
-    in R11 }
-    a_reg_alloc(list, NR_R11);
-    a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
-    a_call_name_direct(list, A_BL, '.ptrgl', false, false, false);
-    a_reg_dealloc(list, NR_R11);
   end;
-
-  { we need to load the old RTOC from stackframe because we changed it}
-  reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
-  a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
-
   include(current_procinfo.flags, pi_do_call);
 end;
 
@@ -1270,7 +1258,8 @@ begin
   end;
 
   { save current RTOC for restoration after calls if necessary }
-  if pi_do_call in current_procinfo.flags then
+  if (pi_do_call in current_procinfo.flags) and
+     (target_info.abi in abis_ppc_toc) then
     begin
       reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
       a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);

+ 21 - 13
compiler/ppcgen/cgppc.pas

@@ -89,6 +89,8 @@ unit cgppc;
         procedure a_jmp(list: TAsmList; op: tasmop;
                         c: tasmcondflag; crval: longint; l: tasmlabel);
 
+        function get_rtoc_offset: longint;
+
         function save_lr_in_prologue: boolean;
 
         function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
@@ -123,7 +125,6 @@ unit cgppc;
                          C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
     TocSecBaseName = 'toc_table';
 
-
 {$ifdef extdebug}
      function ref2string(const ref : treference) : string;
      function cgop2string(const op : TOpCg) : String;
@@ -473,9 +474,6 @@ unit cgppc;
             { no need to allocate/free R0, is already allocated by call node
               because it's a volatile register }
             reg:=NR_R0;
-            { save current TOC }
-            reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_AIX,ctempposinvalid,sizeof(pint),[]);
-            a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,tmpref);
           end;
         list.concat(taicpu.op_reg(A_MTCTR,reg));
         if target_info.system in systems_aix then
@@ -488,9 +486,6 @@ unit cgppc;
           end
         else if target_info.abi=abi_powerpc_elfv2 then
           begin
-            { save current TOC }
-            reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_ELFV2,ctempposinvalid,sizeof(pint),[]);
-            a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,tmpref);
             { functions must be called via R12 for this ABI }
             if reg<>NR_R12 then
               begin
@@ -499,17 +494,13 @@ unit cgppc;
               end;
           end;
         list.concat(taicpu.op_none(A_BCTRL));
-        if (target_info.system in systems_aix) or
-           (target_info.abi=abi_powerpc_elfv2) then
+        if target_info.abi in abis_ppc_toc then
           begin
             if (target_info.abi=abi_powerpc_elfv2) and
                (reg<>NR_R12) then
               ungetcpuregister(list,NR_R12);
             { restore our TOC }
-            if target_info.system in systems_aix then
-              toc_offset:=LA_RTOC_AIX
-            else
-              toc_offset:=LA_RTOC_ELFV2;
+            toc_offset:=get_rtoc_offset;
             reference_reset_base(tmpref,NR_STACK_POINTER_REG,toc_offset,ctempposinvalid,sizeof(pint),[]);
             a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_RTOC);
           end;
@@ -743,6 +734,23 @@ unit cgppc;
      list.concat(p)
    end;
 
+ function tcgppcgen.get_rtoc_offset: longint;
+   begin
+     case target_info.abi of
+       abi_powerpc_aix:
+         result:=LA_RTOC_AIX;
+{$ifdef powerpc64}
+       { no TOC on Linux/ppc32 }
+       abi_powerpc_elfv1:
+         result:=LA_RTOC_SYSV;
+{$endif}
+       abi_powerpc_elfv2:
+         result:=LA_RTOC_ELFV2;
+       else
+         internalerror(2015021001);
+     end;
+   end;
+
 
 
   function tcgppcgen.load_got_symbol(list: TAsmList; const symbol : string; const flags: tindsymflags) : tregister;

+ 3 - 8
compiler/systems.pas

@@ -448,14 +448,9 @@ 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
+       { all PPC ABIs that use a TOC register to address globals }
+       abis_ppc_toc = [
+         abi_powerpc_sysv,abi_powerpc_aix,abi_powerpc_elfv2
        ];
 
        { pointer checking (requires special code in FPC_CHECKPOINTER,