2
0
Эх сурвалжийг харах

* improve powerpc64/linux stub for external procedures in units: also consider GOT change in call to this external procedure
* refactored above mentioned stub code generation, allowing the CG to define a cpu specific method for this task by overriding new g_external_wrapper() method

git-svn-id: trunk@8566 -

tom_at_work 18 жил өмнө
parent
commit
b0bb3f94a7

+ 10 - 0
compiler/cgobj.pas

@@ -474,6 +474,11 @@ unit cgobj;
           procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: aint);virtual;
 
           function g_indirect_sym_load(list:TAsmList;const symname: string): tregister;virtual;
+          { generate a stub which only purpose is to pass control the given external method, 
+          setting up any additional environment before doing so (if required).
+
+          The default implementation issues a jump instruction to the external name. }
+          procedure g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string); virtual;
         protected
           procedure get_subsetref_load_info(const sref: tsubsetreference; out loadsize: tcgsize; out extra_load: boolean);
           procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); virtual;
@@ -3702,6 +3707,11 @@ implementation
       end;
 
 
+    procedure tcg.g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string);
+      begin
+        a_jmp_name(list,externalname);
+      end;
+
     procedure tcg.a_call_name_static(list : TAsmList;const s : string);
       begin
         a_call_name(list,s);

+ 1 - 26
compiler/ncgutil.pas

@@ -2168,11 +2168,6 @@ implementation
 ****************************************************************************}
 
     procedure gen_external_stub(list:TAsmList;pd:tprocdef;const externalname:string);
-{$ifdef x86}
-      var
-        ref : treference;
-        sym : tasmsymbol;
-{$endif x86}
       begin
         { add the procedure to the al_procedures }
         maybe_new_object_file(list);
@@ -2183,27 +2178,7 @@ implementation
         else
           list.concat(Tai_symbol.createname(pd.mangledname,AT_FUNCTION,0));
 
-{$ifdef x86}
-        { fix this for other CPUs as well }
-        sym:=current_asmdata.RefAsmSymbol(externalname);
-        reference_reset_symbol(ref,sym,0);
-
-
-        { create pic'ed? }
-        if cs_create_pic in current_settings.moduleswitches then
-          begin
-            { it could be that we're called from a procedure not having the
-              got loaded
-            }
-            gen_got_load(list);
-            ref.refaddr:=addr_pic;
-          end
-        else
-          ref.refaddr:=addr_full;
-        list.concat(taicpu.op_ref(A_JMP,S_NO,ref));
-{$else x86}
-        cg.a_jmp_name(list,externalname);
-{$endif x86}
+        cg.g_external_wrapper(list,pd,externalname);
       end;
 
 {****************************************************************************

+ 48 - 0
compiler/powerpc64/cgcpu.pas

@@ -99,6 +99,8 @@ type
     procedure g_concatcopy(list: TAsmList; const source, dest: treference;
       len: aint); override;
 
+    procedure g_external_wrapper(list: TAsmList; pd: TProcDef; const externalname: string); override;
+
   private
 
     procedure a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt); override;
@@ -1868,6 +1870,52 @@ begin
 
 end;
 
+procedure tcgppc.g_external_wrapper(list: TAsmList; pd: TProcDef; const externalname: string);
+var
+  href : treference;
+begin
+  if (target_info.system <> system_powerpc64_linux) then begin
+    inherited;
+    exit;
+  end;
+
+  { for ppc64/linux emit correct code which sets up a stack frame and then calls the
+  external method normally to ensure that the GOT/TOC will be loaded correctly if 
+  required.
+
+  It's not really advantageous to use cg methods here because they are too specialized.
+
+  I.e. the resulting code sequence looks as follows:
+
+  mflr r0
+  std r0, 16(r1)
+  stdu r1, -112(r1)
+  bl <external_method>
+  nop
+  addi r1, r1, 112
+  ld r0, 16(r1)
+  mtlr r0
+  blr
+
+  TODO: put "112" magic constant (minimum stack frame size on ppc64)  into constant
+  }
+  list.concat(taicpu.op_reg(A_MFLR, NR_R0));
+  reference_reset_base(href, NR_STACK_POINTER_REG, 16);
+  list.concat(taicpu.op_reg_ref(A_STD, NR_R0, href));
+  reference_reset_base(href, NR_STACK_POINTER_REG, -112);
+  list.concat(taicpu.op_reg_ref(A_STDU, NR_STACK_POINTER_REG, href));
+
+  list.concat(taicpu.op_sym(A_BL, current_asmdata.RefAsmSymbol(externalname)));
+  list.concat(taicpu.op_none(A_NOP));
+
+  list.concat(taicpu.op_reg_reg_const(A_ADDI, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, 112));
+
+  reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_ELF);
+  list.concat(taicpu.op_reg_ref(A_LD, NR_R0, href));
+  list.concat(taicpu.op_reg(A_MTLR, NR_R0));
+  list.concat(taicpu.op_none(A_BLR));
+end;
+
 {***************** This is private property, keep out! :) *****************}
 
 procedure tcgppc.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);

+ 26 - 3
compiler/x86/cgx86.pas

@@ -32,7 +32,7 @@ unit cgx86;
        cgbase,cgutils,cgobj,
        aasmbase,aasmtai,aasmdata,aasmcpu,
        cpubase,cpuinfo,rgobj,rgx86,rgcpu,
-       symconst,symtype;
+       symconst,symtype,symdef;
 
     type
       tcgx86 = class(tcg)
@@ -108,6 +108,8 @@ unit cgx86;
 
         procedure g_overflowcheck(list: TAsmList; const l:tlocation;def:tdef);override;
 
+        procedure g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string); override;
+
         procedure make_simple_ref(list:TAsmList;var ref: treference);
       protected
         procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
@@ -150,8 +152,8 @@ unit cgx86;
 
     uses
        globals,verbose,systems,cutils,
-       symdef,defutil,paramgr,procinfo,
-       tgobj,
+       defutil,paramgr,procinfo,
+       tgobj,ncgutil,
        fmodule;
 
     const
@@ -1951,5 +1953,26 @@ unit cgx86;
          a_label(list,hl);
       end;
 
+    procedure tcgx86.g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string);
+      var
+        ref : treference;
+        sym : tasmsymbol;
+      begin
+        sym:=current_asmdata.RefAsmSymbol(externalname);
+        reference_reset_symbol(ref,sym,0);
+
+        { create pic'ed? }
+        if cs_create_pic in current_settings.moduleswitches then
+          begin
+            { it could be that we're called from a procedure not having the
+              got loaded
+            }
+            gen_got_load(list);
+            ref.refaddr:=addr_pic;
+          end
+        else
+          ref.refaddr:=addr_full;
+        list.concat(taicpu.op_ref(A_JMP,S_NO,ref));
+      end;
 
 end.