Browse Source

* 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 -

nickysn 7 years ago
parent
commit
c530e031b1
2 changed files with 15 additions and 5 deletions
  1. 6 4
      compiler/i386/cpupara.pas
  2. 9 1
      compiler/x86/nx86cal.pas

+ 6 - 4
compiler/i386/cpupara.pas

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

+ 9 - 1
compiler/x86/nx86cal.pas

@@ -86,12 +86,20 @@ implementation
 
 
 
 
   function tx86callnode.can_call_ref(var ref: treference): boolean;
   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
     begin
       tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,ref);
       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
       { 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 }
         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
       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;
     end;