+ 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
cgpara.reset;
cgpara.size:=OS_INT;
cgpara.intsize:=tcgsize2size[OS_INT];
cgpara.alignment:=get_para_align(calloption);
paraloc:=cgpara.add_location;
with paraloc^ do
@ -313,12 +314,16 @@ unit cpupara;
begin
hp:=tparavarsym(paras[i]);
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
begin
paracgsize:=def_cgSize(hp.vartype.def);
if paracgsize=OS_NO then
paracgsize:=OS_ADDR;
hp.paraloc[side].intsize := tcgsize2size[paracgsize];
end;
hp.paraloc[side].reset;
hp.paraloc[side].size:=paracgsize;
@ -388,9 +393,19 @@ unit cpupara;
hp:=tparavarsym(paras[i]);
pushaddr:=push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption);
if pushaddr then
paracgsize:=OS_ADDR
begin
paracgsize:=OS_ADDR;
hp.paraloc[side].intsize:=tcgsize2size[OS_ADDR];
end
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]);
hp.paraloc[side].reset;
hp.paraloc[side].size:=paracgsize;
@ -514,7 +529,12 @@ begin
end.
{
$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
* replaced dynarray with tlist

View File

@ -329,7 +329,8 @@ implementation
LOC_CREFERENCE :
begin
{$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)
else
{$endif cpu64bit}
@ -684,6 +685,7 @@ implementation
ppn : tcgcallparanode;
callerparaloc,
tmpparaloc : pcgparalocation;
sizeleft: aint;
{$ifdef cputargethasfixedstack}
htempref,
href : treference;
@ -703,6 +705,7 @@ implementation
{$endif PASS2INLINE}
paramanager.freeparaloc(exprasmlist,ppn.tempcgpara);
tmpparaloc:=ppn.tempcgpara.location;
sizeleft:=ppn.tempcgpara.intsize;
callerparaloc:=ppn.parasym.paraloc[callerside].location;
while assigned(callerparaloc) do
begin
@ -745,6 +748,8 @@ implementation
{$endif PASS2INLINE}
begin
{$ifdef cputargethasfixedstack}
if (assigned(tmpparaloc^.next)) then
internalerror(20050111);
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 }
case tmpparaloc^.loc of
@ -753,7 +758,7 @@ implementation
reference_reset_base(htempref,tmpparaloc^.reference.index,tmpparaloc^.reference.offset);
{ use concatcopy, because it can also be a float which fails when
load_ref_ref is used }
cg.g_concatcopy(exprasmlist,htempref,href,tcgsize2size[tmpparaloc^.size]);
cg.g_concatcopy(exprasmlist,htempref,href,sizeleft);
end;
LOC_REGISTER:
cg.a_load_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
@ -768,6 +773,7 @@ implementation
end;
end;
end;
dec(sizeleft,tcgsize2size[tmpparaloc^.size]);
callerparaloc:=callerparaloc^.next;
tmpparaloc:=tmpparaloc^.next;
end;
@ -1256,7 +1262,12 @@ begin
end.
{
$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
Revision 1.192 2005/01/04 16:36:51 peter

View File

@ -1267,7 +1267,7 @@ implementation
end;
procedure gen_load_ref(const paraloc:TCGParaLocation;const ref:treference);
procedure gen_load_ref(const paraloc:TCGParaLocation;const ref:treference;sizeleft:aint);
var
href : treference;
begin
@ -1284,7 +1284,7 @@ implementation
{ 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 }
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;
else
internalerror(2002081302);
@ -1323,7 +1323,7 @@ implementation
end;
var
i : integer;
i, sizeleft : aint;
currpara : tparavarsym;
paraloc : pcgparalocation;
{$ifdef sparc}
@ -1339,6 +1339,7 @@ implementation
begin
currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
paraloc:=currpara.paraloc[calleeside].location;
sizeleft:=currpara.paraloc[calleeside].intsize;
while assigned(paraloc) do
begin
if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then
@ -1352,6 +1353,7 @@ implementation
begin
currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
paraloc:=currpara.paraloc[calleeside].location;
sizeleft:=currpara.paraloc[calleeside].intsize;
if not assigned(paraloc) then
internalerror(200408203);
case currpara.localloc.loc of
@ -1361,8 +1363,9 @@ implementation
while assigned(paraloc) do
begin
unget_para(paraloc^);
gen_load_ref(paraloc^,href);
gen_load_ref(paraloc^,href,sizeleft);
inc(href.offset,TCGSize2Size[paraloc^.size]);
dec(sizeleft,TCGSize2Size[paraloc^.size]);
paraloc:=paraloc^.next;
end;
end;
@ -1422,13 +1425,15 @@ implementation
{$ifdef sparc}
{ Sparc passes floats in int registers, when loading to fpu register
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;
while assigned(paraloc) do
begin
unget_para(paraloc^);
gen_load_ref(paraloc^,href);
gen_load_ref(paraloc^,href,sizeleft);
inc(href.offset,TCGSize2Size[paraloc^.size]);
dec(sizeleft,TCGSize2Size[paraloc^.size]);
paraloc:=paraloc^.next;
end;
cg.a_loadfpu_ref_reg(list,currpara.localloc.size,tempref,currpara.localloc.register);
@ -2341,7 +2346,12 @@ implementation
end.
{
$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
so the used registers can't be reused when parameters are loaded
into register variables

View File

@ -54,6 +54,10 @@ unit parabase;
Location : PCGParalocation;
Alignment : ShortInt;
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;
destructor done;
procedure reset;
@ -97,7 +101,11 @@ implementation
begin
alignment:=0;
size:=OS_NO;
intsize:=0;
location:=nil;
{$ifdef powerpc}
composite:=false;
{$endif powerpc}
end;
@ -119,6 +127,10 @@ implementation
end;
alignment:=0;
size:=OS_NO;
intsize:=0;
{$ifdef powerpc}
composite:=false;
{$endif powerpc}
end;
@ -136,6 +148,10 @@ implementation
end;
result.alignment:=alignment;
result.size:=size;
result.intsize:=intsize;
{$ifdef powerpc}
result.composite:=composite;
{$endif powerpc}
end;
@ -251,7 +267,12 @@ end.
{
$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
Revision 1.6 2004/11/22 22:01:19 peter

View File

@ -379,7 +379,11 @@ implementation
begin
cgpara.reset;
cgpara.size:=parasym.paraloc[callerside].size;
cgpara.intsize:=parasym.paraloc[callerside].intsize;
cgpara.alignment:=parasym.paraloc[callerside].alignment;
{$ifdef powerpc}
cgpara.composite:=parasym.paraloc[callerside].composite;
{$endif powerpc}
paraloc:=parasym.paraloc[callerside].location;
while assigned(paraloc) do
begin
@ -423,7 +427,11 @@ implementation
begin
cgpara.reset;
cgpara.size:=parasym.paraloc[callerside].size;
cgpara.intsize:=parasym.paraloc[callerside].intsize;
cgpara.alignment:=parasym.paraloc[callerside].alignment;
{$ifdef powerpc}
cgpara.composite:=parasym.paraloc[callerside].composite;
{$endif powerpc}
paraloc:=parasym.paraloc[callerside].location;
while assigned(paraloc) do
begin
@ -451,7 +459,12 @@ end.
{
$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
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);
var
ref: treference;
tmpreg: tregister;
tmpref, ref: treference;
location: pcgparalocation;
sizeleft: aint;
begin
paraloc.check_simple_location;
case paraloc.location^.loc of
LOC_REGISTER,LOC_CREGISTER:
a_load_ref_reg(list,size,size,r,paraloc.location^.register);
LOC_REFERENCE:
begin
reference_reset_base(ref,paraloc.location^.reference.index,paraloc.location^.reference.offset);
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load_ref_reg(list,size,size,r,tmpreg);
a_load_reg_ref(list,size,size,tmpreg,ref);
location := paraloc.location;
tmpref := r;
sizeleft := paraloc.intsize;
while assigned(location) do
begin
case location^.loc of
LOC_REGISTER,LOC_CREGISTER:
begin
{$ifndef cpu64bit}
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;
LOC_FPUREGISTER,LOC_CFPUREGISTER:
case size of
OS_F32, OS_F64:
a_loadfpu_ref_reg(list,size,r,paraloc.location^.register);
else
internalerror(2002072801);
end;
else
internalerror(2002081103);
end;
inc(tmpref.offset,tcgsize2size[location^.size]);
dec(sizeleft,tcgsize2size[location^.size]);
location := location^.next;
end;
end;
@ -2299,7 +2358,12 @@ begin
end.
{
$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
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;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
// function copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; override;
private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
@ -86,6 +87,7 @@ unit cpupara;
begin
cgpara.reset;
cgpara.size:=OS_INT;
cgpara.intsize:=tcgsize2size[OS_INT];
cgpara.alignment:=get_para_align(calloption);
paraloc:=cgpara.add_location;
with paraloc^ do
@ -102,7 +104,10 @@ unit cpupara;
begin
loc:=LOC_REFERENCE;
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;
@ -129,7 +134,10 @@ unit cpupara;
classrefdef:
result:=LOC_REGISTER;
recorddef:
result:=LOC_REFERENCE;
if (target_info.abi<>abi_powerpc_aix) then
result:=LOC_REFERENCE
else
result:=LOC_REGISTER;
objectdef:
if is_object(p) then
result:=LOC_REFERENCE
@ -166,8 +174,6 @@ unit cpupara;
function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
var
size, dummy: aint;
begin
{ var,out always require address }
if varspez in [vs_var,vs_out] then
@ -177,18 +183,7 @@ unit cpupara;
end;
case def.deftype of
recorddef:
begin
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;
result :=(target_info.abi<>abi_powerpc_aix);
arraydef:
result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
is_open_array(def) or
@ -221,6 +216,14 @@ unit cpupara;
curmmreg:=RS_M1;
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);
var
@ -304,7 +307,8 @@ unit cpupara;
function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
var
stack_offset: aword;
stack_offset, parasize: longint;
paralen: aint;
nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
paradef : tdef;
paraloc,paraloc2 : pcgparalocation;
@ -312,8 +316,9 @@ unit cpupara;
hp : tparavarsym;
loc : tcgloc;
paracgsize: tcgsize;
is_64bit: boolean;
def64bit: boolean;
(*
procedure assignintreg;
begin
@ -336,6 +341,7 @@ unit cpupara;
inc(stack_offset,4);
end;
end;
*)
begin
{$ifdef extdebug}
@ -348,6 +354,7 @@ unit cpupara;
nextfloatreg := curfloatreg;
nextmmreg := curmmreg;
stack_offset := cur_stack_offset;
parasize := cur_stack_offset;
case target_info.abi of
abi_powerpc_aix:
maxfpureg := RS_F13;
@ -359,6 +366,7 @@ unit cpupara;
for i:=0 to paras.count-1 do
begin
hp:=tparavarsym(paras[i]);
paradef := hp.vartype.def;
{ Syscall for Morphos can have already a paraloc set }
if (vo_has_explicit_paraloc in hp.varoptions) then
begin
@ -369,7 +377,7 @@ unit cpupara;
hp.paraloc[side].reset;
{ currently only support C-style array of const }
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
is_array_of_const(hp.vartype.def) then
is_array_of_const(paradef) then
begin
paraloc:=hp.paraloc[side].add_location;
{ hack: the paraloc must be valid, but is not actually used }
@ -379,146 +387,144 @@ unit cpupara;
break;
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
paradef:=voidpointertype.def;
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
end
else
begin
paradef := hp.vartype.def;
loc:=getparaloc(paradef);
if (hp.vartype.def.deftype = recorddef) and
(target_info.abi = abi_powerpc_aix) and
(hp.vartype.def.size <= 4) and
(byte(hp.vartype.def.size) in [1,2,4]) then
if not is_special_array(paradef) then
paralen := paradef.size
else
paralen := tcgsize2size[def_cgsize(paradef)];
if (target_info.abi = abi_powerpc_aix) and
(paradef.deftype = recorddef) and
(hp.varspez in [vs_value,vs_const]) then
begin
loc := LOC_REGISTER;
paracgsize := def_cgsize(paradef);
{ if a record has only one field and that field is }
{ 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
else
begin
loc:=getparaloc(paradef);
paracgsize:=def_cgsize(paradef);
{ for things like formaldef }
if paracgsize=OS_NO then
paracgsize:=OS_ADDR;
end
if (paracgsize=OS_NO) then
begin
paracgsize:=OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
end;
end
end;
hp.paraloc[side].alignment:=std_param_align;
hp.paraloc[side].size:=paracgsize;
{ First location }
paraloc:=hp.paraloc[side].add_location;
paraloc^.size:=paracgsize;
case loc of
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;
hp.paraloc[side].intsize:=paralen;
if (target_info.abi = abi_powerpc_aix) and
(paradef.deftype = recorddef) then
hp.paraloc[side].composite:=true;
{$ifndef cpu64bit}
if is_64bit then
begin
if odd(nextintreg-RS_R3) and (target_info.abi=abi_powerpc_sysv) Then
inc(nextintreg);
paraloc^.size:=OS_32;
paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
inc(nextintreg);
paraloc2:=hp.paraloc[side].add_location;
paraloc2^.loc:=LOC_REGISTER;
paraloc2^.size:=OS_32;
paraloc2^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
inc(nextintreg);
if target_info.abi=abi_powerpc_aix then
inc(stack_offset,8);
end
else
{$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
if (target_info.abi=abi_powerpc_sysv) and
is_64bit(paradef) and
odd(nextintreg-RS_R3) then
inc(nextintreg);
{$endif not cpu64bit}
{ can become < 0 for e.g. 3-byte records }
while (paralen > 0) do
begin
paraloc:=hp.paraloc[side].add_location;
if (loc = LOC_REGISTER) and
(nextintreg <= RS_R10) then
begin
paraloc^.loc := loc;
paracgsize := int_cgsize(paralen);
if (paracgsize in [OS_NO,OS_64,OS_S64]) then
paraloc^.size := OS_INT
else
begin
nextintreg:=RS_R11;
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;
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;
paraloc^.size := paracgsize;
paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
inc(nextintreg);
dec(paralen,tcgsize2size[paraloc^.size]);
inc(parasize,tcgsize2size[paraloc^.size]);
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
if paraloc^.size = OS_F32 then
begin
inc(stack_offset,4);
if (nextintreg < RS_R11) then
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
inc(parasize,4);
if (nextintreg < RS_R11) then
inc(nextintreg);
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;
inc(stack_offset,hp.vartype.def.size);
inc(parasize,8);
if (nextintreg < RS_R10) then
inc(nextintreg,2)
else
nextintreg := RS_R11;
end;
end;
else
internalerror(2002071002);
end;
end;
{$else not cpu64bit}
begin
inc(parasize,tcgsize2size[paracgsize]);
if (nextintreg < RS_R11) then
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;
curfloatreg:=nextfloatreg;
curmmreg:=nextmmreg;
cur_stack_offset:=stack_offset;
result:=cur_stack_offset;
result:=parasize;
end;
@ -537,7 +543,13 @@ unit cpupara;
result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
{ 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
begin
parasize:=cur_stack_offset;
@ -637,7 +649,12 @@ begin
end.
{
$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
using explicit typecase), caused bug3523

View File

@ -84,6 +84,7 @@ implementation
InternalError(2002100806);
cgpara.reset;
cgpara.size:=OS_INT;
cgpara.intsize:=tcgsize2size[OS_INT];
cgpara.alignment:=std_param_align;
paraloc:=cgpara.add_location;
with paraloc^ do
@ -249,6 +250,7 @@ implementation
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].Alignment:=std_param_align;
paralen:=tcgsize2size[paracgsize];
hp.paraloc[side].intsize:=paralen;
while paralen>0 do
begin
paraloc:=hp.paraloc[side].add_location;
@ -327,7 +329,12 @@ begin
end.
{
$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
Revision 1.51 2004/11/22 22:01:19 peter