* synchronize get_saved_registers_int and get_volatile_registers_int for all

calling conventions on i386
* generated code at the caller side for pocall_pascal routines on i386 no longer
  assumes the routine destroys all registers (except ebp) - instead now it
  assumes that it preserves the ebx,esi,edi and ebp registers. This is
  compatible with the pascal calling convention of 32-bit delphi and was already
  honoured by FPC on the callee side.
* updated the list of calling conventions that save all registers, used in
  tx86callnode.can_call_ref, so it is accurate on all x86 platforms - i8086,
  i386 and x86_64.

git-svn-id: trunk@38904 -
This commit is contained in:
nickysn 2018-05-04 16:16:24 +00:00
parent abd893cac4
commit c530e031b1
2 changed files with 16 additions and 6 deletions

View File

@ -263,10 +263,10 @@ unit cpupara;
pocall_cdecl,
pocall_syscall,
pocall_cppdecl,
pocall_mwpascal :
pocall_mwpascal,
pocall_pascal:
result:=[RS_EAX,RS_EDX,RS_ECX];
pocall_far16,
pocall_pascal,
pocall_oldfpccall :
result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX];
else
@ -290,6 +290,7 @@ unit cpupara;
function tcpuparamanager.get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;
const
saveregs : array[0..3] of tsuperregister = (RS_EBX,RS_ESI,RS_EDI,RS_EBP);
saveregs_oldfpccall : array[0..0] of tsuperregister = (RS_EBP);
begin
case calloption of
pocall_internproc,
@ -300,10 +301,11 @@ unit cpupara;
pocall_syscall,
pocall_cppdecl,
pocall_mwpascal,
pocall_far16,
pocall_pascal,
pocall_oldfpccall :
pocall_pascal:
result:=saveregs;
pocall_far16,
pocall_oldfpccall :
result:=saveregs_oldfpccall;
else
internalerror(2018050401);
end;

View File

@ -86,12 +86,20 @@ implementation
function tx86callnode.can_call_ref(var ref: treference): boolean;
const
{$if defined(i8086)}
save_all_regs=[pocall_far16,pocall_pascal,pocall_oldfpccall];
{$elseif defined(i386)}
save_all_regs=[pocall_far16,pocall_oldfpccall];
{$elseif defined(x86_64)}
save_all_regs=[];
{$endif}
begin
tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,ref);
{ do not use a ref. for calling conventions which allocate all registers, the reg. allocator cannot handle this, see
also issue #28639, I were not able to create a simple example though to cause the resulting endless spilling }
result:=((getsupreg(ref.base)<first_int_imreg) and (getsupreg(ref.index)<first_int_imreg)) or
not(procdefinition.proccalloption in [pocall_far16,pocall_pascal,pocall_oldfpccall]);
not(procdefinition.proccalloption in save_all_regs);
end;