+ support for passing records in registers under darwin

* tcgpara now also has an intsize field, which contains the size in
    bytes of the whole parameter
This commit is contained in:
Jonas Maebe 2005-01-10 21:50:05 +00:00
parent e0eb172f4b
commit 9c22d594b0
8 changed files with 338 additions and 175 deletions

View File

@ -192,6 +192,7 @@ unit cpupara;
begin begin
cgpara.reset; cgpara.reset;
cgpara.size:=OS_INT; cgpara.size:=OS_INT;
cgpara.intsize:=tcgsize2size[OS_INT];
cgpara.alignment:=get_para_align(calloption); cgpara.alignment:=get_para_align(calloption);
paraloc:=cgpara.add_location; paraloc:=cgpara.add_location;
with paraloc^ do with paraloc^ do
@ -313,12 +314,16 @@ unit cpupara;
begin begin
hp:=tparavarsym(paras[i]); hp:=tparavarsym(paras[i]);
if push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption) then if push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption) then
paracgsize:=OS_ADDR begin
paracgsize:=OS_ADDR;
hp.paraloc[side].intsize:=tcgsize2size[OS_ADDR];
end
else else
begin begin
paracgsize:=def_cgSize(hp.vartype.def); paracgsize:=def_cgSize(hp.vartype.def);
if paracgsize=OS_NO then if paracgsize=OS_NO then
paracgsize:=OS_ADDR; paracgsize:=OS_ADDR;
hp.paraloc[side].intsize := tcgsize2size[paracgsize];
end; end;
hp.paraloc[side].reset; hp.paraloc[side].reset;
hp.paraloc[side].size:=paracgsize; hp.paraloc[side].size:=paracgsize;
@ -388,9 +393,19 @@ unit cpupara;
hp:=tparavarsym(paras[i]); hp:=tparavarsym(paras[i]);
pushaddr:=push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption); pushaddr:=push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption);
if pushaddr then if pushaddr then
paracgsize:=OS_ADDR begin
paracgsize:=OS_ADDR;
hp.paraloc[side].intsize:=tcgsize2size[OS_ADDR];
end
else else
paracgsize:=def_cgsize(hp.vartype.def); begin
paracgsize:=def_cgSize(hp.vartype.def);
hp.paraloc[side].intsize := hp.vartype.def.size;
if (hp.paraloc[side].intsize = 0) and
{ records can have size 0}
(hp.vartype.def.deftype <> recorddef) then
hp.paraloc[side].intsize := tcgsize2size[OS_ADDR];
end;
is_64bit:=(paracgsize in [OS_64,OS_S64,OS_F64]); is_64bit:=(paracgsize in [OS_64,OS_S64,OS_F64]);
hp.paraloc[side].reset; hp.paraloc[side].reset;
hp.paraloc[side].size:=paracgsize; hp.paraloc[side].size:=paracgsize;
@ -514,7 +529,12 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.60 2004-11-22 22:01:19 peter Revision 1.61 2005-01-10 21:50:05 jonas
+ support for passing records in registers under darwin
* tcgpara now also has an intsize field, which contains the size in
bytes of the whole parameter
Revision 1.60 2004/11/22 22:01:19 peter
* fixed varargs * fixed varargs
* replaced dynarray with tlist * replaced dynarray with tlist

View File

