mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-15 15:19:25 +02:00
* 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:
parent
9049f845f4
commit
b0bb3f94a7
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
{****************************************************************************
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user