mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-13 09:59:25 +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;
|
||||
function push_addr_param(varspez: tvarspez; def: tdef; calloption:
|
||||
tproccalloption): boolean; override;
|
||||
function ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
|
||||
|
||||
procedure getintparaloc(pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override;
|
||||
function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
|
||||
@ -54,7 +55,7 @@ type
|
||||
var curintreg, curfloatreg, curmmreg: tsuperregister; var
|
||||
cur_stack_offset: aword; isVararg : boolean): longint;
|
||||
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;
|
||||
|
||||
implementation
|
||||
@ -200,6 +201,74 @@ begin
|
||||
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:
|
||||
tsuperregister; var cur_stack_offset: aword);
|
||||
begin
|
||||
@ -213,32 +282,45 @@ end;
|
||||
function tppcparamanager.get_funcretloc(p : tabstractprocdef; side:
|
||||
tcallercallee; forcetempdef: tdef): tcgpara;
|
||||
var
|
||||
paraloc : pcgparalocation;
|
||||
retcgsize : tcgsize;
|
||||
paraloc: pcgparalocation;
|
||||
retcgsize: tcgsize;
|
||||
nextfloatreg, nextintreg, nextmmreg: tsuperregister;
|
||||
stack_offset: aword;
|
||||
begin
|
||||
if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
|
||||
exit;
|
||||
|
||||
paraloc:=result.add_location;
|
||||
{ Return in FPU register? }
|
||||
if result.def.typ=floatdef then
|
||||
{ on Darwin and with ELFv2, results are returned the same way as they are
|
||||
passed }
|
||||
if target_info.abi in [abi_powerpc_elfv2,abi_powerpc_darwin] then
|
||||
begin
|
||||
paraloc^.loc:=LOC_FPUREGISTER;
|
||||
paraloc^.register:=NR_FPU_RESULT_REG;
|
||||
paraloc^.size:=retcgsize;
|
||||
paraloc^.def:=result.def;
|
||||
init_values(nextintreg,nextfloatreg,nextmmreg,stack_offset);
|
||||
create_paraloc_for_def(result,vs_value,result.def,nextfloatreg,nextintreg,stack_offset,false,false,side,p);
|
||||
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;
|
||||
{ for AIX and ELFv1, the situation is simpler: always just one register }
|
||||
paraloc:=result.add_location;
|
||||
{ Return in FPU register? }
|
||||
if result.def.typ=floatdef then
|
||||
begin
|
||||
paraloc^.loc:=LOC_FPUREGISTER;
|
||||
paraloc^.register:=NR_FPU_RESULT_REG;
|
||||
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;
|
||||
|
||||
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:
|
||||
aword; isVararg : boolean): longint;
|
||||
var
|
||||
stack_offset: longint;
|
||||
nextintreg, nextfloatreg, nextmmreg : tsuperregister;
|
||||
i: integer;
|
||||
hp: tparavarsym;
|
||||
@ -277,7 +358,6 @@ begin
|
||||
nextintreg := curintreg;
|
||||
nextfloatreg := curfloatreg;
|
||||
nextmmreg := curmmreg;
|
||||
stack_offset := cur_stack_offset;
|
||||
|
||||
for i := 0 to paras.count - 1 do begin
|
||||
hp := tparavarsym(paras[i]);
|
||||
@ -300,17 +380,17 @@ begin
|
||||
end;
|
||||
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,
|
||||
nextfloatreg, nextintreg, stack_offset, isVararg, delphi_nestedfp, side, p);
|
||||
nextfloatreg, nextintreg, cur_stack_offset, isVararg, delphi_nestedfp, side, p);
|
||||
end;
|
||||
|
||||
curintreg := nextintreg;
|
||||
curfloatreg := nextfloatreg;
|
||||
curmmreg := nextmmreg;
|
||||
cur_stack_offset := stack_offset;
|
||||
result := stack_offset;
|
||||
cur_stack_offset := cur_stack_offset;
|
||||
result := cur_stack_offset;
|
||||
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
|
||||
paracgsize: tcgsize;
|
||||
loc: tcgloc;
|
||||
|
Loading…
Reference in New Issue
Block a user