Explorar el Código

* fix code generation for interface wrappers: adjustment of self pointers with offsets > 16 bit crashed because it tried to allocate a virtual register, but the register allocator is not called for these wrappers. Always use the R11 register, which is scratch on ppc64, for now.

git-svn-id: trunk@16272 -
tom_at_work hace 14 años
padre
commit
e215b215d6
Se han modificado 1 ficheros con 39 adiciones y 0 borrados
  1. 39 0
      compiler/powerpc64/cgcpu.pas

+ 39 - 0
compiler/powerpc64/cgcpu.pas

@@ -85,6 +85,15 @@ type
     procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags;
       reg: TRegister); override;
 
+    { need to override this for ppc64 to avoid calling CG methods which allocate 
+      registers during creation of the interface wrappers to subtract ioffset from 
+      the self pointer. But register allocation does not take place for them (which
+      would probably be the generic fix) so we need to have a specialized method
+      that uses the R11 scratch register in these cases.
+      At the same time this allows > 32 bit offsets as well.
+    }
+    procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: aint);override;
+
     procedure g_profilecode(list: TAsmList); override;
     procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe:
       boolean); override;
@@ -1379,6 +1388,36 @@ begin
   end;
 end;
 
+procedure tcgppc.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: aint);
+var
+  hsym : tsym;
+  href : treference;
+  paraloc : Pcgparalocation;
+begin
+  if ((ioffset >= low(smallint)) and (ioffset < high(smallint)) then begin
+    { the original method can handle this }
+    inherited g_adjust_self_value(list, procdef, ioffset);
+    exit;
+  end;
+  { calculate the parameter info for the procdef }
+  procdef.init_paraloc_info(callerside);
+  hsym:=tsym(procdef.parast.Find('self'));
+  if not(assigned(hsym) and
+    (hsym.typ=paravarsym)) then
+    internalerror(2010103101);
+  paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+  while paraloc<>nil do
+    with paraloc^ do begin
+      case loc of
+        LOC_REGISTER:
+          a_load_const_reg(list, size, ioffset, NR_R11);
+          a_op_reg_reg(list, OP_SUB, size, NR_R11, register);
+        else
+          internalerror(2010103102);
+      end;
+      paraloc:=next;
+    end;
+end;
 
 procedure tcgppc.g_profilecode(list: TAsmList);
 begin