mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 23:49:22 +02:00
+ ppc64le/ELFv2 ret_in_param implementation
* fixed ret_in_param for other ppc64 ABIs git-svn-id: trunk@30221 -
This commit is contained in:
parent
f4a580d669
commit
3d6fcd8815
@ -39,6 +39,7 @@ type
|
|||||||
tcpuregisterset; override;
|
tcpuregisterset; override;
|
||||||
function push_addr_param(varspez: tvarspez; def: tdef; calloption:
|
function push_addr_param(varspez: tvarspez; def: tdef; calloption:
|
||||||
tproccalloption): boolean; override;
|
tproccalloption): boolean; override;
|
||||||
|
function ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
|
||||||
|
|
||||||
procedure getintparaloc(pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override;
|
procedure getintparaloc(pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override;
|
||||||
function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
|
function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
|
||||||
@ -54,7 +55,7 @@ type
|
|||||||
var curintreg, curfloatreg, curmmreg: tsuperregister; var
|
var curintreg, curfloatreg, curmmreg: tsuperregister; var
|
||||||
cur_stack_offset: aword; isVararg : boolean): longint;
|
cur_stack_offset: aword; isVararg : boolean): longint;
|
||||||
function parseparaloc(p: tparavarsym; const s: string): boolean; override;
|
function parseparaloc(p: tparavarsym; const s: string): boolean; override;
|
||||||
procedure create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: longint; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
|
procedure create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -200,6 +201,74 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function tppcparamanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
|
||||||
|
var
|
||||||
|
tmpdef: tdef;
|
||||||
|
begin
|
||||||
|
if handle_common_ret_in_param(def,pd,result) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
{ general rule: passed in registers -> returned in registers }
|
||||||
|
result:=push_addr_param(vs_value,def,pd.proccalloption);
|
||||||
|
|
||||||
|
case target_info.abi of
|
||||||
|
{ elfv2: non-homogeneous aggregate larger than 2 doublewords or a
|
||||||
|
homogeneous aggregate with more than eight registers are returned by
|
||||||
|
reference }
|
||||||
|
abi_powerpc_elfv2:
|
||||||
|
begin
|
||||||
|
if not result then
|
||||||
|
begin
|
||||||
|
if (def.typ=recorddef) then
|
||||||
|
begin
|
||||||
|
if tcpurecorddef(def).has_single_type_elfv2(tmpdef) then
|
||||||
|
begin
|
||||||
|
if def.size>8*tmpdef.size then
|
||||||
|
result:=true
|
||||||
|
end
|
||||||
|
else if def.size>2*sizeof(aint) then
|
||||||
|
result:=true;
|
||||||
|
end
|
||||||
|
else if (def.typ=arraydef) then
|
||||||
|
begin
|
||||||
|
if tcpuarraydef(def).has_single_type_elfv2(tmpdef) then
|
||||||
|
begin
|
||||||
|
if def.size>8*tmpdef.size then
|
||||||
|
result:=true
|
||||||
|
end
|
||||||
|
else if def.size>2*sizeof(aint) then
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{ sysv/aix: any non-scalar/non-floating point is returned by reference }
|
||||||
|
abi_powerpc_sysv,
|
||||||
|
abi_powerpc_aix:
|
||||||
|
begin
|
||||||
|
case def.typ of
|
||||||
|
procvardef:
|
||||||
|
result:=def.size>8;
|
||||||
|
recorddef:
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{ Darwin: if completely passed in registers -> returned by registers;
|
||||||
|
i.e., if part is passed via memory because there are not enough
|
||||||
|
registers, return via memory }
|
||||||
|
abi_powerpc_darwin:
|
||||||
|
begin
|
||||||
|
case def.typ of
|
||||||
|
recorddef:
|
||||||
|
{ todo: fix once the Darwin/ppc64 abi is fully implemented, as it
|
||||||
|
requires individual fields to be passed in individual registers,
|
||||||
|
so a record with 9 bytes may need to be passed via memory }
|
||||||
|
if def.size>8*sizeof(aint) then
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg:
|
procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg:
|
||||||
tsuperregister; var cur_stack_offset: aword);
|
tsuperregister; var cur_stack_offset: aword);
|
||||||
begin
|
begin
|
||||||
@ -213,32 +282,45 @@ end;
|
|||||||
function tppcparamanager.get_funcretloc(p : tabstractprocdef; side:
|
function tppcparamanager.get_funcretloc(p : tabstractprocdef; side:
|
||||||
tcallercallee; forcetempdef: tdef): tcgpara;
|
tcallercallee; forcetempdef: tdef): tcgpara;
|
||||||
var
|
var
|
||||||
paraloc : pcgparalocation;
|
paraloc: pcgparalocation;
|
||||||
retcgsize : tcgsize;
|
retcgsize: tcgsize;
|
||||||
|
nextfloatreg, nextintreg, nextmmreg: tsuperregister;
|
||||||
|
stack_offset: aword;
|
||||||
begin
|
begin
|
||||||
if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
|
if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
paraloc:=result.add_location;
|
{ on Darwin and with ELFv2, results are returned the same way as they are
|
||||||
{ Return in FPU register? }
|
passed }
|
||||||
if result.def.typ=floatdef then
|
if target_info.abi in [abi_powerpc_elfv2,abi_powerpc_darwin] then
|
||||||
begin
|
begin
|
||||||
paraloc^.loc:=LOC_FPUREGISTER;
|
init_values(nextintreg,nextfloatreg,nextmmreg,stack_offset);
|
||||||
paraloc^.register:=NR_FPU_RESULT_REG;
|
create_paraloc_for_def(result,vs_value,result.def,nextfloatreg,nextintreg,stack_offset,false,false,side,p);
|
||||||
paraloc^.size:=retcgsize;
|
|
||||||
paraloc^.def:=result.def;
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
{ Return in register }
|
|
||||||
begin
|
begin
|
||||||
paraloc^.loc:=LOC_REGISTER;
|
{ for AIX and ELFv1, the situation is simpler: always just one register }
|
||||||
if side=callerside then
|
paraloc:=result.add_location;
|
||||||
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
{ Return in FPU register? }
|
||||||
else
|
if result.def.typ=floatdef then
|
||||||
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
begin
|
||||||
paraloc^.size:=retcgsize;
|
paraloc^.loc:=LOC_FPUREGISTER;
|
||||||
paraloc^.def:=result.def;
|
paraloc^.register:=NR_FPU_RESULT_REG;
|
||||||
end;
|
paraloc^.size:=retcgsize;
|
||||||
|
paraloc^.def:=result.def;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{ Return in register }
|
||||||
|
begin
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
if side=callerside then
|
||||||
|
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||||
|
else
|
||||||
|
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||||
|
paraloc^.size:=retcgsize;
|
||||||
|
paraloc^.def:=result.def;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function tppcparamanager.create_paraloc_info(p: tabstractprocdef; side:
|
function tppcparamanager.create_paraloc_info(p: tabstractprocdef; side:
|
||||||
@ -260,7 +342,6 @@ function tppcparamanager.create_paraloc_info_intern(p: tabstractprocdef; side:
|
|||||||
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
|
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
|
||||||
aword; isVararg : boolean): longint;
|
aword; isVararg : boolean): longint;
|
||||||
var
|
var
|
||||||
stack_offset: longint;
|
|
||||||
nextintreg, nextfloatreg, nextmmreg : tsuperregister;
|
nextintreg, nextfloatreg, nextmmreg : tsuperregister;
|
||||||
i: integer;
|
i: integer;
|
||||||
hp: tparavarsym;
|
hp: tparavarsym;
|
||||||
@ -277,7 +358,6 @@ begin
|
|||||||
nextintreg := curintreg;
|
nextintreg := curintreg;
|
||||||
nextfloatreg := curfloatreg;
|
nextfloatreg := curfloatreg;
|
||||||
nextmmreg := curmmreg;
|
nextmmreg := curmmreg;
|
||||||
stack_offset := cur_stack_offset;
|
|
||||||
|
|
||||||
for i := 0 to paras.count - 1 do begin
|
for i := 0 to paras.count - 1 do begin
|
||||||
hp := tparavarsym(paras[i]);
|
hp := tparavarsym(paras[i]);
|
||||||
@ -300,17 +380,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
delphi_nestedfp:=(vo_is_parentfp in hp.varoptions) and (po_delphi_nested_cc in p.procoptions);
|
delphi_nestedfp:=(vo_is_parentfp in hp.varoptions) and (po_delphi_nested_cc in p.procoptions);
|
||||||
create_paraloc_for_def(hp.paraloc[side], hp.varspez, hp.vardef,
|
create_paraloc_for_def(hp.paraloc[side], hp.varspez, hp.vardef,
|
||||||
nextfloatreg, nextintreg, stack_offset, isVararg, delphi_nestedfp, side, p);
|
nextfloatreg, nextintreg, cur_stack_offset, isVararg, delphi_nestedfp, side, p);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
curintreg := nextintreg;
|
curintreg := nextintreg;
|
||||||
curfloatreg := nextfloatreg;
|
curfloatreg := nextfloatreg;
|
||||||
curmmreg := nextmmreg;
|
curmmreg := nextmmreg;
|
||||||
cur_stack_offset := stack_offset;
|
cur_stack_offset := cur_stack_offset;
|
||||||
result := stack_offset;
|
result := cur_stack_offset;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tppcparamanager.create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: longint; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
|
procedure tppcparamanager.create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
|
||||||
var
|
var
|
||||||
paracgsize: tcgsize;
|
paracgsize: tcgsize;
|
||||||
loc: tcgloc;
|
loc: tcgloc;
|
||||||
|
Loading…
Reference in New Issue
Block a user