* add a tdef to each parameter location and set it for all target

backends (not yet used, will be used in high level code generator)

git-svn-id: trunk@24761 -
This commit is contained in:
Jonas Maebe 2013-06-02 10:24:02 +00:00
parent 53ba7fbb8b
commit 7566ddcc8f
13 changed files with 697 additions and 218 deletions

View File

@ -81,20 +81,25 @@ unit cpupara;
procedure tarmparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym : tparavarsym;
pdef : tdef;
begin
if nr<1 then
internalerror(2002070801);
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
size:=OS_INT;
def:=pdef;
size:=def_cgsize(pdef);
{ the four first parameters are passed into registers }
if nr<=4 then
begin
@ -362,6 +367,7 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_R0;
paraloc^.size:=OS_ADDR;
paraloc^.def:=voidpointertype;
break;
end;
@ -413,16 +419,28 @@ unit cpupara;
if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
case paracgsize of
OS_F32:
paraloc^.size:=OS_32;
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
OS_F64:
paraloc^.size:=OS_32;
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
else
internalerror(2005082901);
end
else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
paraloc^.size := OS_32
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
paraloc^.size:=paracgsize;
begin
paraloc^.size:=paracgsize;
paraloc^.def:=get_paraloc_def(paradef,paracgsize,paralen,firstparaloc);
end;
case loc of
LOC_REGISTER:
begin
@ -449,6 +467,7 @@ unit cpupara;
{ LOC_REFERENCE always contains everything that's left }
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=getarraydef(u8inttype,paralen);
if (side=callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
@ -522,6 +541,7 @@ unit cpupara;
{ LOC_REFERENCE always contains everything that's left }
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=getarraydef(u8inttype,paralen);
if (side=callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
@ -534,6 +554,7 @@ unit cpupara;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paraloc^.size:=OS_ADDR;
paraloc^.def:=getpointerdef(paradef);
assignintreg
end
else
@ -545,6 +566,7 @@ unit cpupara;
stack_offset:=align(stack_offset,8);
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
@ -621,6 +643,7 @@ unit cpupara;
internalerror(2012032501);
end;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else if (p.proccalloption in [pocall_softfloat]) or
(cs_fp_emulation in current_settings.moduleswitches) or
@ -636,6 +659,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
if target_info.endian = endian_big then
@ -643,6 +667,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
OS_32,
OS_F32:
@ -650,6 +675,7 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RETURN_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
else
internalerror(2005082603);
@ -660,6 +686,7 @@ unit cpupara;
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=NR_FPU_RESULT_REG;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end;
end
{ Return in register }
@ -673,6 +700,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
if target_info.endian = endian_big then
@ -680,15 +708,22 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RETURN_REG;
if (result.intsize<>3) then
paraloc^.size:=retcgsize
begin
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
paraloc^.size:=OS_32;
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
end;
end;
end;

View File

@ -71,20 +71,25 @@ unit cpupara;
procedure tavrparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym: tparavarsym;
pdef: tdef;
begin
if nr<1 then
internalerror(2002070801);
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
size:=OS_INT;
size:=def_cgsize(pdef);
def:=pdef;
{ the four first parameters are passed into registers }
if nr<=9 then
begin
@ -225,6 +230,7 @@ unit cpupara;
paracgsize : tcgsize;
paralen : longint;
i : integer;
firstparaloc: boolean;
procedure assignintreg;
begin
@ -272,6 +278,7 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_R25;
paraloc^.size:=OS_ADDR;
paraloc^.def:=voidpointertype;
break;
end;
@ -315,6 +322,7 @@ unit cpupara;
if paralen=0 then
internalerror(200410311);
{$endif EXTDEBUG}
firstparaloc:=true;
while paralen>0 do
begin
paraloc:=hp.paraloc[side].add_location;
@ -322,16 +330,28 @@ unit cpupara;
if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
case paracgsize of
OS_F32:
paraloc^.size:=OS_32;
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
OS_F64:
paraloc^.size:=OS_32;
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
else
internalerror(2005082901);
end
else if paracgsize<>OS_S8 then
paraloc^.size := OS_8
begin
paraloc^.size:=OS_8;
paraloc^.def:=u8inttype
end
else
paraloc^.size:=paracgsize;
begin
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
end;
case loc of
LOC_REGISTER:
begin
@ -346,6 +366,8 @@ unit cpupara;
{ LOC_REFERENCE covers always the overleft }
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=get_paraloc_def(paradef,paracgsize,paralen,firstparaloc);
if (side=callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
@ -357,9 +379,13 @@ unit cpupara;
begin
paraloc^.size:=OS_ADDR;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
assignintreg
begin
paraloc^.def:=getpointerdef(paradef);
assignintreg
end
else
begin
paraloc^.def:=hp.vardef;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
@ -378,6 +404,7 @@ unit cpupara;
end;
end;
dec(paralen,tcgsize2size[paraloc^.size]);
firstparaloc:=false;
end;
end;
curintreg:=nextintreg;
@ -424,10 +451,12 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
OS_32,
OS_F32:
@ -435,6 +464,7 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RETURN_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
else
internalerror(2005082603);
@ -445,6 +475,7 @@ unit cpupara;
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=NR_FPU_RESULT_REG;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end;
end
{ Return in register }
@ -455,16 +486,19 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RETURN_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
end;
end;

View File

@ -277,18 +277,23 @@ unit cpupara;
procedure ti386paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym: tparavarsym;
pdef: tdef;
begin
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=get_para_align(pd.proccalloption);
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
size:=OS_INT;
size:=def_cgsize(pdef);
def:=pdef;
if pd.proccalloption=pocall_register then
begin
if (nr<=length(parasupregs)) then
@ -367,6 +372,7 @@ unit cpupara;
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=NR_FPU_RESULT_REG;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
{ Return in register }
@ -381,6 +387,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
{ high 32bits }
paraloc:=result.add_location;
@ -390,10 +397,12 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
begin
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
if side=callerside then
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
else
@ -413,8 +422,9 @@ unit cpupara;
paralen,
varalign : longint;
paraalign : shortint;
pushaddr : boolean;
paracgsize : tcgsize;
firstparaloc,
pushaddr : boolean;
begin
paraalign:=get_para_align(p.proccalloption);
{ we push Flags and CS as long
@ -476,6 +486,7 @@ unit cpupara;
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
if side=callerside then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
@ -497,6 +508,7 @@ unit cpupara;
begin
if paralen=0 then
internalerror(200501163);
firstparaloc:=true;
while (paralen>0) do
begin
paraloc:=hp.paraloc[side].add_location;
@ -505,15 +517,22 @@ unit cpupara;
if (paracgsize in [OS_F64,OS_F32]) then
begin
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
l:=paralen;
end
else
begin
{ We can allocate at maximum 32 bits per location }
if paralen>sizeof(aint) then
l:=sizeof(aint)
begin
l:=sizeof(aint);
paraloc^.def:=uinttype;
end
else
l:=paralen;
begin
l:=paralen;
paraloc^.def:=get_paraloc_def(paradef,paracgsize,l,firstparaloc);
end;
paraloc^.size:=int_cgsize(l);
end;
if (side=callerside) or
@ -531,6 +550,7 @@ unit cpupara;
inc(paraloc^.reference.offset,4);
parasize:=align(parasize+l,varalign);
dec(paralen,l);
firstparaloc:=false;
end;
end;
if p.proccalloption in pushleftright_pocalls then
@ -552,9 +572,10 @@ unit cpupara;
l,
paralen,
varalign : longint;
pushaddr : boolean;
paraalign : shortint;
pass : byte;
firstparaloc,
pushaddr : boolean;
begin
if paras.count=0 then
exit;
@ -621,6 +642,7 @@ unit cpupara;
begin
paraloc:=hp.paraloc[side].add_location;
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
inc(parareg);
@ -636,6 +658,7 @@ unit cpupara;
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
if side=callerside then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
@ -650,6 +673,7 @@ unit cpupara;
begin
if paralen=0 then
internalerror(200501163);
firstparaloc:=true;
while (paralen>0) do
begin
paraloc:=hp.paraloc[side].add_location;
@ -658,15 +682,22 @@ unit cpupara;
if (paracgsize in [OS_F64,OS_F32]) then
begin
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
l:=paralen;
end
else
begin
{ We can allocate at maximum 32 bits per location }
if paralen>sizeof(aint) then
l:=sizeof(aint)
begin
l:=sizeof(aint);
paraloc^.def:=uinttype;
end
else
l:=paralen;
begin
l:=paralen;
paraloc^.def:=get_paraloc_def(paradef,paracgsize,l,firstparaloc);
end;
paraloc^.size:=int_cgsize(l);
end;
if side=callerside then
@ -679,6 +710,7 @@ unit cpupara;
inc(paraloc^.reference.offset,target_info.first_parm_offset);
parasize:=align(parasize+l,varalign);
dec(paralen,l);
firstparaloc:=false;
end;
end;
end;

View File

@ -231,18 +231,23 @@ unit cpupara;
procedure ti8086paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym: tparavarsym;
pdef : tdef;
begin
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=get_para_align(pd.proccalloption);
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
size:=OS_INT;
size:=def_cgsize(pdef);
def:=pdef;
if pd.proccalloption=pocall_register then
begin
if (nr<=length(parasupregs)) then
@ -321,6 +326,7 @@ unit cpupara;
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=NR_FPU_RESULT_REG;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
{ Return in register }
@ -335,6 +341,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
paraloc^.size:=OS_16;
paraloc^.def:=u16inttype;
{ bits 16..31 }
paraloc:=result.add_location;
@ -344,6 +351,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
paraloc^.size:=OS_16;
paraloc^.def:=u16inttype;
{ bits 32..47 }
paraloc:=result.add_location;
@ -353,6 +361,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGHER_REG;
paraloc^.size:=OS_16;
paraloc^.def:=u16inttype;
{ bits 48..63 }
paraloc:=result.add_location;
@ -362,6 +371,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGHEST_REG;
paraloc^.size:=OS_16;
paraloc^.def:=u16inttype;
end
else if retcgsize in [OS_32,OS_S32] then
begin
@ -371,6 +381,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN32_LOW_REG;
paraloc^.size:=OS_16;
paraloc^.def:=u16inttype;
{ high 16bits }
paraloc:=result.add_location;
@ -380,10 +391,12 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN32_HIGH_REG;
paraloc^.size:=OS_16;
paraloc^.def:=u16inttype;
end
else
begin
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
if side=callerside then
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
else
@ -403,8 +416,9 @@ unit cpupara;
paralen,
varalign : longint;
paraalign : shortint;
pushaddr : boolean;
paracgsize : tcgsize;
firstparaloc,
pushaddr : boolean;
begin
paraalign:=get_para_align(p.proccalloption);
{ we push Flags and CS as long
@ -466,6 +480,7 @@ unit cpupara;
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
if side=callerside then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
@ -487,6 +502,7 @@ unit cpupara;
begin
if paralen=0 then
internalerror(200501163);
firstparaloc:=true;
while (paralen>0) do
begin
paraloc:=hp.paraloc[side].add_location;
@ -495,15 +511,22 @@ unit cpupara;
if (paracgsize in [OS_F64,OS_F32]) then
begin
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
l:=paralen;
end
else
begin
{ We can allocate at maximum 32 bits per location }
if paralen>sizeof(aint) then
l:=sizeof(aint)
begin
l:=sizeof(aint);
paraloc^.def:=uinttype;
end
else
l:=paralen;
begin
l:=paralen;
paraloc^.def:=get_paraloc_def(paradef,paracgsize,l,firstparaloc);
end;
paraloc^.size:=int_cgsize(l);
end;
if (side=callerside) or
@ -521,6 +544,7 @@ unit cpupara;
inc(paraloc^.reference.offset,4);
parasize:=align(parasize+l,varalign);
dec(paralen,l);
firstparaloc:=false;
end;
end;
if p.proccalloption in pushleftright_pocalls then
@ -545,6 +569,7 @@ unit cpupara;
pushaddr : boolean;
paraalign : shortint;
pass : byte;
firstparaloc : boolean;
begin
if paras.count=0 then
exit;
@ -611,6 +636,7 @@ unit cpupara;
begin
paraloc:=hp.paraloc[side].add_location;
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
inc(parareg);
@ -626,6 +652,7 @@ unit cpupara;
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
if side=callerside then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
@ -640,6 +667,7 @@ unit cpupara;
begin
if paralen=0 then
internalerror(200501163);
firstparaloc:=true;
while (paralen>0) do
begin
paraloc:=hp.paraloc[side].add_location;
@ -648,15 +676,22 @@ unit cpupara;
if (paracgsize in [OS_F64,OS_F32]) then
begin
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
l:=paralen;
end
else
begin
{ We can allocate at maximum 32 bits per location }
if paralen>sizeof(aint) then
l:=sizeof(aint)
begin
l:=sizeof(aint);
paraloc^.def:=uinttype;
end
else
l:=paralen;
begin
l:=paralen;
paraloc^.def:=get_paraloc_def(paradef,paracgsize,l,firstparaloc);
end;
paraloc^.size:=int_cgsize(l);
end;
if side=callerside then
@ -669,6 +704,7 @@ unit cpupara;
inc(paraloc^.reference.offset,target_info.first_parm_offset);
parasize:=align(parasize+l,varalign);
dec(paralen,l);
firstparaloc:=false;
end;
end;
end;

View File

@ -147,6 +147,7 @@ implementation
result.size:=OS_NO;
result.intsize:=0;
paraloc^.size:=OS_NO;
paraloc^.def:=voidtype;
paraloc^.loc:=LOC_VOID;
exit;
end;
@ -156,6 +157,11 @@ implementation
retcgsize:=OS_INT;
result.intsize:=sizeof(pint);
end
else if jvmimplicitpointertype(result.def) then
begin
retcgsize:=OS_ADDR;
result.def:=getpointerdef(result.def);
end
else
begin
retcgsize:=def_cgsize(result.def);
@ -168,6 +174,8 @@ implementation
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_EVAL_STACK_BASE;
paraloc^.reference.offset:=0;
paraloc^.size:=result.size;
paraloc^.def:=result.def;
end;
function TJVMParaManager.param_use_paraloc(const cgpara: tcgpara): boolean;
@ -226,6 +234,11 @@ implementation
paracgsize:=OS_ADDR;
paradef:=java_jlobject;
end
else if jvmimplicitpointertype(hp.vardef) then
begin
paracgsize:=OS_ADDR;
paradef:=getpointerdef(hp.vardef);
end
else
begin
paracgsize:=def_cgsize(hp.vardef);
@ -246,6 +259,8 @@ implementation
taking up two slots) }
paraloc^.loc:=LOC_REFERENCE;;
paraloc^.reference.offset:=paraofs;
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
case side of
callerside:
begin

View File

@ -68,16 +68,20 @@ unit cpupara;
procedure tm68kparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym: tparavarsym;
pdef: tdef;
begin
if nr<1 then
internalerror(2002070801);
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@ -87,7 +91,8 @@ unit cpupara;
loc:=LOC_REFERENCE;
reference.index:=NR_STACK_POINTER_REG;
reference.offset:=target_info.first_parm_offset+nr*4;
size:=OS_INT;
size:=def_cgsize(pdef);
def:=pdef;
end;
end;
@ -206,6 +211,7 @@ unit cpupara;
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=NR_FPU_RESULT_REG;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
{ Return in register }
@ -215,6 +221,7 @@ unit cpupara;
{ low 32bits }
paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
if side=callerside then
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
else
@ -223,6 +230,7 @@ unit cpupara;
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
if side=calleeside then
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
else
@ -232,6 +240,7 @@ unit cpupara;
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
if side=callerside then
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
else
@ -266,6 +275,7 @@ unit cpupara;
nextintreg,
nextfloatreg : tsuperregister;
stack_offset : longint;
firstparaloc : boolean;
begin
result:=0;
@ -301,6 +311,7 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_D0;
paraloc^.size:=OS_ADDR;
paraloc^.def:=voidpointertype;
break;
end;
@ -344,6 +355,7 @@ unit cpupara;
end
else
internalerror(200506052);
firstparaloc:=true;
{ can become < 0 for e.g. 3-byte records }
while (paralen > 0) do
begin
@ -384,6 +396,7 @@ unit cpupara;
{$endif DEBUG_CHARLIE}
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=get_paraloc_def(paradef,paraloc^.size,paralen,firstparaloc);
if (side = callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
@ -392,6 +405,7 @@ unit cpupara;
inc(stack_offset,align(paralen,4));
paralen := 0;
end;
firstparaloc:=false;
end;
end;
result:=stack_offset;
@ -493,6 +507,7 @@ unit cpupara;
paraloc:=p.paraloc[callerside].add_location;
paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=def_cgsize(p.vardef);
paraloc^.def:=p.vardef;
{ pattern is always uppercase'd }
if s='D0' then
paraloc^.register:=NR_D0

View File

@ -126,16 +126,20 @@ implementation
procedure TMIPSParaManager.GetIntParaLoc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym: tparavarsym;
pdef: tdef;
begin
if nr<1 then
InternalError(2002100806);
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@ -154,7 +158,8 @@ implementation
reference.index:=NR_STACK_POINTER_REG;
reference.offset:=nr*mips_sizeof_register_param;
end;
size:=OS_INT;
size:=def_cgsize(pdef);
def:=pdef;
end;
end;
@ -225,6 +230,7 @@ implementation
if retcgsize=OS_F64 then
setsubreg(paraloc^.register,R_SUBFD);
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
{ Return in register }
@ -239,6 +245,7 @@ implementation
else
paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
{ high }
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
@ -247,12 +254,14 @@ implementation
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
{$endif cpu64bitalu}
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
if side=callerside then
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
else
@ -269,11 +278,13 @@ implementation
hp : tparavarsym;
paracgsize : tcgsize;
paralen : longint;
paradef : tdef;
fpparareg : integer;
reg : tsuperregister;
alignment : longint;
tmp : longint;
locdef : tdef;
paradef : tdef;
fpparareg : integer;
reg : tsuperregister;
alignment : longint;
tmp : longint;
firstparaloc : boolean;
begin
fpparareg := 0;
for i:=0 to paras.count-1 do
@ -290,6 +301,7 @@ implementation
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_R0;
paraloc^.size:=OS_ADDR;
paraloc^.def:=voidpointertype;
break;
end;
@ -321,6 +333,7 @@ implementation
//writeln('para: ',hp.Name,' typ=',hp.vardef.typ,' paracgsize=',paracgsize,' align=',hp.vardef.alignment);
hp.paraloc[side].reset;
hp.paraloc[side].Alignment:=alignment;
locdef:=paradef;
if (paracgsize=OS_NO) or
{ Ordinals on caller side must be promoted to machine word }
((target_info.endian=endian_big) and // applies to little-endian too?
@ -329,9 +342,15 @@ implementation
(paralen<tcgsize2size[OS_INT]))then
begin
if is_signed(paradef) then
paracgsize:=OS_S32
begin
paracgsize:=OS_S32;
locdef:=s32inttype;
end
else
paracgsize:=OS_32;
begin
paracgsize:=OS_32;
locdef:=u32inttype;
end;
paralen:=align(paralen,4);
end
else
@ -363,6 +382,7 @@ implementation
if (not(paracgsize in [OS_F32, OS_F64])) or (fpparareg = 2) then
can_use_float := false;
firstparaloc:=true;
while paralen>0 do
begin
paraloc:=hp.paraloc[side].add_location;
@ -370,9 +390,15 @@ implementation
if (paracgsize in [OS_64,OS_S64]) or
((paracgsize in [OS_F32,OS_F64]) and
not(can_use_float)) then
paraloc^.size:=OS_32
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
paraloc^.size:=paracgsize;
begin
paraloc^.size:=paracgsize;
paraloc^.def:=locdef;
end;
{ ret in param? }
if (vo_is_funcret in hp.varoptions) and
@ -427,6 +453,7 @@ implementation
begin
paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
paraloc^.size := OS_INT;
paraloc^.def := osuinttype;
end;
inc(intparareg);
inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
@ -436,6 +463,7 @@ implementation
begin
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=get_paraloc_def(locdef,paraloc^.size,paralen,firstparaloc);
if side=callerside then
begin
@ -463,6 +491,7 @@ implementation
paralen:=0;
end;
dec(paralen,tcgsize2size[paraloc^.size]);
firstparaloc:=false;
end;
end;
{ O32 ABI reqires at least 16 bytes }

View File

@ -39,6 +39,7 @@ unit parabase;
TCGParaLocation = record
Next : PCGParaLocation;
Size : TCGSize; { size of this location }
Def : tdef;
Loc : TCGLoc;
case TCGLoc of
LOC_REFERENCE : (reference : TCGParaReference);

View File

@ -149,6 +149,11 @@ unit paramgr;
itself as well; parameter retinparam is only valid if function
returns true }
function handle_common_ret_in_param(def:tdef;pd:tabstractprocdef;out retinparam:boolean):boolean;
{ returns the def to use for a tparalocation part of a cgpara for paradef,
for which the tcgsize is locsize and the integer length is restlen.
fullsize is true if restlen equals the full paradef size }
function get_paraloc_def(paradef: tdef; paracgsize: tcgsize; restlen: aint; fullsize: boolean): tdef;
end;
@ -403,6 +408,7 @@ implementation
len:=tcgsize2size[paraloc^.size];
newparaloc:=cgpara.add_location;
newparaloc^.size:=paraloc^.size;
newparaloc^.def:=paraloc^.def;
newparaloc^.shiftval:=paraloc^.shiftval;
{ $warning maybe release this optimization for all targets? }
{ released for all CPUs:
@ -543,6 +549,7 @@ implementation
retloc.size:=OS_NO;
retcgsize:=OS_NO;
retloc.intsize:=0;
paraloc^.def:=retloc.def;
paraloc^.size:=OS_NO;
paraloc^.loc:=LOC_VOID;
exit;
@ -565,6 +572,7 @@ implementation
paraloc:=retloc.add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=retcgsize;
paraloc^.def:=retloc.def;
exit;
end;
result:=false;
@ -602,6 +610,19 @@ implementation
end;
function tparamanager.get_paraloc_def(paradef: tdef; paracgsize: tcgsize; restlen: aint; fullsize: boolean): tdef;
begin
if fullsize then
result:=paradef
{ no support for 128 bit ints -> tcgsize2orddef can't handle
OS_(S)128 }
else if not(paracgsize in [OS_NO,OS_128,OS_S128]) then
result:=cgsize_orddef(paracgsize)
else
result:=getarraydef(u8inttype,restlen);
end;
procedure tparamanager.getintparaloc(pd: tabstractprocdef; nr : longint; var cgpara: tcgpara);
begin
if (nr<1) or (nr>pd.paras.count) then

View File

@ -80,18 +80,23 @@ unit cpupara;
procedure tppcparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym : tparavarsym;
pdef : tdef;
begin
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=get_para_align(pd.proccalloption);
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
size:=OS_INT;
size:=def_cgsize(pdef);
def:=pdef;
if (nr<=8) then
begin
if nr=0 then
@ -262,6 +267,7 @@ unit cpupara;
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=NR_FPU_RESULT_REG;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
{ Return in register }
@ -275,6 +281,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
{ high 32bits }
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
@ -283,6 +290,7 @@ unit cpupara;
else
paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
begin
@ -292,6 +300,7 @@ unit cpupara;
else
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end;
end;
end;
@ -318,6 +327,7 @@ unit cpupara;
stack_offset: longint;
paralen: aint;
nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
locdef,
paradef : tdef;
paraloc : pcgparalocation;
i : integer;
@ -325,6 +335,7 @@ unit cpupara;
loc : tcgloc;
paracgsize: tcgsize;
sym: tfieldvarsym;
firstparaloc: boolean;
begin
{$ifdef extdebug}
@ -366,6 +377,7 @@ unit cpupara;
paraloc^.loc := LOC_REGISTER;
paraloc^.register := NR_R0;
paraloc^.size := OS_ADDR;
paraloc^.def:=voidpointertype;
break;
end;
@ -420,10 +432,16 @@ unit cpupara;
(paradef.typ = floatdef) then
begin
loc := LOC_REGISTER;
if paracgsize = OS_F64 then
paracgsize := OS_64
if paracgsize=OS_F64 then
begin
paracgsize:=OS_64;
paradef:=u64inttype;
end
else
paracgsize := OS_32;
begin
paracgsize:=OS_32;
paradef:=u32inttype;
end;
end;
hp.paraloc[side].alignment:=std_param_align;
@ -444,6 +462,8 @@ unit cpupara;
end
else
internalerror(2005011310);
locdef:=paradef;
firstparaloc:=true;
{ can become < 0 for e.g. 3-byte records }
while (paralen > 0) do
begin
@ -457,12 +477,21 @@ unit cpupara;
begin
paraloc^.loc := loc;
{ make sure we don't lose whether or not the type is signed }
if (paradef.typ <> orddef) then
paracgsize := int_cgsize(paralen);
if (paradef.typ<>orddef) then
begin
paracgsize:=int_cgsize(paralen);
locdef:=get_paraloc_def(paradef,paracgsize,paralen,firstparaloc);
end;
if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
paraloc^.size := OS_INT
begin
paraloc^.size:=OS_INT;
paraloc^.def:=u32inttype;
end
else
paraloc^.size := paracgsize;
begin
paraloc^.size:=paracgsize;
paraloc^.def:=locdef;
end;
{ aix requires that record data stored in parameter
registers is left-aligned }
if (target_info.system in systems_aix) and
@ -471,6 +500,7 @@ unit cpupara;
begin
paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
paraloc^.size := OS_INT;
paraloc^.def := u32inttype;
end;
paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
inc(nextintreg);
@ -483,6 +513,7 @@ unit cpupara;
begin
paraloc^.loc:=loc;
paraloc^.size := paracgsize;
paraloc^.def := paradef;
paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
inc(nextfloatreg);
dec(paralen,tcgsize2size[paraloc^.size]);
@ -517,10 +548,24 @@ unit cpupara;
paraloc^.loc:=LOC_REFERENCE;
case loc of
LOC_FPUREGISTER:
paraloc^.size:=int_float_cgsize(paralen);
begin
paraloc^.size:=int_float_cgsize(paralen);
case paraloc^.size of
OS_F32: paraloc^.def:=s32floattype;
OS_F64: paraloc^.def:=s64floattype;
else
internalerror(2013060124);
end;
end;
LOC_REGISTER,
LOC_REFERENCE:
paraloc^.size:=int_cgsize(paralen);
begin
paraloc^.size:=int_cgsize(paralen);
if paraloc^.size<>OS_NO then
paraloc^.def:=cgsize_orddef(paraloc^.size)
else
paraloc^.def:=getarraydef(u8inttype,paralen);
end;
else
internalerror(2006011101);
end;
@ -553,6 +598,7 @@ unit cpupara;
end;
paralen := 0;
end;
firstparaloc:=false;
end;
end;
curintreg:=nextintreg;
@ -595,6 +641,7 @@ unit cpupara;
paraloc:=hp.paraloc[callerside].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=def_cgsize(hp.vardef);
paraloc^.def:=hp.vardef;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
paraloc^.reference.offset:=parasize;
@ -623,6 +670,7 @@ unit cpupara;
paraloc:=p.paraloc[callerside].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=paracgsize;
paraloc^.def:=p.vardef;
paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
{ pattern is always uppercase'd }
if s='D0' then
@ -667,6 +715,7 @@ unit cpupara;
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=OS_ADDR;
paraloc^.def:=voidpointertype;
paraloc^.register:=NR_R12;
end
else

View File

@ -80,17 +80,22 @@ end;
procedure tppcparamanager.getintparaloc(pd : tabstractprocdef; nr: longint; var cgpara: tcgpara);
var
paraloc: pcgparalocation;
def: tdef;
psym: tparavarsym;
pdef: tdef;
begin
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size := def_cgsize(def);
cgpara.size := def_cgsize(pdef);
cgpara.intsize := tcgsize2size[cgpara.size];
cgpara.alignment := get_para_align(pd.proccalloption);
cgpara.def:=def;
cgpara.def:=pdef;
paraloc := cgpara.add_location;
with paraloc^ do begin
size := OS_INT;
size := def_cgsize(pdef);
def := pdef;
if (nr <= 8) then begin
if (nr = 0) then
internalerror(200309271);
@ -219,6 +224,7 @@ begin
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=NR_FPU_RESULT_REG;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
{ Return in register }
@ -229,6 +235,7 @@ begin
else
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end;
end;
@ -255,6 +262,7 @@ var
stack_offset: longint;
paralen: aint;
nextintreg, nextfloatreg, nextmmreg : tsuperregister;
locdef,
paradef: tdef;
paraloc: pcgparalocation;
i: integer;
@ -263,6 +271,7 @@ var
paracgsize: tcgsize;
parashift : byte;
firstparaloc,
adjusttail: boolean;
begin
@ -295,6 +304,7 @@ begin
paraloc^.loc := LOC_REGISTER;
paraloc^.register := NR_R0;
paraloc^.size := OS_ADDR;
paraloc^.def := voidpointertype;
break;
end;
@ -359,6 +369,8 @@ begin
end else
internalerror(2005011310);
adjusttail:=paralen>8;
locdef:=paradef;
firstparaloc:=true;
{ can become < 0 for e.g. 3-byte records }
while (paralen > 0) do begin
paraloc := hp.paraloc[side].add_location;
@ -373,7 +385,10 @@ begin
{ make sure we don't lose whether or not the type is signed }
if (paracgsize <> OS_NO) and (paradef.typ <> orddef) then
paracgsize := int_cgsize(paralen);
begin
paracgsize := int_cgsize(paralen);
locdef:=get_paraloc_def(paradef,paracgsize,paralen,firstparaloc);
end;
{ aix requires that record data (including partial data) stored in
parameter registers is left-aligned. Other targets only do this if
@ -385,11 +400,18 @@ begin
begin
paraloc^.shiftval := (sizeof(aint)-paralen)*(-8);
paraloc^.size := OS_INT;
paraloc^.def := u64inttype;
end
else if (paracgsize in [OS_NO,OS_128,OS_S128]) then
paraloc^.size := OS_INT
begin
paraloc^.size := OS_INT;
paraloc^.def := osuinttype;
end
else
paraloc^.size := paracgsize;
begin
paraloc^.size := paracgsize;
paraloc^.def := locdef;
end;
paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
inc(nextintreg);
@ -400,6 +422,7 @@ begin
(nextfloatreg <= RS_F13) then begin
paraloc^.loc := loc;
paraloc^.size := paracgsize;
paraloc^.def := locdef;
paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
{ the PPC64 ABI says that the GPR index is increased for every parameter, no matter
which type it is stored in }
@ -417,10 +440,21 @@ begin
paraloc^.loc := LOC_REFERENCE;
case loc of
LOC_FPUREGISTER:
paraloc^.size:=int_float_cgsize(paralen);
begin
paraloc^.size:=int_float_cgsize(paralen);
case paraloc^.size of
OS_F32: paraloc^.def:=s32floattype;
OS_F64: paraloc^.def:=s64floattype;
else
internalerror(2013060122);
end;
end;
LOC_REGISTER,
LOC_REFERENCE:
paraloc^.size:=int_cgsize(paralen);
begin
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=get_paraloc_def(paradef,paraloc^.size,paralen,firstparaloc);
end;
else
internalerror(2006011101);
end;
@ -440,6 +474,7 @@ begin
inc(stack_offset, align(paralen, 8));
paralen := 0;
end;
firstparaloc:=false;
end;
end;
@ -480,6 +515,7 @@ begin
paraloc := hp.paraloc[callerside].add_location;
paraloc^.loc := LOC_REFERENCE;
paraloc^.size := def_cgsize(hp.vardef);
paraloc^.def := hp.vardef;
paraloc^.reference.index := NR_STACK_POINTER_REG;
l := push_size(hp.varspez, hp.vardef, p.proccalloption);
paraloc^.reference.offset := parasize;

View File

@ -77,16 +77,20 @@ implementation
procedure TSparcParaManager.GetIntParaLoc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym: tparavarsym;
pdef: tdef;
begin
if nr<1 then
InternalError(2002100806);
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@ -104,7 +108,8 @@ implementation
reference.index:=NR_STACK_POINTER_REG;
reference.offset:=92+(nr-6)*4;
end;
size:=OS_INT;
size:=def_cgsize(pdef);
def:=pdef;
end;
end;
@ -158,6 +163,7 @@ implementation
if retcgsize=OS_F64 then
setsubreg(paraloc^.register,R_SUBFD);
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
{ Return in register }
@ -172,6 +178,7 @@ implementation
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
{ low }
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
@ -180,12 +187,14 @@ implementation
else
paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
{$endif not cpu64bitaddr}
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
if (side=callerside) then
paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
else
@ -224,6 +233,7 @@ implementation
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_G0;
paraloc^.size:=OS_ADDR;
paraloc^.def:=voidpointertype;
break;
end;
@ -257,9 +267,15 @@ implementation
{ Floats are passed in int registers,
We can allocate at maximum 32 bits per register }
if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
paraloc^.size:=OS_32
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end
else
paraloc^.size:=paracgsize;
begin
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
end;
{ ret in param? }
if vo_is_funcret in hp.varoptions then
begin

View File

@ -99,7 +99,7 @@ unit cpupara;
MAX_PARA_CLASSES = 4;
type
tx64paraclass = (
tx64paraclasstype = (
X86_64_NO_CLASS,
X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS,
X86_64_SSE_CLASS,X86_64_SSESF_CLASS,X86_64_SSEDF_CLASS,X86_64_SSEUP_CLASS,
@ -107,6 +107,12 @@ unit cpupara;
X86_64_COMPLEX_X87_CLASS,
X86_64_MEMORY_CLASS
);
tx64paraclass = record
def: tdef;
typ: tx64paraclasstype;
end;
tx64paraclasses = array[0..MAX_PARA_CLASSES-1] of tx64paraclass;
{ Win64-specific helper }
@ -120,82 +126,168 @@ unit cpupara;
of this code is to classify each 8bytes of incoming argument by the register
class and assign registers accordingly. *)
function classify_representative_def(def1, def2: tdef): tdef;
var
def1size, def2size: asizeint;
begin
if not assigned(def1) then
result:=def2
else if not assigned(def2) then
result:=def1
else
begin
def1size:=def1.size;
def2size:=def2.size;
if def1size>def2size then
result:=def1
else if def2size>def1size then
result:=def2
else if def1.alignment>def2.alignment then
result:=def1
else
result:=def2;
end;
end;
(* Classify the argument of type TYPE and mode MODE.
CLASSES will be filled by the register class used to pass each word
of the operand. The number of words is returned. In case the parameter
should be passed in memory, 0 is returned. As a special case for zero
sized containers, classes[0] will be NO_CLASS and 1 is returned.
real_size contains either def.size, or a value derived from
def.bitpackedsize and the field offset denoting the number of bytes
spanned by a bitpacked field
See the x86-64 PS ABI for details.
*)
procedure classify_single_integer_class(def: tdef; size,real_size: aint; var cl: tx64paraclass; byte_offset: aint);
begin
if (byte_offset=0) and
(real_size in [1,2,4,8]) and
(not assigned(cl.def) or
(def.alignment>=cl.def.alignment)) then
cl.def:=def;
if size<=4 then
begin
cl.typ:=X86_64_INTEGERSI_CLASS;
if not assigned(cl.def) or
(cl.def.size<size) then
begin
case size of
1: cl.def:=u8inttype;
2: cl.def:=u16inttype;
3,4: cl.def:=u32inttype;
end;
end;
end
else
begin
cl.typ:=X86_64_INTEGER_CLASS;
if not assigned(cl.def) or
(cl.def.size<size) then
cl.def:=u64inttype;
end;
end;
function classify_as_integer_argument(def: tdef; real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint;
var
size: aint;
begin
size:=byte_offset+real_size;
classify_single_integer_class(def,size,real_size,classes[0],byte_offset);
if size<=8 then
result:=1
else
begin
classify_single_integer_class(def,size-8,real_size,classes[1],byte_offset-8);
if size>16 then
internalerror(2010021401);
result:=2;
end
end;
(* Return the union class of CLASS1 and CLASS2.
See the x86-64 PS ABI for details. *)
function merge_classes(class1, class2: tx64paraclass): tx64paraclass;
begin
(* Rule #1: If both classes are equal, this is the resulting class. *)
if (class1=class2) then
exit(class1);
if (class1.typ=class2.typ) then
begin
result.typ:=class1.typ;
result.def:=classify_representative_def(class1.def,class2.def);
exit;
end;
(* Rule #2: If one of the classes is NO_CLASS, the resulting class is
the other class. *)
if (class1=X86_64_NO_CLASS) then
if (class1.typ=X86_64_NO_CLASS) then
exit(class2);
if (class2=X86_64_NO_CLASS) then
if (class2.typ=X86_64_NO_CLASS) then
exit(class1);
(* Rule #3: If one of the classes is MEMORY, the result is MEMORY. *)
if (class1=X86_64_MEMORY_CLASS) or
(class2=X86_64_MEMORY_CLASS) then
exit(X86_64_MEMORY_CLASS);
if (class1.typ=X86_64_MEMORY_CLASS) then
exit(class1)
else if (class2.typ=X86_64_MEMORY_CLASS) then
exit(class2);
(* Rule #4: If one of the classes is INTEGER, the result is INTEGER. *)
{ 32 bit }
if ((class1=X86_64_INTEGERSI_CLASS) and
(class2=X86_64_SSESF_CLASS)) or
((class2=X86_64_INTEGERSI_CLASS) and
(class1=X86_64_SSESF_CLASS)) then
exit(X86_64_INTEGERSI_CLASS);
if ((class1.typ=X86_64_INTEGERSI_CLASS) and
(class2.typ=X86_64_SSESF_CLASS)) then
exit(class1)
else if ((class2.typ=X86_64_INTEGERSI_CLASS) and
(class1.typ=X86_64_SSESF_CLASS)) then
exit(class2);
{ 64 bit }
if (class1 in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) or
(class2 in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) then
exit(X86_64_INTEGER_CLASS);
if (class1.typ in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) then
begin
result:=class1;
if result.def.size<8 then
begin
result.typ:=X86_64_INTEGER_CLASS;
result.def:=s64inttype;
end;
exit
end
else if (class2.typ in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) then
begin
result:=class2;
if result.def.size<8 then
begin
result.typ:=X86_64_INTEGER_CLASS;
result.def:=s64inttype;
end;
exit
end;
(* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
MEMORY is used. *)
if (class1 in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) or
(class2 in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) then
exit(X86_64_MEMORY_CLASS);
if (class1.typ in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) then
begin
result:=class1;
result.typ:=X86_64_MEMORY_CLASS;
exit;
end
else if (class2.typ in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) then
begin
result:=class2;
result.typ:=X86_64_MEMORY_CLASS;
exit;
end;
(* Rule #6: Otherwise class SSE is used. *)
result:=X86_64_SSE_CLASS;
end;
(* Classify the argument of type TYPE and mode MODE.
CLASSES will be filled by the register class used to pass each word
of the operand. The number of words is returned. In case the parameter
should be passed in memory, 0 is returned. As a special case for zero
sized containers, classes[0] will be NO_CLASS and 1 is returned.
real_size contains either def.size, or a value derived from
def.bitpackedsize and the field offset denoting the number of bytes
spanned by a bitpacked field
See the x86-64 PS ABI for details.
*)
function classify_as_integer_argument(real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint;
var
size: aint;
begin
size:=byte_offset+real_size;
if size<=4 then
classes[0]:=X86_64_INTEGERSI_CLASS
if class1.def.size>class2.def.size then
result:=class1
else
classes[0]:=X86_64_INTEGER_CLASS;
if size<=8 then
result:=1
else
begin
if size<=12 then
classes[1]:=X86_64_INTEGERSI_CLASS
else if (size<=16) then
classes[1]:=X86_64_INTEGER_CLASS
else
internalerror(2010021401);
result:=2;
end
result:=class2;
result.typ:=X86_64_SSE_CLASS;
result.def:=getarraydef(s32floattype,2)
end;
@ -211,7 +303,8 @@ unit cpupara;
begin
if aggregate_in_registers_win64(varspez,def.size) then
begin
classes[0]:=X86_64_INTEGER_CLASS;
classes[0].typ:=X86_64_INTEGER_CLASS;
classes[0].def:=def;
result:=1;
end
else
@ -231,14 +324,18 @@ unit cpupara;
signal memory class, so handle it as special case. *)
if (words=0) then
begin
classes[0]:=X86_64_NO_CLASS;
classes[0].typ:=X86_64_NO_CLASS;
classes[0].def:=def;
exit(1);
end;
{ we'll be merging the classes elements with the subclasses
elements, so initialise them first }
for i:=low(classes) to high(classes) do
classes[i]:=X86_64_NO_CLASS;
begin
classes[i].typ:=X86_64_NO_CLASS;
classes[i].def:=nil;
end;
result:=words;
end;
@ -249,6 +346,7 @@ unit cpupara;
i,
pos: longint;
begin
fillchar(subclasses,sizeof(subclasses),0);
result:=classify_argument(def,varspez,real_size,subclasses,new_byte_offset mod 8);
if (result=0) then
exit;
@ -274,38 +372,41 @@ unit cpupara;
X86_64_SSE_CLASS or any other ones aren't
X86_64_SSEUP_CLASS, everything should be passed in
memory. *)
if (classes[0]<>X86_64_SSE_CLASS) then
if (classes[0].typ<>X86_64_SSE_CLASS) then
exit(0);
for i:=1 to words-1 do
if (classes[i]<>X86_64_SSEUP_CLASS) then
if (classes[i].typ<>X86_64_SSEUP_CLASS) then
exit(0);
end;
(* Final merger cleanup. *)
(* The first one must never be X86_64_SSEUP_CLASS or
X86_64_X87UP_CLASS. *)
if (classes[0]=X86_64_SSEUP_CLASS) or
(classes[0]=X86_64_X87UP_CLASS) then
if (classes[0].typ=X86_64_SSEUP_CLASS) or
(classes[0].typ=X86_64_X87UP_CLASS) then
internalerror(2010021402);
for i:=0 to words-1 do
begin
(* If one class is MEMORY, everything should be passed in
memory. *)
if (classes[i]=X86_64_MEMORY_CLASS) then
if (classes[i].typ=X86_64_MEMORY_CLASS) then
exit(0);
(* The X86_64_SSEUP_CLASS should be always preceded by
X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. *)
if (classes[i]=X86_64_SSEUP_CLASS) and
(classes[i-1]<>X86_64_SSE_CLASS) and
(classes[i-1]<>X86_64_SSEUP_CLASS) then
classes[i]:=X86_64_SSE_CLASS;
if (classes[i].typ=X86_64_SSEUP_CLASS) and
(classes[i-1].typ<>X86_64_SSE_CLASS) and
(classes[i-1].typ<>X86_64_SSEUP_CLASS) then
begin
classes[i].typ:=X86_64_SSE_CLASS;
classes[i].def:=getarraydef(s32floattype,2);
end;
(* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
everything should be passed in memory. *)
if (classes[i]=X86_64_X87UP_CLASS) and
(classes[i-1]<>X86_64_X87_CLASS) then
if (classes[i].typ=X86_64_X87UP_CLASS) and
(classes[i-1].typ<>X86_64_X87_CLASS) then
exit(0);
end;
@ -317,20 +418,32 @@ unit cpupara;
such locations always up to 64 bits, although this loads/stores
some superfluous data }
{ 1) the first part is 32 bit while there is still a second part }
if (classes[1]<>X86_64_NO_CLASS) then
case classes[0] of
if (classes[1].typ<>X86_64_NO_CLASS) then
case classes[0].typ of
X86_64_INTEGERSI_CLASS:
classes[0]:=X86_64_INTEGER_CLASS;
begin
classes[0].typ:=X86_64_INTEGER_CLASS;
classes[0].def:=s64inttype;
end;
X86_64_SSESF_CLASS:
classes[0]:=X86_64_SSE_CLASS;
begin
classes[0].typ:=X86_64_SSE_CLASS;
classes[0].def:=getarraydef(s32floattype,2);
end;
end;
{ 2) the second part is 32 bit, but the total size is > 12 bytes }
if (def.size>12) then
case classes[1] of
case classes[1].typ of
X86_64_INTEGERSI_CLASS:
classes[1]:=X86_64_INTEGER_CLASS;
begin
classes[1].typ:=X86_64_INTEGER_CLASS;
classes[1].def:=s64inttype;
end;
X86_64_SSESF_CLASS:
classes[1]:=X86_64_SSE_CLASS;
begin
classes[1].typ:=X86_64_SSE_CLASS;
classes[1].def:=getarraydef(s32floattype,2);
end;
end;
result:=words;
@ -466,44 +579,51 @@ unit cpupara;
enumdef,
pointerdef,
classrefdef:
result:=classify_as_integer_argument(real_size,classes,byte_offset);
result:=classify_as_integer_argument(def,real_size,classes,byte_offset);
formaldef:
result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset);
result:=classify_as_integer_argument(voidpointertype,voidpointertype.size,classes,byte_offset);
floatdef:
begin
classes[0].def:=def;
case tfloatdef(def).floattype of
s32real:
begin
if byte_offset=0 then
classes[0]:=X86_64_SSESF_CLASS
classes[0].typ:=X86_64_SSESF_CLASS
else
{ if we have e.g. a record with two successive "single"
fields, we need a 64 bit rather than a 32 bit load }
classes[0]:=X86_64_SSE_CLASS;
begin
{ if we have e.g. a record with two successive "single"
fields, we need a 64 bit rather than a 32 bit load }
classes[0].typ:=X86_64_SSE_CLASS;
classes[0].def:=getarraydef(s32floattype,2);
end;
result:=1;
end;
s64real:
begin
classes[0]:=X86_64_SSEDF_CLASS;
classes[0].typ:=X86_64_SSEDF_CLASS;
result:=1;
end;
s80real,
sc80real:
begin
classes[0]:=X86_64_X87_CLASS;
classes[1]:=X86_64_X87UP_CLASS;
classes[0].typ:=X86_64_X87_CLASS;
classes[1].typ:=X86_64_X87UP_CLASS;
classes[1].def:=def;
result:=2;
end;
s64comp,
s64currency:
begin
classes[0]:=X86_64_INTEGER_CLASS;
classes[0].typ:=X86_64_INTEGER_CLASS;
result:=1;
end;
s128real:
begin
classes[0]:=X86_64_SSE_CLASS;
classes[1]:=X86_64_SSEUP_CLASS;
classes[0].typ:=X86_64_SSE_CLASS;
classes[0].def:=getarraydef(s32floattype,2);
classes[1].typ:=X86_64_SSEUP_CLASS;
classes[1].def:=getarraydef(s32floattype,2);
result:=2;
end;
else
@ -519,12 +639,12 @@ unit cpupara;
result:=0
else
{ all kinds of pointer types: class, objcclass, interface, ... }
result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset);
result:=classify_as_integer_argument(def,voidpointertype.size,classes,byte_offset);
end;
setdef:
begin
if is_smallset(def) then
result:=classify_as_integer_argument(def.size,classes,byte_offset)
result:=classify_as_integer_argument(def,def.size,classes,byte_offset)
else
result:=0;
end;
@ -533,13 +653,13 @@ unit cpupara;
if (tstringdef(def).stringtype in [st_shortstring,st_longstring]) then
result:=0
else
result:=classify_as_integer_argument(def.size,classes,byte_offset);
result:=classify_as_integer_argument(def,def.size,classes,byte_offset);
end;
arraydef:
begin
{ a dynamic array is treated like a pointer }
if is_dynamic_array(def) then
result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset)
result:=classify_as_integer_argument(def,voidpointertype.size,classes,byte_offset)
{ other special arrays are passed on the stack }
else if is_open_array(def) or
is_array_of_const(def) then
@ -561,7 +681,7 @@ unit cpupara;
end
else
{ pointer }
result:=classify_as_integer_argument(def.size,classes,byte_offset);
result:=classify_as_integer_argument(def,def.size,classes,byte_offset);
end;
variantdef:
begin
@ -585,7 +705,10 @@ unit cpupara;
{ init the classes array, because even if classify_argument inits only
one element we copy both to loc1/loc2 in case "1" is returned }
for i:=low(classes) to high(classes) do
classes[i]:=X86_64_NO_CLASS;
begin
classes[i].typ:=X86_64_NO_CLASS;
classes[i].def:=nil;
end;
{ def.size internalerrors for open arrays and dynamic arrays, since
their size cannot be determined at compile-time.
classify_argument does not look at the realsize argument for arrays
@ -598,16 +721,17 @@ unit cpupara;
case numclasses of
0:
begin
loc1:=X86_64_MEMORY_CLASS;
loc2:=X86_64_NO_CLASS;
loc1.typ:=X86_64_MEMORY_CLASS;
loc1.def:=def;
loc2.typ:=X86_64_NO_CLASS;
end;
1,2:
begin
{ If the class is X87, X87UP or COMPLEX_X87, it is passed in memory }
if classes[0] in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
classes[0]:=X86_64_MEMORY_CLASS;
if classes[1] in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
classes[1]:=X86_64_MEMORY_CLASS;
if classes[0].typ in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
classes[0].typ:=X86_64_MEMORY_CLASS;
if classes[1].typ in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
classes[1].typ:=X86_64_MEMORY_CLASS;
loc1:=classes[0];
loc2:=classes[1];
end
@ -625,6 +749,7 @@ unit cpupara;
begin
if handle_common_ret_in_param(def,pd,result) then
exit;
fillchar(classes,sizeof(classes),0);
case def.typ of
{ for records it depends on their contents and size }
recorddef,
@ -667,6 +792,7 @@ unit cpupara;
classes: tx64paraclasses;
numclasses: longint;
begin
fillchar(classes,sizeof(classes),0);
result:=false;
{ var,out,constref always require address }
if varspez in [vs_var,vs_out,vs_constref] then
@ -766,18 +892,23 @@ unit cpupara;
procedure tx86_64paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
def : tdef;
psym : tparavarsym;
pdef : tdef;
begin
def:=tparavarsym(pd.paras[nr-1]).vardef;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=getpointerdef(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(def);
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=get_para_align(pd.proccalloption);
cgpara.def:=def;
cgpara.def:=pdef;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
size:=OS_INT;
size:=def_cgsize(pdef);
paraloc^.def:=pdef;
if target_info.system=system_x86_64_win64 then
begin
if nr<1 then
@ -785,7 +916,7 @@ unit cpupara;
else if nr<=high(paraintsupregs_winx64)+1 then
begin
loc:=LOC_REGISTER;
register:=newreg(R_INTREGISTER,paraintsupregs_winx64[nr-1],R_SUBWHOLE);
register:=newreg(R_INTREGISTER,paraintsupregs_winx64[nr-1],cgsize2subreg(R_INTREGISTER,size));
end
else
begin
@ -801,7 +932,7 @@ unit cpupara;
else if nr<=high(paraintsupregs)+1 then
begin
loc:=LOC_REGISTER;
register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],R_SUBWHOLE);
register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],cgsize2subreg(R_INTREGISTER,size));
end
else
begin
@ -847,6 +978,7 @@ unit cpupara;
if result.def.typ=floatdef then
begin
paraloc:=result.add_location;
paraloc^.def:=result.def;
case tfloatdef(result.def).floattype of
s32real:
begin
@ -878,6 +1010,7 @@ unit cpupara;
else
{ Return in register }
begin
fillchar(classes,sizeof(classes),0);
numclasses:=classify_argument(result.def,vs_value,result.def.size,classes,0);
{ this would mean a memory return }
if (numclasses=0) then
@ -890,18 +1023,30 @@ unit cpupara;
for i:=0 to numclasses-1 do
begin
paraloc:=result.add_location;
case classes[i] of
paraloc^.def:=classes[i].def;
case classes[i].typ of
X86_64_INTEGERSI_CLASS,
X86_64_INTEGER_CLASS:
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=intretregs[intretregidx];
if classes[i]=X86_64_INTEGER_CLASS then
paraloc^.size:=OS_64
if classes[i].typ=X86_64_INTEGER_CLASS then
begin
paraloc^.size:=OS_64;
if paraloc^.def.size<>8 then
paraloc^.def:=u64inttype;
end
else if result.intsize in [1,2,4] then
paraloc^.size:=retcgsize
begin
paraloc^.size:=retcgsize;
paraloc^.def:=result.def;
end
else
paraloc^.size:=OS_32;
begin
paraloc^.size:=OS_32;
if paraloc^.def.size<>4 then
paraloc^.def:=u32inttype;
end;
setsubreg(paraloc^.register,cgsize2subreg(R_INTREGISTER,paraloc^.size));
inc(intretregidx);
end;
@ -912,7 +1057,7 @@ unit cpupara;
begin
paraloc^.loc:=LOC_MMREGISTER;
paraloc^.register:=mmretregs[mmretregidx];
case classes[i] of
case classes[i].typ of
X86_64_SSESF_CLASS:
begin
setsubreg(paraloc^.register,R_SUBMMS);
@ -938,6 +1083,7 @@ unit cpupara;
(numclasses<>1) then
internalerror(2010060302);
paraloc^.loc:=LOC_VOID;
paraloc^.def:=voidtype;
end;
else
internalerror(2010021504);
@ -974,11 +1120,12 @@ unit cpupara;
pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
if pushaddr then
begin
loc[1]:=X86_64_INTEGER_CLASS;
loc[2]:=X86_64_NO_CLASS;
loc[1].typ:=X86_64_INTEGER_CLASS;
loc[2].typ:=X86_64_NO_CLASS;
paracgsize:=OS_ADDR;
paralen:=sizeof(pint);
paradef:=getpointerdef(paradef);
loc[1].def:=paradef;
end
else
begin
@ -993,6 +1140,7 @@ unit cpupara;
paracgsize:=OS_S32;
paralen:=4;
paradef:=s32inttype;
loc[1].def:=paradef;
end;
end;
@ -1001,19 +1149,20 @@ unit cpupara;
(target_info.system = system_x86_64_win64) and
(paradef.typ = floatdef) then
begin
loc[2]:=X86_64_NO_CLASS;
loc[2].typ:=X86_64_NO_CLASS;
if paracgsize=OS_F64 then
begin
loc[1]:=X86_64_INTEGER_CLASS;
loc[1].typ:=X86_64_INTEGER_CLASS;
paracgsize:=OS_64;
paradef:=u64inttype;
end
else
begin
loc[1]:=X86_64_INTEGERSI_CLASS;
loc[1].typ:=X86_64_INTEGERSI_CLASS;
paracgsize:=OS_32;
paradef:=u32inttype;
end;
loc[1].def:=paradef;
end;
hp.paraloc[side].reset;
@ -1027,7 +1176,7 @@ unit cpupara;
needintloc:=0;
needmmloc:=0;
for locidx:=low(loc) to high(loc) do
case loc[locidx] of
case loc[locidx].typ of
X86_64_INTEGER_CLASS,
X86_64_INTEGERSI_CLASS:
inc(needintloc);
@ -1048,9 +1197,10 @@ unit cpupara;
{ If there are no registers available for any
eightbyte of an argument, the whole argument is
passed on the stack. }
loc[low(loc)]:=X86_64_MEMORY_CLASS;
loc[low(loc)].typ:=X86_64_MEMORY_CLASS;
loc[low(loc)].def:=paradef;
for locidx:=succ(low(loc)) to high(loc) do
loc[locidx]:=X86_64_NO_CLASS;
loc[locidx].typ:=X86_64_NO_CLASS;
end;
locidx:=1;
@ -1059,31 +1209,38 @@ unit cpupara;
if locidx>2 then
internalerror(200501283);
{ Allocate }
case loc[locidx] of
case loc[locidx].typ of
X86_64_INTEGER_CLASS,
X86_64_INTEGERSI_CLASS:
begin
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc:=LOC_REGISTER;
if (paracgsize=OS_NO) or (loc[2]<>X86_64_NO_CLASS) then
paraloc^.def:=loc[locidx].def;
if (paracgsize=OS_NO) or (loc[2].typ<>X86_64_NO_CLASS) then
begin
if loc[locidx]=X86_64_INTEGER_CLASS then
if loc[locidx].typ=X86_64_INTEGER_CLASS then
begin
paraloc^.size:=OS_INT;
paraloc^.def:=u64inttype;
subreg:=R_SUBWHOLE;
end
else
begin
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
subreg:=R_SUBD;
end;
end
else
begin
paraloc^.size:=paracgsize;
paraloc^.def:=paradef;
{ s64comp is pushed in an int register }
if paraloc^.size=OS_C64 then
paraloc^.size:=OS_64;
begin
paraloc^.size:=OS_64;
paraloc^.def:=u64inttype;
end;
subreg:=cgsize2subreg(R_INTREGISTER,paraloc^.size);
end;
@ -1107,8 +1264,9 @@ unit cpupara;
begin
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc:=LOC_MMREGISTER;
paraloc^.def:=loc[locidx].def;
case loc[locidx] of
case loc[locidx].typ of
X86_64_SSESF_CLASS:
begin
subreg:=R_SUBMMS;
@ -1143,6 +1301,7 @@ unit cpupara;
begin
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.def:=loc[locidx].def;
{Hack alert!!! We should modify int_cgsize to handle OS_128,
however, since int_cgsize is called in many places in the
compiler where only a few can already handle OS_128, fixing it
@ -1171,7 +1330,7 @@ unit cpupara;
internalerror(2010053113);
end;
if (locidx<2) and
(loc[locidx+1]<>X86_64_NO_CLASS) then
(loc[locidx+1].typ<>X86_64_NO_CLASS) then
inc(locidx);
end;
end
@ -1179,6 +1338,7 @@ unit cpupara;
begin
paraloc:=hp.paraloc[side].add_location;
paraloc^.loc:=LOC_VOID;
paraloc^.def:=paradef;
end;
end;
{ Register parameters are assigned from left-to-right, but the