* 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 -
This commit is contained in:
tom_at_work 2007-09-19 20:41:39 +00:00
parent 9049f845f4
commit b0bb3f94a7
4 changed files with 85 additions and 29 deletions

View File

@ -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);

View File

@ -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;
{****************************************************************************

View File

@ -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);

View File

@ -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.