@ -329,7 +329,8 @@ implementation
LOC_CREFERENCE : LOC_CREFERENCE :
begin begin
{$ifndef cpu64bit} {$ifndef cpu64bit}
if left.location.size in [OS_64,OS_S64] then { don't call the cg64 stuff for 8-byte sized records etc }
if is_64bit(left.resulttype.def) then
cg64.a_param64_loc(exprasmlist,left.location,tempcgpara) cg64.a_param64_loc(exprasmlist,left.location,tempcgpara)
else else
{$endif cpu64bit} {$endif cpu64bit}
@ -684,6 +685,7 @@ implementation
ppn : tcgcallparanode; ppn : tcgcallparanode;
callerparaloc, callerparaloc,
tmpparaloc : pcgparalocation; tmpparaloc : pcgparalocation;
sizeleft: aint;
{$ifdef cputargethasfixedstack} {$ifdef cputargethasfixedstack}
htempref, htempref,
href : treference; href : treference;
@ -703,6 +705,7 @@ implementation
{$endif PASS2INLINE} {$endif PASS2INLINE}
paramanager.freeparaloc(exprasmlist,ppn.tempcgpara); paramanager.freeparaloc(exprasmlist,ppn.tempcgpara);
tmpparaloc:=ppn.tempcgpara.location; tmpparaloc:=ppn.tempcgpara.location;
sizeleft:=ppn.tempcgpara.intsize;
callerparaloc:=ppn.parasym.paraloc[callerside].location; callerparaloc:=ppn.parasym.paraloc[callerside].location;
while assigned(callerparaloc) do while assigned(callerparaloc) do
begin begin
@ -745,6 +748,8 @@ implementation
{$endif PASS2INLINE} {$endif PASS2INLINE}
begin begin
{$ifdef cputargethasfixedstack} {$ifdef cputargethasfixedstack}
if (assigned(tmpparaloc^.next)) then
internalerror(20050111);
reference_reset_base(href,callerparaloc^.reference.index,callerparaloc^.reference.offset); reference_reset_base(href,callerparaloc^.reference.index,callerparaloc^.reference.offset);
{ copy parameters in case they were moved to a temp. location because we've a fixed stack } { copy parameters in case they were moved to a temp. location because we've a fixed stack }
case tmpparaloc^.loc of case tmpparaloc^.loc of
@ -753,7 +758,7 @@ implementation
reference_reset_base(htempref,tmpparaloc^.reference.index,tmpparaloc^.reference.offset); reference_reset_base(htempref,tmpparaloc^.reference.index,tmpparaloc^.reference.offset);
{ use concatcopy, because it can also be a float which fails when { use concatcopy, because it can also be a float which fails when
load_ref_ref is used } load_ref_ref is used }
cg.g_concatcopy(exprasmlist,htempref,href,tcgsize2size[tmpparaloc^.size]); cg.g_concatcopy(exprasmlist,htempref,href,sizeleft);
end; end;
LOC_REGISTER: LOC_REGISTER:
cg.a_load_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href); cg.a_load_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
@ -768,6 +773,7 @@ implementation
end; end;
end; end;
end; end;
dec(sizeleft,tcgsize2size[tmpparaloc^.size]);
callerparaloc:=callerparaloc^.next; callerparaloc:=callerparaloc^.next;
tmpparaloc:=tmpparaloc^.next; tmpparaloc:=tmpparaloc^.next;
end; end;
@ -1256,7 +1262,12 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.193 2005-01-07 16:22:54 florian Revision 1.194 2005-01-10 21:50:05 jonas
+ support for passing records in registers under darwin
* tcgpara now also has an intsize field, which contains the size in
bytes of the whole parameter
Revision 1.193 2005/01/07 16:22:54 florian
+ implemented abi compliant handling of strucutured functions results on sparc platform + implemented abi compliant handling of strucutured functions results on sparc platform
Revision 1.192 2005/01/04 16:36:51 peter Revision 1.192 2005/01/04 16:36:51 peter

View File

