mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-06 11:18:36 +02:00
* handle stack parameters like delphi when using register calling conventions, resolves #8199
git-svn-id: trunk@6201 -
This commit is contained in:
parent
c0e9782da9
commit
e923c6072d
@ -503,104 +503,144 @@ unit cpupara;
|
|||||||
varalign : longint;
|
varalign : longint;
|
||||||
pushaddr : boolean;
|
pushaddr : boolean;
|
||||||
paraalign : shortint;
|
paraalign : shortint;
|
||||||
|
pass : byte;
|
||||||
begin
|
begin
|
||||||
|
if paras.count=0 then
|
||||||
|
exit;
|
||||||
paraalign:=get_para_align(p.proccalloption);
|
paraalign:=get_para_align(p.proccalloption);
|
||||||
{ Register parameters are assigned from left to right }
|
|
||||||
for i:=0 to paras.count-1 do
|
|
||||||
begin
|
|
||||||
hp:=tparavarsym(paras[i]);
|
|
||||||
pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
|
|
||||||
if pushaddr then
|
|
||||||
begin
|
|
||||||
paralen:=sizeof(aint);
|
|
||||||
paracgsize:=OS_ADDR;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
|
|
||||||
paracgsize:=def_cgsize(hp.vardef);
|
|
||||||
end;
|
|
||||||
hp.paraloc[side].reset;
|
|
||||||
hp.paraloc[side].size:=paracgsize;
|
|
||||||
hp.paraloc[side].intsize:=paralen;
|
|
||||||
hp.paraloc[side].Alignment:=paraalign;
|
|
||||||
{
|
|
||||||
EAX
|
|
||||||
EDX
|
|
||||||
ECX
|
|
||||||
Stack
|
|
||||||
Stack
|
|
||||||
|
|
||||||
64bit values,floats,arrays and records are always
|
{ clean up here so we can later detect properly if a parameter has been
|
||||||
on the stack.
|
assigned or not
|
||||||
}
|
}
|
||||||
if (parareg<=high(parasupregs)) and
|
for i:=0 to paras.count-1 do
|
||||||
(paralen<=sizeof(aint)) and
|
tparavarsym(paras[i]).paraloc[side].reset;
|
||||||
(
|
{ Register parameters are assigned from left to right,
|
||||||
not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
|
stack parameters from right to left so assign first the
|
||||||
pushaddr
|
register parameters in a first pass, in the second
|
||||||
) then
|
pass all unhandled parameters are done }
|
||||||
begin
|
for pass:=1 to 2 do
|
||||||
paraloc:=hp.paraloc[side].add_location;
|
begin
|
||||||
paraloc^.size:=paracgsize;
|
if pass=1 then
|
||||||
paraloc^.loc:=LOC_REGISTER;
|
i:=0
|
||||||
paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(paracgsize));
|
|
||||||
inc(parareg);
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
|
i:=paras.count-1;
|
||||||
|
while true do
|
||||||
begin
|
begin
|
||||||
{ Copy to stack? }
|
hp:=tparavarsym(paras[i]);
|
||||||
if (use_fixed_stack) or
|
if not(assigned(hp.paraloc[side].location)) then
|
||||||
(paracgsize=OS_NO) then
|
|
||||||
begin
|
begin
|
||||||
paraloc:=hp.paraloc[side].add_location;
|
|
||||||
paraloc^.loc:=LOC_REFERENCE;
|
pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
|
||||||
paraloc^.size:=paracgsize;
|
if pushaddr then
|
||||||
if side=callerside then
|
|
||||||
paraloc^.reference.index:=NR_STACK_POINTER_REG
|
|
||||||
else
|
|
||||||
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
|
|
||||||
varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
|
|
||||||
paraloc^.reference.offset:=parasize;
|
|
||||||
if side=calleeside then
|
|
||||||
inc(paraloc^.reference.offset,target_info.first_parm_offset);
|
|
||||||
parasize:=align(parasize+paralen,varalign);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if paralen=0 then
|
|
||||||
internalerror(200501163);
|
|
||||||
while (paralen>0) do
|
|
||||||
begin
|
begin
|
||||||
paraloc:=hp.paraloc[side].add_location;
|
paralen:=sizeof(aint);
|
||||||
paraloc^.loc:=LOC_REFERENCE;
|
paracgsize:=OS_ADDR;
|
||||||
{ Extended and double need a single location }
|
end
|
||||||
if (paracgsize in [OS_F64,OS_F32]) then
|
else
|
||||||
begin
|
begin
|
||||||
paraloc^.size:=paracgsize;
|
paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
|
||||||
l:=paralen;
|
paracgsize:=def_cgsize(hp.vardef);
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{ We can allocate at maximum 32 bits per location }
|
|
||||||
if paralen>sizeof(aint) then
|
|
||||||
l:=sizeof(aint)
|
|
||||||
else
|
|
||||||
l:=paralen;
|
|
||||||
paraloc^.size:=int_cgsize(l);
|
|
||||||
end;
|
|
||||||
if side=callerside then
|
|
||||||
paraloc^.reference.index:=NR_STACK_POINTER_REG
|
|
||||||
else
|
|
||||||
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
|
|
||||||
varalign:=used_align(size_2_align(l),paraalign,paraalign);
|
|
||||||
paraloc^.reference.offset:=parasize;
|
|
||||||
if side=calleeside then
|
|
||||||
inc(paraloc^.reference.offset,target_info.first_parm_offset);
|
|
||||||
parasize:=align(parasize+l,varalign);
|
|
||||||
dec(paralen,l);
|
|
||||||
end;
|
end;
|
||||||
|
hp.paraloc[side].size:=paracgsize;
|
||||||
|
hp.paraloc[side].intsize:=paralen;
|
||||||
|
hp.paraloc[side].Alignment:=paraalign;
|
||||||
|
{
|
||||||
|
EAX
|
||||||
|
EDX
|
||||||
|
ECX
|
||||||
|
Stack
|
||||||
|
Stack
|
||||||
|
|
||||||
|
64bit values,floats,arrays and records are always
|
||||||
|
on the stack.
|
||||||
|
}
|
||||||
|
if (parareg<=high(parasupregs)) and
|
||||||
|
(paralen<=sizeof(aint)) and
|
||||||
|
(
|
||||||
|
not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
|
||||||
|
pushaddr
|
||||||
|
) then
|
||||||
|
begin
|
||||||
|
if pass=1 then
|
||||||
|
begin
|
||||||
|
paraloc:=hp.paraloc[side].add_location;
|
||||||
|
paraloc^.size:=paracgsize;
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(paracgsize));
|
||||||
|
inc(parareg);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if pass=2 then
|
||||||
|
begin
|
||||||
|
{ Copy to stack? }
|
||||||
|
if (use_fixed_stack) or
|
||||||
|
(paracgsize=OS_NO) then
|
||||||
|
begin
|
||||||
|
paraloc:=hp.paraloc[side].add_location;
|
||||||
|
paraloc^.loc:=LOC_REFERENCE;
|
||||||
|
paraloc^.size:=paracgsize;
|
||||||
|
if side=callerside then
|
||||||
|
paraloc^.reference.index:=NR_STACK_POINTER_REG
|
||||||
|
else
|
||||||
|
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
|
||||||
|
varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
|
||||||
|
paraloc^.reference.offset:=parasize;
|
||||||
|
if side=calleeside then
|
||||||
|
inc(paraloc^.reference.offset,target_info.first_parm_offset);
|
||||||
|
parasize:=align(parasize+paralen,varalign);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if paralen=0 then
|
||||||
|
internalerror(200501163);
|
||||||
|
while (paralen>0) do
|
||||||
|
begin
|
||||||
|
paraloc:=hp.paraloc[side].add_location;
|
||||||
|
paraloc^.loc:=LOC_REFERENCE;
|
||||||
|
{ Extended and double need a single location }
|
||||||
|
if (paracgsize in [OS_F64,OS_F32]) then
|
||||||
|
begin
|
||||||
|
paraloc^.size:=paracgsize;
|
||||||
|
l:=paralen;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ We can allocate at maximum 32 bits per location }
|
||||||
|
if paralen>sizeof(aint) then
|
||||||
|
l:=sizeof(aint)
|
||||||
|
else
|
||||||
|
l:=paralen;
|
||||||
|
paraloc^.size:=int_cgsize(l);
|
||||||
|
end;
|
||||||
|
if side=callerside then
|
||||||
|
paraloc^.reference.index:=NR_STACK_POINTER_REG
|
||||||
|
else
|
||||||
|
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
|
||||||
|
varalign:=used_align(size_2_align(l),paraalign,paraalign);
|
||||||
|
paraloc^.reference.offset:=parasize;
|
||||||
|
if side=calleeside then
|
||||||
|
inc(paraloc^.reference.offset,target_info.first_parm_offset);
|
||||||
|
parasize:=align(parasize+l,varalign);
|
||||||
|
dec(paralen,l);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
case pass of
|
||||||
|
1:
|
||||||
|
begin
|
||||||
|
if i=paras.count-1 then
|
||||||
|
break;
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
2:
|
||||||
|
begin
|
||||||
|
if i=0 then
|
||||||
|
break;
|
||||||
|
dec(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user