* fixed paraloc^.size for 3-byte parameter parts

* fixed record parameter passing (all records <= 4 bytes passed
    by value, records > 4 bytes by reference)
  * fixed procedure of object parameter passing (handle like tmethod
    record) (mantis #16520)
  * fixed aligning parameters for EABI (it does not depend on the
    parameter size, but rather on its alignment, and also align in
    case a parameter that we wanted to pass via registers has to be
    passed via the stack because we ran out of registers)

git-svn-id: trunk@15390 -
This commit is contained in:
Jonas Maebe 2010-06-05 17:08:28 +00:00
parent 7181287ed2
commit a4c4bc1ee5

View File

@ -53,7 +53,7 @@ unit cpupara;
implementation
uses
verbose,systems,
verbose,systems,cutils,
rgobj,
defutil,symsym;
@ -201,16 +201,12 @@ unit cpupara;
begin
case def.typ of
recorddef:
{ this is how gcc 4.0.4 on linux seems to do it, it doesn't look like being
ARM ABI standard compliant
}
result:=not((trecorddef(def).symtable.SymList.count=1) and
not(ret_in_param(tabstractvarsym(trecorddef(def).symtable.SymList[0]).vardef,calloption)));
{
objectdef
arraydef:
result:=not(def.size in [1,2,4]);
}
result:=def.size>4;
procvardef:
if (po_methodpointer in tprocvardef(def).procoptions) then
result:=true
else
result:=false
else
result:=inherited ret_in_param(def,calloption);
end;
@ -239,6 +235,7 @@ unit cpupara;
paracgsize : tcgsize;
paralen : longint;
i : integer;
firstparaloc: boolean;
procedure assignintreg;
begin
@ -321,6 +318,7 @@ unit cpupara;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].Alignment:=std_param_align;
hp.paraloc[side].intsize:=paralen;
firstparaloc:=true;
{$ifdef EXTDEBUG}
if paralen=0 then
@ -348,11 +346,14 @@ unit cpupara;
begin
{ align registers for eabi }
if (target_info.abi=abi_eabi) and
(paracgsize in [OS_F64,OS_64,OS_S64]) and
(nextintreg in [RS_R1,RS_R3]) and
{ first location? }
(paralen=8) then
inc(nextintreg);
firstparaloc and
(paradef.alignment=8) then
begin
if (nextintreg in [RS_R1,RS_R3]) then
inc(nextintreg)
else if nextintreg>RS_R3 then
stack_offset:=align(stack_offset,8);
end;
{ this is not abi compliant
why? (FK) }
if nextintreg<=RS_R3 then
@ -363,7 +364,7 @@ unit cpupara;
end
else
begin
{ LOC_REFERENCE covers always the overleft }
{ LOC_REFERENCE always contains everything that's left }
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
if (side=callerside) then
@ -402,25 +403,25 @@ unit cpupara;
end;
LOC_REFERENCE:
begin
{ align stack for eabi }
if (target_info.abi=abi_eabi) and
(paracgsize in [OS_F64,OS_64,OS_S64]) and
(stack_offset mod 8<>0) and
{ first location? }
(paralen=8) then
inc(stack_offset,8-(stack_offset mod 8));
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
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paraloc^.size:=OS_ADDR;
assignintreg
end
else
begin
{ align stack for eabi }
if (target_info.abi=abi_eabi) and
firstparaloc and
(paradef.alignment=8) then
stack_offset:=align(stack_offset,8);
paraloc^.size:=paracgsize;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,hp.vardef.size);
inc(stack_offset,align(paralen,4));
paralen:=0
end;
end;
else
@ -435,6 +436,7 @@ unit cpupara;
end;
end;
dec(paralen,tcgsize2size[paraloc^.size]);
firstparaloc:=false
end;
end;
curintreg:=nextintreg;
@ -544,7 +546,10 @@ unit cpupara;
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RETURN_REG;
paraloc^.size:=retcgsize;
if (result.intsize<>3) then
paraloc^.size:=retcgsize
else
paraloc^.size:=OS_32;
end;
end;
end;