mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 01:27:59 +02:00
* fixed handling the result value of functions where the result type is
forced to something else by the compiler (internal rtl functions etc), necessary for the objc branch * fixed adding all used function result registers to the list of registers that may need to be saved before a function call git-svn-id: trunk@13695 -
This commit is contained in:
parent
66240c1204
commit
cc5aeb09de
@ -29,7 +29,7 @@ unit cpupara;
|
||||
uses
|
||||
globtype,globals,
|
||||
aasmtai,aasmdata,
|
||||
cpuinfo,cpubase,cgbase,
|
||||
cpuinfo,cpubase,cgbase,cgutils,
|
||||
symconst,symbase,symtype,symdef,parabase,paramgr;
|
||||
|
||||
type
|
||||
@ -41,10 +41,12 @@ unit cpupara;
|
||||
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
|
||||
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
||||
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
|
||||
private
|
||||
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
|
||||
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
|
||||
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
|
||||
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -52,8 +54,7 @@ unit cpupara;
|
||||
uses
|
||||
verbose,systems,
|
||||
rgobj,
|
||||
defutil,symsym,
|
||||
cgutils;
|
||||
defutil,symsym;
|
||||
|
||||
|
||||
function tarmparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
|
||||
@ -428,40 +429,40 @@ unit cpupara;
|
||||
end;
|
||||
|
||||
|
||||
function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
|
||||
procedure tarmparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
begin
|
||||
p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
|
||||
end;
|
||||
|
||||
|
||||
function tarmparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
|
||||
var
|
||||
cur_stack_offset: aword;
|
||||
curintreg, curfloatreg, curmmreg: tsuperregister;
|
||||
retcgsize : tcgsize;
|
||||
begin
|
||||
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
|
||||
|
||||
result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
|
||||
|
||||
{ Constructors return self instead of a boolean }
|
||||
if (p.proctypeoption=potype_constructor) then
|
||||
retcgsize:=OS_ADDR
|
||||
else
|
||||
retcgsize:=def_cgsize(p.returndef);
|
||||
retcgsize:=def_cgsize(def);
|
||||
|
||||
location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
location_reset(result,LOC_INVALID,OS_NO);
|
||||
result.size:=retcgsize;
|
||||
|
||||
{ void has no location }
|
||||
if is_void(p.returndef) then
|
||||
if is_void(def) then
|
||||
begin
|
||||
location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
|
||||
location_reset(result,LOC_VOID,OS_NO);
|
||||
exit;
|
||||
end;
|
||||
{ Return is passed as var parameter }
|
||||
if ret_in_param(p.returndef,p.proccalloption) then
|
||||
if ret_in_param(def,p.proccalloption) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REFERENCE;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REFERENCE;
|
||||
result.size:=retcgsize;
|
||||
exit;
|
||||
end;
|
||||
{ Return in FPU register? }
|
||||
if p.returndef.typ=floatdef then
|
||||
if def.typ=floatdef then
|
||||
begin
|
||||
if (p.proccalloption in [pocall_softfloat]) or (cs_fp_emulation in current_settings.moduleswitches) then
|
||||
begin
|
||||
@ -470,17 +471,17 @@ unit cpupara;
|
||||
OS_F64:
|
||||
begin
|
||||
{ low }
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
|
||||
p.funcretloc[side].size:=OS_64;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||
result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
|
||||
result.size:=OS_64;
|
||||
end;
|
||||
OS_32,
|
||||
OS_F32:
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
|
||||
p.funcretloc[side].size:=OS_32;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.register:=NR_FUNCTION_RETURN_REG;
|
||||
result.size:=OS_32;
|
||||
end;
|
||||
else
|
||||
internalerror(2005082603);
|
||||
@ -488,8 +489,8 @@ unit cpupara;
|
||||
end
|
||||
else
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_FPUREGISTER;
|
||||
p.funcretloc[side].register:=NR_FPU_RESULT_REG;
|
||||
result.loc:=LOC_FPUREGISTER;
|
||||
result.register:=NR_FPU_RESULT_REG;
|
||||
end;
|
||||
end
|
||||
{ Return in register }
|
||||
@ -498,17 +499,29 @@ unit cpupara;
|
||||
if retcgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
{ low }
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||
result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
|
||||
end
|
||||
else
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.register:=NR_FUNCTION_RETURN_REG;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
|
||||
var
|
||||
cur_stack_offset: aword;
|
||||
curintreg, curfloatreg, curmmreg: tsuperregister;
|
||||
begin
|
||||
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
|
||||
|
||||
result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
|
||||
|
||||
create_funcretloc_info(p,side);
|
||||
end;
|
||||
|
||||
|
||||
|
@ -29,7 +29,7 @@ unit cpupara;
|
||||
uses
|
||||
globtype,globals,
|
||||
aasmtai,aasmdata,
|
||||
cpuinfo,cpubase,cgbase,
|
||||
cpuinfo,cpubase,cgbase,cgutils,
|
||||
symconst,symbase,symtype,symdef,parabase,paramgr;
|
||||
|
||||
type
|
||||
@ -52,8 +52,7 @@ unit cpupara;
|
||||
uses
|
||||
verbose,systems,
|
||||
rgobj,
|
||||
defutil,symsym,
|
||||
cgutils;
|
||||
defutil,symsym;
|
||||
|
||||
|
||||
function tavrparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
|
||||
@ -396,30 +395,44 @@ unit cpupara;
|
||||
|
||||
result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
|
||||
|
||||
create_funcretloc_info(p,side);
|
||||
end;
|
||||
|
||||
|
||||
procedure tavrparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
begin
|
||||
p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
|
||||
end;
|
||||
|
||||
|
||||
function tavrparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
|
||||
var
|
||||
retcgsize : tcgsize;
|
||||
begin
|
||||
{ Constructors return self instead of a boolean }
|
||||
if (p.proctypeoption=potype_constructor) then
|
||||
retcgsize:=OS_ADDR
|
||||
else
|
||||
retcgsize:=def_cgsize(p.returndef);
|
||||
retcgsize:=def_cgsize(def);
|
||||
|
||||
location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
location_reset(result,LOC_INVALID,OS_NO);
|
||||
result.size:=retcgsize;
|
||||
|
||||
{ void has no location }
|
||||
if is_void(p.returndef) then
|
||||
if is_void(def) then
|
||||
begin
|
||||
location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
|
||||
location_reset(result,LOC_VOID,OS_NO);
|
||||
exit;
|
||||
end;
|
||||
{ Return is passed as var parameter }
|
||||
if ret_in_param(p.returndef,p.proccalloption) then
|
||||
if ret_in_param(def,p.proccalloption) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REFERENCE;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REFERENCE;
|
||||
result.size:=retcgsize;
|
||||
exit;
|
||||
end;
|
||||
{ Return in FPU register? }
|
||||
if p.returndef.typ=floatdef then
|
||||
if def.typ=floatdef then
|
||||
begin
|
||||
if (p.proccalloption in [pocall_softfloat]) or (cs_fp_emulation in current_settings.moduleswitches) then
|
||||
begin
|
||||
@ -428,17 +441,17 @@ unit cpupara;
|
||||
OS_F64:
|
||||
begin
|
||||
{ low }
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
|
||||
p.funcretloc[side].size:=OS_64;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||
result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
|
||||
result.size:=OS_64;
|
||||
end;
|
||||
OS_32,
|
||||
OS_F32:
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
|
||||
p.funcretloc[side].size:=OS_32;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.register:=NR_FUNCTION_RETURN_REG;
|
||||
result.size:=OS_32;
|
||||
end;
|
||||
else
|
||||
internalerror(2005082603);
|
||||
@ -446,8 +459,8 @@ unit cpupara;
|
||||
end
|
||||
else
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_FPUREGISTER;
|
||||
p.funcretloc[side].register:=NR_FPU_RESULT_REG;
|
||||
result.loc:=LOC_FPUREGISTER;
|
||||
result.register:=NR_FPU_RESULT_REG;
|
||||
end;
|
||||
end
|
||||
{ Return in register }
|
||||
@ -456,18 +469,18 @@ unit cpupara;
|
||||
if retcgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
{ low }
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||
result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
|
||||
end
|
||||
else
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.register:=NR_FUNCTION_RETURN_REG;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function tavrparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
|
||||
|
@ -27,7 +27,7 @@ unit cpupara;
|
||||
|
||||
uses
|
||||
globtype,
|
||||
aasmtai,aasmdata,cpubase,cgbase,
|
||||
aasmtai,aasmdata,cpubase,cgbase,cgutils,
|
||||
symconst,symtype,symsym,symdef,
|
||||
parabase,paramgr;
|
||||
|
||||
@ -49,6 +49,7 @@ unit cpupara;
|
||||
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
||||
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
|
||||
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);override;
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
|
||||
private
|
||||
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
procedure create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
|
||||
@ -61,8 +62,7 @@ unit cpupara;
|
||||
uses
|
||||
cutils,
|
||||
systems,verbose,
|
||||
defutil,
|
||||
cgutils;
|
||||
defutil;
|
||||
|
||||
const
|
||||
parasupregs : array[0..2] of tsuperregister = (RS_EAX,RS_EDX,RS_ECX);
|
||||
@ -307,6 +307,12 @@ unit cpupara;
|
||||
|
||||
|
||||
procedure ti386paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
begin
|
||||
p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
|
||||
end;
|
||||
|
||||
|
||||
function ti386paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
|
||||
var
|
||||
retcgsize : tcgsize;
|
||||
begin
|
||||
@ -314,28 +320,28 @@ unit cpupara;
|
||||
if (p.proctypeoption=potype_constructor) then
|
||||
retcgsize:=OS_ADDR
|
||||
else
|
||||
retcgsize:=def_cgsize(p.returndef);
|
||||
retcgsize:=def_cgsize(def);
|
||||
|
||||
location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
|
||||
location_reset(result,LOC_INVALID,OS_NO);
|
||||
{ void has no location }
|
||||
if is_void(p.returndef) then
|
||||
if is_void(def) then
|
||||
begin
|
||||
location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
|
||||
location_reset(result,LOC_VOID,OS_NO);
|
||||
exit;
|
||||
end;
|
||||
{ Return is passed as var parameter }
|
||||
if ret_in_param(p.returndef,p.proccalloption) then
|
||||
if ret_in_param(def,p.proccalloption) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REFERENCE;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REFERENCE;
|
||||
result.size:=retcgsize;
|
||||
exit;
|
||||
end;
|
||||
{ Return in FPU register? }
|
||||
if p.returndef.typ=floatdef then
|
||||
if def.typ=floatdef then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_FPUREGISTER;
|
||||
p.funcretloc[side].register:=NR_FPU_RESULT_REG;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_FPUREGISTER;
|
||||
result.register:=NR_FPU_RESULT_REG;
|
||||
result.size:=retcgsize;
|
||||
end
|
||||
else
|
||||
{ Return in register }
|
||||
@ -343,26 +349,26 @@ unit cpupara;
|
||||
if retcgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
{ low 32bits }
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].size:=OS_64;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.size:=OS_64;
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
else
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
{ high 32bits }
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
else
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
end
|
||||
else
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.size:=retcgsize;
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
else
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -45,6 +45,8 @@ interface
|
||||
|
||||
tcgcallnode = class(tcallnode)
|
||||
private
|
||||
retloc: tlocation;
|
||||
|
||||
procedure handle_return_value;
|
||||
procedure release_unused_return_value;
|
||||
procedure release_para_temps;
|
||||
@ -510,7 +512,6 @@ implementation
|
||||
var
|
||||
tmpcgsize,
|
||||
cgsize : tcgsize;
|
||||
retloc : tlocation;
|
||||
{$ifdef cpu64bitaddr}
|
||||
ref : treference;
|
||||
{$endif cpu64bitaddr}
|
||||
@ -529,12 +530,12 @@ implementation
|
||||
end;
|
||||
|
||||
{ Load normal (ordinal,float,pointer) result value from accumulator }
|
||||
cgsize:=procdefinition.funcretloc[callerside].size;
|
||||
case procdefinition.funcretloc[callerside].loc of
|
||||
cgsize:=retloc.size;
|
||||
case retloc.loc of
|
||||
LOC_FPUREGISTER:
|
||||
begin
|
||||
location_reset(location,LOC_FPUREGISTER,cgsize);
|
||||
location.register:=procdefinition.funcretloc[callerside].register;
|
||||
location.register:=retloc.register;
|
||||
{$ifdef x86}
|
||||
tcgx86(cg).inc_fpu_stack;
|
||||
{$else x86}
|
||||
@ -548,8 +549,8 @@ implementation
|
||||
(mantis #13536). }
|
||||
if (cnf_return_value_used in callnodeflags) then
|
||||
begin
|
||||
if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
||||
if getsupreg(retloc.register)<first_fpu_imreg then
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register);
|
||||
hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
|
||||
cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.size,location.register,hregister);
|
||||
location.register:=hregister;
|
||||
@ -567,7 +568,6 @@ implementation
|
||||
structs with up to 16 bytes are returned in registers }
|
||||
if cgsize in [OS_128,OS_S128] then
|
||||
begin
|
||||
retloc:=procdefinition.funcretloc[callerside];
|
||||
if retloc.loc<>LOC_REGISTER then
|
||||
internalerror(2009042001);
|
||||
{ See #13536 comment above. }
|
||||
@ -591,7 +591,6 @@ implementation
|
||||
{$else cpu64bitaddr}
|
||||
if cgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
retloc:=procdefinition.funcretloc[callerside];
|
||||
if retloc.loc<>LOC_REGISTER then
|
||||
internalerror(200409141);
|
||||
{ See #13536 comment above. }
|
||||
@ -621,8 +620,8 @@ implementation
|
||||
{ See #13536 comment above. }
|
||||
if (cnf_return_value_used in callnodeflags) then
|
||||
begin
|
||||
if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
||||
if getsupreg(retloc.register)<first_int_imreg then
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register);
|
||||
|
||||
{ but use def_size only if it returns something valid because in
|
||||
case of odd sized structured results in registers def_cgsize(resultdef)
|
||||
@ -633,10 +632,10 @@ implementation
|
||||
tmpcgsize:=cgsize;
|
||||
|
||||
location.register:=cg.getintregister(current_asmdata.CurrAsmList,tmpcgsize);
|
||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,tmpcgsize,procdefinition.funcretloc[callerside].register,location.register);
|
||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,tmpcgsize,retloc.register,location.register);
|
||||
end
|
||||
else
|
||||
location:=procdefinition.funcretloc[callerside];
|
||||
location:=retloc;
|
||||
end;
|
||||
{$ifdef arm}
|
||||
if (resultdef.typ=floatdef) and (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
|
||||
@ -658,13 +657,13 @@ implementation
|
||||
if (cnf_return_value_used in callnodeflags) then
|
||||
begin
|
||||
location_reset(location,LOC_MMREGISTER,cgsize);
|
||||
if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
||||
if getsupreg(retloc.register)<first_mm_imreg then
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register);
|
||||
location.register:=cg.getmmregister(current_asmdata.CurrAsmList,cgsize);
|
||||
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
|
||||
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,retloc.register,location.register,mms_movescalar);
|
||||
end
|
||||
else
|
||||
location:=procdefinition.funcretloc[callerside];
|
||||
location:=retloc;
|
||||
end;
|
||||
|
||||
else
|
||||
@ -735,8 +734,8 @@ implementation
|
||||
end;
|
||||
{$endif x86}
|
||||
end;
|
||||
if procdefinition.funcretloc[callerside].size<>OS_NO then
|
||||
location_free(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside]);
|
||||
if retloc.size<>OS_NO then
|
||||
location_free(current_asmdata.CurrAsmList,retloc);
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
end;
|
||||
end;
|
||||
@ -944,16 +943,49 @@ implementation
|
||||
{ Include Function result registers }
|
||||
if (not is_void(resultdef)) then
|
||||
begin
|
||||
case procdefinition.funcretloc[callerside].loc of
|
||||
{ The forced returntype may have a different size than the one
|
||||
declared for the procdef }
|
||||
if not assigned(typedef) then
|
||||
retloc:=procdefinition.funcretloc[callerside]
|
||||
else
|
||||
retloc:=paramanager.get_funcretloc(procdefinition,callerside,typedef);
|
||||
case retloc.loc of
|
||||
LOC_REGISTER,
|
||||
LOC_CREGISTER:
|
||||
include(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
|
||||
begin
|
||||
{$ifdef cpu64bitaddr}
|
||||
{ x86-64 system v abi:
|
||||
structs with up to 16 bytes are returned in registers }
|
||||
if retloc.size in [OS_128,OS_S128] then
|
||||
begin
|
||||
include(regs_to_save_int,getsupreg(retloc.register));
|
||||
include(regs_to_save_int,getsupreg(retloc.registerhi));
|
||||
end
|
||||
else
|
||||
{$else cpu64bitaddr}
|
||||
if retloc.size in [OS_64,OS_S64] then
|
||||
begin
|
||||
include(regs_to_save_int,getsupreg(retloc.register64.reglo));
|
||||
include(regs_to_save_int,getsupreg(retloc.register64.reghi));
|
||||
end
|
||||
else
|
||||
{$endif not cpu64bitaddr}
|
||||
include(regs_to_save_int,getsupreg(retloc.register));
|
||||
end;
|
||||
LOC_FPUREGISTER,
|
||||
LOC_CFPUREGISTER:
|
||||
include(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
|
||||
begin
|
||||
include(regs_to_save_fpu,getsupreg(retloc.register));
|
||||
{$ifdef SPARC}
|
||||
{ SPARC uses two successive single precision fpu registers
|
||||
for double-precision values }
|
||||
if retloc.size=OS_F64 then
|
||||
include(regs_to_save_fpu,succ(getsupreg(retloc.register)));
|
||||
{$endif SPARC}
|
||||
end;
|
||||
LOC_MMREGISTER,
|
||||
LOC_CMMREGISTER:
|
||||
include(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
|
||||
include(regs_to_save_mm,getsupreg(retloc.register));
|
||||
LOC_REFERENCE,
|
||||
LOC_VOID:
|
||||
;
|
||||
@ -1145,26 +1177,32 @@ implementation
|
||||
function result }
|
||||
if (not is_void(resultdef)) then
|
||||
begin
|
||||
case procdefinition.funcretloc[callerside].loc of
|
||||
case retloc.loc of
|
||||
LOC_REGISTER,
|
||||
LOC_CREGISTER:
|
||||
begin
|
||||
{$ifndef cpu64bitalu}
|
||||
if procdefinition.funcretloc[callerside].size in [OS_64,OS_S64] then
|
||||
if retloc.size in [OS_64,OS_S64] then
|
||||
begin
|
||||
exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register64.reghi));
|
||||
exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register64.reglo));
|
||||
exclude(regs_to_save_int,getsupreg(retloc.register64.reghi));
|
||||
exclude(regs_to_save_int,getsupreg(retloc.register64.reglo));
|
||||
end
|
||||
{$else not cpu64bitalu}
|
||||
if retloc.size in [OS_128,OS_S128] then
|
||||
begin
|
||||
exclude(regs_to_save_int,getsupreg(retloc.register));
|
||||
exclude(regs_to_save_int,getsupreg(retloc.registerhi));
|
||||
end
|
||||
else
|
||||
{$endif not cpu64bitalu}
|
||||
exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
|
||||
else
|
||||
exclude(regs_to_save_int,getsupreg(retloc.register));
|
||||
end;
|
||||
LOC_FPUREGISTER,
|
||||
LOC_CFPUREGISTER:
|
||||
exclude(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
|
||||
exclude(regs_to_save_fpu,getsupreg(retloc.register));
|
||||
LOC_MMREGISTER,
|
||||
LOC_CMMREGISTER:
|
||||
exclude(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
|
||||
exclude(regs_to_save_mm,getsupreg(retloc.register));
|
||||
LOC_REFERENCE,
|
||||
LOC_VOID:
|
||||
;
|
||||
|
@ -29,7 +29,7 @@ unit paramgr;
|
||||
|
||||
uses
|
||||
cclasses,globtype,
|
||||
cpubase,cgbase,
|
||||
cpubase,cgbase,cgutils,
|
||||
parabase,
|
||||
aasmtai,aasmdata,
|
||||
symconst,symtype,symsym,symdef;
|
||||
@ -96,6 +96,12 @@ unit paramgr;
|
||||
}
|
||||
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;virtual;abstract;
|
||||
|
||||
{ Returns the location of the function result if p had def as
|
||||
function result instead of its actual result. Used if the compiler
|
||||
forces the function result to something different than the real
|
||||
result. }
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;virtual;abstract;
|
||||
|
||||
{ This is used to populate the location information on all parameters
|
||||
for the routine when it is being inlined. It returns
|
||||
the size allocated on the stack
|
||||
@ -124,7 +130,7 @@ implementation
|
||||
|
||||
uses
|
||||
systems,
|
||||
cgobj,tgobj,cgutils,
|
||||
cgobj,tgobj,
|
||||
defutil,verbose;
|
||||
|
||||
{ true if the location in paraloc can be reused as localloc }
|
||||
|
@ -29,7 +29,7 @@ unit cpupara;
|
||||
aasmtai,aasmdata,
|
||||
cpubase,
|
||||
symconst,symtype,symdef,symsym,
|
||||
paramgr,parabase,cgbase;
|
||||
paramgr,parabase,cgbase,cgutils;
|
||||
|
||||
type
|
||||
tppcparamanager = class(tparamanager)
|
||||
@ -40,6 +40,7 @@ unit cpupara;
|
||||
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
|
||||
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
||||
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
|
||||
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
private
|
||||
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
|
||||
@ -53,7 +54,6 @@ unit cpupara;
|
||||
uses
|
||||
verbose,systems,
|
||||
defutil,
|
||||
cgutils,
|
||||
procinfo,cpupi;
|
||||
|
||||
|
||||
@ -245,6 +245,12 @@ unit cpupara;
|
||||
|
||||
|
||||
procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
begin
|
||||
p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
|
||||
end;
|
||||
|
||||
|
||||
function tppcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
|
||||
var
|
||||
retcgsize : tcgsize;
|
||||
begin
|
||||
@ -252,29 +258,29 @@ unit cpupara;
|
||||
if (p.proctypeoption=potype_constructor) then
|
||||
retcgsize:=OS_ADDR
|
||||
else
|
||||
retcgsize:=def_cgsize(p.returndef);
|
||||
retcgsize:=def_cgsize(def);
|
||||
|
||||
location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
location_reset(result,LOC_INVALID,OS_NO);
|
||||
result.size:=retcgsize;
|
||||
{ void has no location }
|
||||
if is_void(p.returndef) then
|
||||
if is_void(def) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_VOID;
|
||||
result.loc:=LOC_VOID;
|
||||
exit;
|
||||
end;
|
||||
{ Return is passed as var parameter }
|
||||
if ret_in_param(p.returndef,p.proccalloption) then
|
||||
if ret_in_param(def,p.proccalloption) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REFERENCE;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REFERENCE;
|
||||
result.size:=retcgsize;
|
||||
exit;
|
||||
end;
|
||||
{ Return in FPU register? }
|
||||
if p.returndef.typ=floatdef then
|
||||
if def.typ=floatdef then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_FPUREGISTER;
|
||||
p.funcretloc[side].register:=NR_FPU_RESULT_REG;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_FPUREGISTER;
|
||||
result.register:=NR_FPU_RESULT_REG;
|
||||
result.size:=retcgsize;
|
||||
end
|
||||
else
|
||||
{ Return in register }
|
||||
@ -283,26 +289,26 @@ unit cpupara;
|
||||
if retcgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
{ low 32bits }
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
result.loc:=LOC_REGISTER;
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
else
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
{ high 32bits }
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
else
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
end
|
||||
else
|
||||
{$endif cpu64bitaddr}
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.size:=retcgsize;
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
else
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -29,7 +29,7 @@ uses
|
||||
aasmtai,aasmdata,
|
||||
cpubase,
|
||||
symconst, symtype, symdef, symsym,
|
||||
paramgr, parabase, cgbase;
|
||||
paramgr, parabase, cgbase, cgutils;
|
||||
|
||||
type
|
||||
tppcparamanager = class(tparamanager)
|
||||
@ -45,6 +45,7 @@ type
|
||||
function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
|
||||
function create_varargs_paraloc_info(p: tabstractprocdef; varargspara:
|
||||
tvarargsparalist): longint; override;
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
|
||||
procedure create_funcretloc_info(p: tabstractprocdef; side: tcallercallee);
|
||||
|
||||
private
|
||||
@ -62,7 +63,6 @@ implementation
|
||||
uses
|
||||
verbose, systems,
|
||||
defutil,
|
||||
cgutils,
|
||||
procinfo, cpupi;
|
||||
|
||||
function tppcparamanager.get_volatile_registers_int(calloption:
|
||||
@ -204,6 +204,12 @@ end;
|
||||
|
||||
procedure tppcparamanager.create_funcretloc_info(p: tabstractprocdef; side:
|
||||
tcallercallee);
|
||||
begin
|
||||
p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
|
||||
end;
|
||||
|
||||
function tppcparamanager.get_funcretloc(p : tabstractprocdef; side:
|
||||
tcallercallee; def: tdef): tlocation;
|
||||
var
|
||||
retcgsize: tcgsize;
|
||||
begin
|
||||
@ -211,37 +217,37 @@ begin
|
||||
if (p.proctypeoption = potype_constructor) then
|
||||
retcgsize := OS_ADDR
|
||||
else
|
||||
retcgsize := def_cgsize(p.returndef);
|
||||
retcgsize := def_cgsize(def);
|
||||
|
||||
location_reset(p.funcretloc[side], LOC_INVALID, OS_NO);
|
||||
p.funcretloc[side].size := retcgsize;
|
||||
location_reset(result, LOC_INVALID, OS_NO);
|
||||
result.size := retcgsize;
|
||||
{ void has no location }
|
||||
if is_void(p.returndef) then begin
|
||||
p.funcretloc[side].loc := LOC_VOID;
|
||||
if is_void(def) then begin
|
||||
result.loc := LOC_VOID;
|
||||
exit;
|
||||
end;
|
||||
{ Return is passed as var parameter }
|
||||
if ret_in_param(p.returndef, p.proccalloption) then
|
||||
if ret_in_param(def, p.proccalloption) then
|
||||
begin
|
||||
p.funcretloc[side].loc := LOC_REFERENCE;
|
||||
p.funcretloc[side].size := retcgsize;
|
||||
result.loc := LOC_REFERENCE;
|
||||
result.size := retcgsize;
|
||||
exit;
|
||||
end;
|
||||
{ Return in FPU register? }
|
||||
if p.returndef.typ = floatdef then begin
|
||||
p.funcretloc[side].loc := LOC_FPUREGISTER;
|
||||
p.funcretloc[side].register := NR_FPU_RESULT_REG;
|
||||
p.funcretloc[side].size := retcgsize;
|
||||
if def.typ = floatdef then begin
|
||||
result.loc := LOC_FPUREGISTER;
|
||||
result.register := NR_FPU_RESULT_REG;
|
||||
result.size := retcgsize;
|
||||
end else
|
||||
{ Return in register }
|
||||
begin
|
||||
p.funcretloc[side].loc := LOC_REGISTER;
|
||||
p.funcretloc[side].size := retcgsize;
|
||||
result.loc := LOC_REGISTER;
|
||||
result.size := retcgsize;
|
||||
if side = callerside then
|
||||
p.funcretloc[side].register := newreg(R_INTREGISTER,
|
||||
result.register := newreg(R_INTREGISTER,
|
||||
RS_FUNCTION_RESULT_REG, cgsize2subreg(R_INTREGISTER, retcgsize))
|
||||
else
|
||||
p.funcretloc[side].register := newreg(R_INTREGISTER,
|
||||
result.register := newreg(R_INTREGISTER,
|
||||
RS_FUNCTION_RETURN_REG, cgsize2subreg(R_INTREGISTER, retcgsize));
|
||||
end;
|
||||
end;
|
||||
|
@ -28,7 +28,7 @@ interface
|
||||
cclasses,
|
||||
aasmtai,aasmdata,
|
||||
cpubase,cpuinfo,
|
||||
symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase;
|
||||
symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase,cgutils;
|
||||
|
||||
type
|
||||
TSparcParaManager=class(TParaManager)
|
||||
@ -41,6 +41,7 @@ interface
|
||||
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
|
||||
function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
|
||||
function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
|
||||
private
|
||||
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
|
||||
@ -52,7 +53,7 @@ implementation
|
||||
uses
|
||||
cutils,verbose,systems,
|
||||
defutil,
|
||||
cgutils,cgobj;
|
||||
cgobj;
|
||||
|
||||
type
|
||||
tparasupregs = array[0..5] of tsuperregister;
|
||||
@ -139,6 +140,12 @@ implementation
|
||||
|
||||
|
||||
procedure tsparcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
begin
|
||||
p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
|
||||
end;
|
||||
|
||||
|
||||
function tsparcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
|
||||
var
|
||||
retcgsize : tcgsize;
|
||||
begin
|
||||
@ -146,31 +153,31 @@ implementation
|
||||
if (p.proctypeoption=potype_constructor) then
|
||||
retcgsize:=OS_ADDR
|
||||
else
|
||||
retcgsize:=def_cgsize(p.returndef);
|
||||
retcgsize:=def_cgsize(def);
|
||||
|
||||
location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
location_reset(result,LOC_INVALID,OS_NO);
|
||||
result.size:=retcgsize;
|
||||
{ void has no location }
|
||||
if is_void(p.returndef) then
|
||||
if is_void(def) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_VOID;
|
||||
result.loc:=LOC_VOID;
|
||||
exit;
|
||||
end;
|
||||
{ Return is passed as var parameter }
|
||||
if ret_in_param(p.returndef,p.proccalloption) then
|
||||
if ret_in_param(def,p.proccalloption) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REFERENCE;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REFERENCE;
|
||||
result.size:=retcgsize;
|
||||
exit;
|
||||
end;
|
||||
{ Return in FPU register? }
|
||||
if p.returndef.typ=floatdef then
|
||||
if def.typ=floatdef then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_FPUREGISTER;
|
||||
p.funcretloc[side].register:=NR_FPU_RESULT_REG;
|
||||
result.loc:=LOC_FPUREGISTER;
|
||||
result.register:=NR_FPU_RESULT_REG;
|
||||
if retcgsize=OS_F64 then
|
||||
setsubreg(p.funcretloc[side].register,R_SUBFD);
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
setsubreg(result.register,R_SUBFD);
|
||||
result.size:=retcgsize;
|
||||
end
|
||||
else
|
||||
{ Return in register }
|
||||
@ -178,27 +185,27 @@ implementation
|
||||
{$ifndef cpu64bitaddr}
|
||||
if retcgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
result.loc:=LOC_REGISTER;
|
||||
{ high }
|
||||
if (side=callerside) or (po_inline in p.procoptions) then
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
|
||||
else
|
||||
p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
{ low }
|
||||
if (side=callerside) or (po_inline in p.procoptions) then
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
|
||||
else
|
||||
p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
end
|
||||
else
|
||||
{$endif not cpu64bitaddr}
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REGISTER;
|
||||
result.size:=retcgsize;
|
||||
if (side=callerside) then
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
else
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -27,7 +27,7 @@ unit cpupara;
|
||||
|
||||
uses
|
||||
globtype,
|
||||
cpubase,cgbase,
|
||||
cpubase,cgbase,cgutils,
|
||||
symconst,symtype,symsym,symdef,
|
||||
aasmtai,aasmdata,
|
||||
parabase,paramgr;
|
||||
@ -48,6 +48,7 @@ unit cpupara;
|
||||
function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
|
||||
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
||||
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
|
||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -55,8 +56,7 @@ unit cpupara;
|
||||
uses
|
||||
cutils,verbose,
|
||||
systems,
|
||||
defutil,
|
||||
cgutils;
|
||||
defutil;
|
||||
|
||||
const
|
||||
paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
|
||||
@ -393,6 +393,12 @@ unit cpupara;
|
||||
|
||||
|
||||
procedure tx86_64paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||
begin
|
||||
p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
|
||||
end;
|
||||
|
||||
|
||||
function tx86_64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
|
||||
var
|
||||
retcgsize : tcgsize;
|
||||
begin
|
||||
@ -400,38 +406,38 @@ unit cpupara;
|
||||
if (p.proctypeoption=potype_constructor) then
|
||||
retcgsize:=OS_ADDR
|
||||
else
|
||||
retcgsize:=def_cgsize(p.returndef);
|
||||
location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
|
||||
retcgsize:=def_cgsize(def);
|
||||
location_reset(result,LOC_INVALID,OS_NO);
|
||||
{ void has no location }
|
||||
if is_void(p.returndef) then
|
||||
if is_void(def) then
|
||||
begin
|
||||
location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
|
||||
location_reset(result,LOC_VOID,OS_NO);
|
||||
exit;
|
||||
end;
|
||||
{ Return is passed as var parameter }
|
||||
if ret_in_param(p.returndef,p.proccalloption) then
|
||||
if ret_in_param(def,p.proccalloption) then
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REFERENCE;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_REFERENCE;
|
||||
result.size:=retcgsize;
|
||||
exit;
|
||||
end;
|
||||
{ Return in FPU register? }
|
||||
if p.returndef.typ=floatdef then
|
||||
if def.typ=floatdef then
|
||||
begin
|
||||
case tfloatdef(p.returndef).floattype of
|
||||
case tfloatdef(def).floattype of
|
||||
s32real,s64real:
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_MMREGISTER;
|
||||
p.funcretloc[side].register:=NR_MM_RESULT_REG;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_MMREGISTER;
|
||||
result.register:=NR_MM_RESULT_REG;
|
||||
result.size:=retcgsize;
|
||||
end;
|
||||
s64currency,
|
||||
s64comp,
|
||||
s80real:
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_FPUREGISTER;
|
||||
p.funcretloc[side].register:=NR_FPU_RESULT_REG;
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.loc:=LOC_FPUREGISTER;
|
||||
result.register:=NR_FPU_RESULT_REG;
|
||||
result.size:=retcgsize;
|
||||
end;
|
||||
else
|
||||
internalerror(200405034);
|
||||
@ -440,41 +446,41 @@ unit cpupara;
|
||||
else
|
||||
{ Return in register }
|
||||
begin
|
||||
p.funcretloc[side].loc:=LOC_REGISTER;
|
||||
result.loc:=LOC_REGISTER;
|
||||
if retcgsize=OS_NO then
|
||||
begin
|
||||
case p.returndef.size of
|
||||
case def.size of
|
||||
0..4:
|
||||
begin
|
||||
p.funcretloc[side].size:=OS_32;
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBD);
|
||||
result.size:=OS_32;
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBD);
|
||||
end;
|
||||
5..8:
|
||||
begin
|
||||
p.funcretloc[side].size:=OS_64;
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBQ);
|
||||
result.size:=OS_64;
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBQ);
|
||||
end;
|
||||
9..16:
|
||||
begin
|
||||
p.funcretloc[side].size:=OS_128;
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE);
|
||||
p.funcretloc[side].registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE);
|
||||
result.size:=OS_128;
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE);
|
||||
result.registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE);
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else if retcgsize in [OS_128,OS_S128] then
|
||||
begin
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE);
|
||||
p.funcretloc[side].registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE);
|
||||
result.size:=retcgsize;
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE);
|
||||
result.registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE);
|
||||
end
|
||||
else
|
||||
begin
|
||||
p.funcretloc[side].size:=retcgsize;
|
||||
result.size:=retcgsize;
|
||||
if side=callerside then
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
|
||||
else
|
||||
p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user