@ -1267,7 +1267,7 @@ implementation
end; end;
procedure gen_load_ref(const paraloc:TCGParaLocation;const ref:treference); procedure gen_load_ref(const paraloc:TCGParaLocation;const ref:treference;sizeleft:aint);
var var
href : treference; href : treference;
begin begin
@ -1284,7 +1284,7 @@ implementation
{ use concatcopy, because it can also be a float which fails when { use concatcopy, because it can also be a float which fails when
load_ref_ref is used. Don't copy data when the references are equal } load_ref_ref is used. Don't copy data when the references are equal }
if not((href.base=ref.base) and (href.offset=ref.offset)) then if not((href.base=ref.base) and (href.offset=ref.offset)) then
cg.g_concatcopy(list,href,ref,tcgsize2size[paraloc.size]); cg.g_concatcopy(list,href,ref,sizeleft);
end; end;
else else
internalerror(2002081302); internalerror(2002081302);
@ -1323,7 +1323,7 @@ implementation
end; end;
var var
i : integer; i, sizeleft : aint;
currpara : tparavarsym; currpara : tparavarsym;
paraloc : pcgparalocation; paraloc : pcgparalocation;
{$ifdef sparc} {$ifdef sparc}
@ -1339,6 +1339,7 @@ implementation
begin begin
currpara:=tparavarsym(current_procinfo.procdef.paras[i]); currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
paraloc:=currpara.paraloc[calleeside].location; paraloc:=currpara.paraloc[calleeside].location;
sizeleft:=currpara.paraloc[calleeside].intsize;
while assigned(paraloc) do while assigned(paraloc) do
begin begin
if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then
@ -1352,6 +1353,7 @@ implementation
begin begin
currpara:=tparavarsym(current_procinfo.procdef.paras[i]); currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
paraloc:=currpara.paraloc[calleeside].location; paraloc:=currpara.paraloc[calleeside].location;
sizeleft:=currpara.paraloc[calleeside].intsize;
if not assigned(paraloc) then if not assigned(paraloc) then
internalerror(200408203); internalerror(200408203);
case currpara.localloc.loc of case currpara.localloc.loc of
@ -1361,8 +1363,9 @@ implementation
while assigned(paraloc) do while assigned(paraloc) do
begin begin
unget_para(paraloc^); unget_para(paraloc^);
gen_load_ref(paraloc^,href); gen_load_ref(paraloc^,href,sizeleft);
inc(href.offset,TCGSize2Size[paraloc^.size]); inc(href.offset,TCGSize2Size[paraloc^.size]);
dec(sizeleft,TCGSize2Size[paraloc^.size]);
paraloc:=paraloc^.next; paraloc:=paraloc^.next;
end; end;
end; end;
@ -1422,13 +1425,15 @@ implementation
{$ifdef sparc} {$ifdef sparc}
{ Sparc passes floats in int registers, when loading to fpu register { Sparc passes floats in int registers, when loading to fpu register
we need a temp } we need a temp }
tg.GetTemp(list,TCGSize2Size[currpara.localloc.size],tt_normal,tempref); sizeleft := TCGSize2Size[currpara.localloc.size];
tg.GetTemp(list,sizeleft,tt_normal,tempref);
href:=tempref; href:=tempref;
while assigned(paraloc) do while assigned(paraloc) do
begin begin
unget_para(paraloc^); unget_para(paraloc^);
gen_load_ref(paraloc^,href); gen_load_ref(paraloc^,href,sizeleft);
inc(href.offset,TCGSize2Size[paraloc^.size]); inc(href.offset,TCGSize2Size[paraloc^.size]);
dec(sizeleft,TCGSize2Size[paraloc^.size]);
paraloc:=paraloc^.next; paraloc:=paraloc^.next;
end; end;
cg.a_loadfpu_ref_reg(list,currpara.localloc.size,tempref,currpara.localloc.register); cg.a_loadfpu_ref_reg(list,currpara.localloc.size,tempref,currpara.localloc.register);
@ -2341,7 +2346,12 @@ implementation
end. end.
{ {
$Log$ $Log$
Revision 1.251 2005-01-03 22:27:56 peter Revision 1.252 2005-01-10 21:50:05 jonas
+ support for passing records in registers under darwin
* tcgpara now also has an intsize field, which contains the size in
bytes of the whole parameter
Revision 1.251 2005/01/03 22:27:56 peter
* insert stack_check helper call before doing register allocation * insert stack_check helper call before doing register allocation
so the used registers can't be reused when parameters are loaded so the used registers can't be reused when parameters are loaded
into register variables into register variables

View File

@ -54,6 +54,10 @@ unit parabase;
Location : PCGParalocation; Location : PCGParalocation;
Alignment : ShortInt; Alignment : ShortInt;
Size : TCGSize; { Size of the parameter included in all locations } Size : TCGSize; { Size of the parameter included in all locations }
IntSize: aint; { size of the total location in bytes }
{$ifdef powerpc}
composite: boolean; { under the AIX abi, how certain parameters are passed depends on whether they are composite or not }
{$endif powerpc}
constructor init; constructor init;
destructor done; destructor done;
procedure reset; procedure reset;
@ -97,7 +101,11 @@ implementation
begin begin
alignment:=0; alignment:=0;
size:=OS_NO; size:=OS_NO;
intsize:=0;
location:=nil; location:=nil;
{$ifdef powerpc}
composite:=false;
{$endif powerpc}
end; end;
@ -119,6 +127,10 @@ implementation
end; end;
alignment:=0; alignment:=0;
size:=OS_NO; size:=OS_NO;
intsize:=0;
{$ifdef powerpc}
composite:=false;
{$endif powerpc}
end; end;
@ -136,6 +148,10 @@ implementation
end; end;
result.alignment:=alignment; result.alignment:=alignment;
result.size:=size; result.size:=size;
result.intsize:=intsize;
{$ifdef powerpc}
result.composite:=composite;
{$endif powerpc}
end; end;
@ -251,7 +267,12 @@ end.
{ {
$Log$ $Log$
Revision 1.7 2005-01-07 16:22:54 florian Revision 1.8 2005-01-10 21:50:05 jonas
+ support for passing records in registers under darwin
* tcgpara now also has an intsize field, which contains the size in
bytes of the whole parameter
Revision 1.7 2005/01/07 16:22:54 florian
+ implemented abi compliant handling of strucutured functions results on sparc platform + implemented abi compliant handling of strucutured functions results on sparc platform
Revision 1.6 2004/11/22 22:01:19 peter Revision 1.6 2004/11/22 22:01:19 peter

View File

@ -379,7 +379,11 @@ implementation
begin begin
cgpara.reset; cgpara.reset;
cgpara.size:=parasym.paraloc[callerside].size; cgpara.size:=parasym.paraloc[callerside].size;
cgpara.intsize:=parasym.paraloc[callerside].intsize;
cgpara.alignment:=parasym.paraloc[callerside].alignment; cgpara.alignment:=parasym.paraloc[callerside].alignment;
{$ifdef powerpc}
cgpara.composite:=parasym.paraloc[callerside].composite;
{$endif powerpc}
paraloc:=parasym.paraloc[callerside].location; paraloc:=parasym.paraloc[callerside].location;
while assigned(paraloc) do while assigned(paraloc) do
begin begin
@ -423,7 +427,11 @@ implementation
begin begin
cgpara.reset; cgpara.reset;
cgpara.size:=parasym.paraloc[callerside].size; cgpara.size:=parasym.paraloc[callerside].size;
cgpara.intsize:=parasym.paraloc[callerside].intsize;
cgpara.alignment:=parasym.paraloc[callerside].alignment; cgpara.alignment:=parasym.paraloc[callerside].alignment;
{$ifdef powerpc}
cgpara.composite:=parasym.paraloc[callerside].composite;
{$endif powerpc}
paraloc:=parasym.paraloc[callerside].location; paraloc:=parasym.paraloc[callerside].location;
while assigned(paraloc) do while assigned(paraloc) do
begin begin
@ -451,7 +459,12 @@ end.
{ {
$Log$ $Log$
Revision 1.82 2004-11-21 17:17:03 florian Revision 1.83 2005-01-10 21:50:05 jonas
+ support for passing records in registers under darwin
* tcgpara now also has an intsize field, which contains the size in
bytes of the whole parameter
Revision 1.82 2004/11/21 17:17:03 florian
* changed funcret location back to tlocation * changed funcret location back to tlocation
Revision 1.81 2004/11/15 23:35:31 peter Revision 1.81 2004/11/15 23:35:31 peter

View File

@ -244,31 +244,90 @@ const
procedure tcgppc.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : tcgpara); procedure tcgppc.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : tcgpara);
var var
ref: treference; tmpref, ref: treference;
tmpreg: tregister; location: pcgparalocation;
sizeleft: aint;
begin begin
paraloc.check_simple_location; location := paraloc.location;
case paraloc.location^.loc of tmpref := r;
LOC_REGISTER,LOC_CREGISTER: sizeleft := paraloc.intsize;
a_load_ref_reg(list,size,size,r,paraloc.location^.register); while assigned(location) do
LOC_REFERENCE: begin
begin case location^.loc of
reference_reset_base(ref,paraloc.location^.reference.index,paraloc.location^.reference.offset); LOC_REGISTER,LOC_CREGISTER:
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE); begin
a_load_ref_reg(list,size,size,r,tmpreg); {$ifndef cpu64bit}
a_load_reg_ref(list,size,size,tmpreg,ref); if (sizeleft <> 3) then
begin
a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
{ the following is only for AIX abi systems, but the }
{ conditions should never be true for SYSV (if they }
{ are, there is a bug in cpupara) }
{ update: this doesn't work yet (we have to shift }
{ right again in ncgutil when storing the parameters, }
{ and additionally Apple's documentation seems to be }
{ wrong, in that these values are always kept in the }
{ lower bytes of the registers }
{
if (paraloc.composite) and
(sizeleft <= 2) and
((paraloc.intsize > 4) or
(target_info.system <> system_powerpc_darwin)) then
begin
case sizeleft of
1:
a_op_const_reg(list,OP_SHL,OS_INT,24,location^.register);
2:
a_op_const_reg(list,OP_SHL,OS_INT,16,location^.register);
else
internalerror(2005010910);
end;
end;
}
end
else
begin
a_load_ref_reg(list,OS_16,OS_16,tmpref,location^.register);
a_reg_alloc(list,NR_R0);
inc(tmpref.offset,2);
a_load_ref_reg(list,OS_8,OS_8,tmpref,newreg(R_INTREGISTER,RS_R0,R_SUBNONE));
a_op_const_reg(list,OP_SHL,OS_INT,16,location^.register);
list.concat(taicpu.op_reg_reg_const_const_const(A_RLWIMI,location^.register,newreg(R_INTREGISTER,RS_R0,R_SUBNONE),8,16,31-8));
a_reg_dealloc(list,NR_R0);
dec(tmpref.offset,2);
end;
{$else not cpu64bit}
{$error add 64 bit support for non power of 2 loads in a_param_ref}
{$endif not cpu64bit}
end;
LOC_REFERENCE:
begin
reference_reset_base(ref,location^.reference.index,location^.reference.offset);
g_concatcopy(list,tmpref,ref,sizeleft);
if assigned(location^.next) then
internalerror(2005010710);
end;
LOC_FPUREGISTER,LOC_CFPUREGISTER:
case location^.size of
OS_F32, OS_F64:
a_loadfpu_ref_reg(list,location^.size,tmpref,location^.register);
else
internalerror(2002072801);
end;
LOC_VOID:
begin
// nothing to do
end;
else
internalerror(2002081103);
end; end;
LOC_FPUREGISTER,LOC_CFPUREGISTER: inc(tmpref.offset,tcgsize2size[location^.size]);
case size of dec(sizeleft,tcgsize2size[location^.size]);
OS_F32, OS_F64: location := location^.next;
a_loadfpu_ref_reg(list,size,r,paraloc.location^.register); end;
else
internalerror(2002072801);
end;
else
internalerror(2002081103);
end;
end; end;
@ -2299,7 +2358,12 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.190 2005-01-05 19:01:53 karoly Revision 1.191 2005-01-10 21:50:05 jonas
+ support for passing records in registers under darwin
* tcgpara now also has an intsize field, which contains the size in
bytes of the whole parameter
Revision 1.190 2005/01/05 19:01:53 karoly
* sysv abi also uses F0-F13 as volatile registers * sysv abi also uses F0-F13 as volatile registers
Revision 1.189 2004/12/24 11:51:55 jonas Revision 1.189 2004/12/24 11:51:55 jonas

View File

@ -42,8 +42,9 @@ unit cpupara;
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override; procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
// function copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; override;
private private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword); procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist; function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
@ -86,6 +87,7 @@ unit cpupara;
begin begin
cgpara.reset; cgpara.reset;
cgpara.size:=OS_INT; cgpara.size:=OS_INT;
cgpara.intsize:=tcgsize2size[OS_INT];
cgpara.alignment:=get_para_align(calloption); cgpara.alignment:=get_para_align(calloption);
paraloc:=cgpara.add_location; paraloc:=cgpara.add_location;
with paraloc^ do with paraloc^ do
@ -102,7 +104,10 @@ unit cpupara;
begin begin
loc:=LOC_REFERENCE; loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG; paraloc^.reference.index:=NR_STACK_POINTER_REG;
reference.offset:=sizeof(aint)*(nr-8); if (target_info.abi <> abi_powerpc_aix) then
reference.offset:=sizeof(aint)*(nr-8)
else
reference.offset:=sizeof(aint)*(nr);
end; end;
end; end;
end; end;
@ -129,7 +134,10 @@ unit cpupara;
classrefdef: classrefdef:
result:=LOC_REGISTER; result:=LOC_REGISTER;
recorddef: recorddef:
result:=LOC_REFERENCE; if (target_info.abi<>abi_powerpc_aix) then
result:=LOC_REFERENCE
else
result:=LOC_REGISTER;
objectdef: objectdef:
if is_object(p) then if is_object(p) then
result:=LOC_REFERENCE result:=LOC_REFERENCE
@ -166,8 +174,6 @@ unit cpupara;
function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
var
size, dummy: aint;
begin begin
{ var,out always require address } { var,out always require address }
if varspez in [vs_var,vs_out] then if varspez in [vs_var,vs_out] then
@ -177,18 +183,7 @@ unit cpupara;
end; end;
case def.deftype of case def.deftype of
recorddef: recorddef:
begin result :=(target_info.abi<>abi_powerpc_aix);
if (target_info.abi = abi_powerpc_aix) then
begin
// all records should be passed by value under the aix abi,
// but we can only fake this for 1, 2 and 4 bytes for now
size := def.size;
result := (size > 4) or
not(byte(size) in [1,2,4]);
end
else
result := true;
end;
arraydef: arraydef:
result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
is_open_array(def) or is_open_array(def) or
@ -221,6 +216,14 @@ unit cpupara;
curmmreg:=RS_M1; curmmreg:=RS_M1;
end; end;
{
function tppcparamanager.copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
begin
result := false;
if (target_info.abi <> abi_powerpc_aix) then
result := inherited copy_value_on_stack(varspez,def,calloption);
end;
}
procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
var var
@ -304,7 +307,8 @@ unit cpupara;
function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist; function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
var var
stack_offset: aword; stack_offset, parasize: longint;
paralen: aint;
nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister; nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
paradef : tdef; paradef : tdef;
paraloc,paraloc2 : pcgparalocation; paraloc,paraloc2 : pcgparalocation;
@ -312,8 +316,9 @@ unit cpupara;
hp : tparavarsym; hp : tparavarsym;
loc : tcgloc; loc : tcgloc;
paracgsize: tcgsize; paracgsize: tcgsize;
is_64bit: boolean; def64bit: boolean;
(*
procedure assignintreg; procedure assignintreg;
begin begin
@ -336,6 +341,7 @@ unit cpupara;
inc(stack_offset,4); inc(stack_offset,4);
end; end;
end; end;
*)
begin begin
{$ifdef extdebug} {$ifdef extdebug}
@ -348,6 +354,7 @@ unit cpupara;
nextfloatreg := curfloatreg; nextfloatreg := curfloatreg;
nextmmreg := curmmreg; nextmmreg := curmmreg;
stack_offset := cur_stack_offset; stack_offset := cur_stack_offset;
parasize := cur_stack_offset;
case target_info.abi of case target_info.abi of
abi_powerpc_aix: abi_powerpc_aix:
maxfpureg := RS_F13; maxfpureg := RS_F13;
@ -359,6 +366,7 @@ unit cpupara;
for i:=0 to paras.count-1 do for i:=0 to paras.count-1 do
begin begin
hp:=tparavarsym(paras[i]); hp:=tparavarsym(paras[i]);
paradef := hp.vartype.def;
{ Syscall for Morphos can have already a paraloc set } { Syscall for Morphos can have already a paraloc set }
if (vo_has_explicit_paraloc in hp.varoptions) then if (vo_has_explicit_paraloc in hp.varoptions) then
begin begin
@ -369,7 +377,7 @@ unit cpupara;
hp.paraloc[side].reset; hp.paraloc[side].reset;
{ currently only support C-style array of const } { currently only support C-style array of const }
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
is_array_of_const(hp.vartype.def) then is_array_of_const(paradef) then
begin begin
paraloc:=hp.paraloc[side].add_location; paraloc:=hp.paraloc[side].add_location;
{ hack: the paraloc must be valid, but is not actually used } { hack: the paraloc must be valid, but is not actually used }
@ -379,146 +387,144 @@ unit cpupara;
break; break;
end; end;
if (hp.varspez in [vs_var,vs_out]) then if (hp.varspez in [vs_var,vs_out]) or
push_addr_param(hp.varspez,paradef,p.proccalloption) or
is_open_array(paradef) or
is_array_of_const(paradef) then
begin begin
paradef:=voidpointertype.def; paradef:=voidpointertype.def;
loc:=LOC_REGISTER; loc:=LOC_REGISTER;
paracgsize := OS_ADDR; paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
end end
else else
begin begin
paradef := hp.vartype.def; if not is_special_array(paradef) then
loc:=getparaloc(paradef); paralen := paradef.size
if (hp.vartype.def.deftype = recorddef) and else
(target_info.abi = abi_powerpc_aix) and paralen := tcgsize2size[def_cgsize(paradef)];
(hp.vartype.def.size <= 4) and if (target_info.abi = abi_powerpc_aix) and
(byte(hp.vartype.def.size) in [1,2,4]) then (paradef.deftype = recorddef) and
(hp.varspez in [vs_value,vs_const]) then
begin begin
loc := LOC_REGISTER; { if a record has only one field and that field is }
paracgsize := def_cgsize(paradef); { non-composite (not array or record), it must be }
{ passed according to the rules of that type. }
if (trecorddef(hp.vartype.def).symtable.symindex.count = 1) and
((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
((target_info.system = system_powerpc_darwin) and
(tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
begin
paradef :=
tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
loc := getparaloc(paradef);
paracgsize:=def_cgsize(paradef);
end
else
begin
loc := LOC_REGISTER;
paracgsize := int_cgsize(paralen);
end;
end end
else else
begin begin
loc:=getparaloc(paradef);
paracgsize:=def_cgsize(paradef); paracgsize:=def_cgsize(paradef);
{ for things like formaldef } { for things like formaldef }
if paracgsize=OS_NO then if (paracgsize=OS_NO) then
paracgsize:=OS_ADDR; begin
end paracgsize:=OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
end;
end
end; end;
hp.paraloc[side].alignment:=std_param_align; hp.paraloc[side].alignment:=std_param_align;
hp.paraloc[side].size:=paracgsize; hp.paraloc[side].size:=paracgsize;
{ First location } hp.paraloc[side].intsize:=paralen;
paraloc:=hp.paraloc[side].add_location; if (target_info.abi = abi_powerpc_aix) and
paraloc^.size:=paracgsize; (paradef.deftype = recorddef) then
case loc of hp.paraloc[side].composite:=true;
LOC_REGISTER:
begin
is_64bit:=paraloc^.size in [OS_64,OS_S64];
if nextintreg<=(RS_R10-ord(is_64bit)) then
begin
paraloc^.loc:=LOC_REGISTER;
{$ifndef cpu64bit} {$ifndef cpu64bit}
if is_64bit then if (target_info.abi=abi_powerpc_sysv) and
begin is_64bit(paradef) and
if odd(nextintreg-RS_R3) and (target_info.abi=abi_powerpc_sysv) Then odd(nextintreg-RS_R3) then
inc(nextintreg); inc(nextintreg);
paraloc^.size:=OS_32; {$endif not cpu64bit}
paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE); { can become < 0 for e.g. 3-byte records }
inc(nextintreg); while (paralen > 0) do
paraloc2:=hp.paraloc[side].add_location; begin
paraloc2^.loc:=LOC_REGISTER; paraloc:=hp.paraloc[side].add_location;
paraloc2^.size:=OS_32; if (loc = LOC_REGISTER) and
paraloc2^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE); (nextintreg <= RS_R10) then
inc(nextintreg); begin
if target_info.abi=abi_powerpc_aix then paraloc^.loc := loc;
inc(stack_offset,8); paracgsize := int_cgsize(paralen);
end if (paracgsize in [OS_NO,OS_64,OS_S64]) then
else paraloc^.size := OS_INT
{$endif cpu64bit}
begin
paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
inc(nextintreg);
if target_info.abi=abi_powerpc_aix then
inc(stack_offset,sizeof(aword));
end;
end
else else
begin paraloc^.size := paracgsize;
nextintreg:=RS_R11; paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
paraloc^.loc:=LOC_REFERENCE; inc(nextintreg);
if (side = callerside) then dec(paralen,tcgsize2size[paraloc^.size]);
paraloc^.reference.index:=NR_STACK_POINTER_REG inc(parasize,tcgsize2size[paraloc^.size]);
else
paraloc^.reference.index:=NR_R12;
paraloc^.reference.offset:=stack_offset;
if not is_64bit then
inc(stack_offset,4)
else
inc(stack_offset,8);
end;
end;
LOC_FPUREGISTER:
begin
if nextfloatreg<=maxfpureg then
begin
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
inc(nextfloatreg);
end
else
begin
paraloc^.loc:=LOC_REFERENCE;
if (side = callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
paraloc^.reference.index:=NR_R12;
paraloc^.reference.offset:=stack_offset;
end;
if target_info.abi=abi_powerpc_aix then if target_info.abi=abi_powerpc_aix then
stack_offset := parasize;
end
else if (loc = LOC_FPUREGISTER) and
(nextfloatreg <= maxfpureg) then
begin
paraloc^.loc:=loc;
paraloc^.size := paracgsize;
paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
inc(nextfloatreg);
dec(paralen,tcgsize2size[paraloc^.size]);
{ if nextfpureg > maxfpureg, all intregs are already used, since there }
{ are less of those available for parameter passing in the AIX abi }
{$ifndef cpu64bit}
if (paracgsize = OS_F32) then
begin begin
if paraloc^.size = OS_F32 then inc(parasize,4);
begin if (nextintreg < RS_R11) then
inc(stack_offset,4); inc(nextintreg);
if (nextintreg < RS_R11) then end
inc(nextintreg);
end
else
begin
inc(stack_offset,8);
if (nextintreg < RS_R10) then
inc(nextintreg,2)
else
nextintreg := RS_R11;
end;
end;
end;
LOC_REFERENCE:
begin
paraloc^.size:=OS_ADDR;
if push_addr_param(hp.varspez,paradef,p.proccalloption) or
is_open_array(paradef) or
is_array_of_const(paradef) then
assignintreg
else else
begin begin
paraloc^.loc:=LOC_REFERENCE; inc(parasize,8);
if (side = callerside) then if (nextintreg < RS_R10) then
paraloc^.reference.index:=NR_STACK_POINTER_REG inc(nextintreg,2)
else else
paraloc^.reference.index:=NR_R12; nextintreg := RS_R11;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,hp.vartype.def.size);
end; end;
end; {$else not cpu64bit}
else begin
internalerror(2002071002); inc(parasize,tcgsize2size[paracgsize]);
end; if (nextintreg < RS_R11) then
end; inc(nextintreg);
end;
{$endif not cpu64bit}
if target_info.abi=abi_powerpc_aix then
stack_offset := parasize;
end
else { LOC_REFERENCE }
begin
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
if (side = callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
paraloc^.reference.index:=NR_R12;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,align(paralen,4));
inc(parasize,align(paralen,4));
paralen := 0;
end;
end;
end;
curintreg:=nextintreg; curintreg:=nextintreg;
curfloatreg:=nextfloatreg; curfloatreg:=nextfloatreg;
curmmreg:=nextmmreg; curmmreg:=nextmmreg;
cur_stack_offset:=stack_offset; cur_stack_offset:=stack_offset;
result:=cur_stack_offset; result:=parasize;
end; end;
@ -537,7 +543,13 @@ unit cpupara;
result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset); result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset) begin
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
{ varargs routines have to reserve at least 32 bytes for the AIX abi }
if (target_info.abi = abi_powerpc_aix) and
(result < 32) then
result := 32;
end
else else
begin begin
parasize:=cur_stack_offset; parasize:=cur_stack_offset;
@ -637,7 +649,12 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.80 2005-01-07 10:58:03 jonas Revision 1.81 2005-01-10 21:50:05 jonas
+ support for passing records in registers under darwin
* tcgpara now also has an intsize field, which contains the size in
bytes of the whole parameter
Revision 1.80 2005/01/07 10:58:03 jonas
* fixed stupid tregister/tsuperregister bug (type checking circumvented * fixed stupid tregister/tsuperregister bug (type checking circumvented
using explicit typecase), caused bug3523 using explicit typecase), caused bug3523

View File

@ -84,6 +84,7 @@ implementation
InternalError(2002100806); InternalError(2002100806);
cgpara.reset; cgpara.reset;
cgpara.size:=OS_INT; cgpara.size:=OS_INT;
cgpara.intsize:=tcgsize2size[OS_INT];
cgpara.alignment:=std_param_align; cgpara.alignment:=std_param_align;
paraloc:=cgpara.add_location; paraloc:=cgpara.add_location;
with paraloc^ do with paraloc^ do
@ -249,6 +250,7 @@ implementation
hp.paraloc[side].size:=paracgsize; hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].Alignment:=std_param_align; hp.paraloc[side].Alignment:=std_param_align;
paralen:=tcgsize2size[paracgsize]; paralen:=tcgsize2size[paracgsize];
hp.paraloc[side].intsize:=paralen;
while paralen>0 do while paralen>0 do
begin begin
paraloc:=hp.paraloc[side].add_location; paraloc:=hp.paraloc[side].add_location;
@ -327,7 +329,12 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.52 2005-01-07 16:22:54 florian Revision 1.53 2005-01-10 21:50:05 jonas
+ support for passing records in registers under darwin
* tcgpara now also has an intsize field, which contains the size in
bytes of the whole parameter
Revision 1.52 2005/01/07 16:22:54 florian
+ implemented abi compliant handling of strucutured functions results on sparc platform + implemented abi compliant handling of strucutured functions results on sparc platform
Revision 1.51 2004/11/22 22:01:19 peter Revision 1.51 2004/11/22 22:01:19 peter