Browse Source

* insert stack_check helper call before doing register allocation
so the used registers can't be reused when parameters are loaded
into register variables

peter 20 years ago
parent
commit
296e81146e
3 changed files with 55 additions and 7 deletions
  1. 23 3
      compiler/ncgutil.pas
  2. 20 3
      compiler/psub.pas
  3. 12 1
      compiler/symsym.pas

+ 23 - 3
compiler/ncgutil.pas

@@ -59,7 +59,8 @@ interface
     procedure gen_proc_symbol_end(list:Taasmoutput);
     procedure gen_proc_entry_code(list:Taasmoutput);
     procedure gen_proc_exit_code(list:Taasmoutput);
-    procedure gen_stack_check_code(list:Taasmoutput);
+    procedure gen_stack_check_size_para(list:Taasmoutput);
+    procedure gen_stack_check_call(list:Taasmoutput);
     procedure gen_save_used_regs(list:TAAsmoutput);
     procedure gen_restore_used_regs(list:TAAsmoutput);
     procedure gen_initialize_code(list:TAAsmoutput);
@@ -1808,7 +1809,7 @@ implementation
       end;
 
 
-    procedure gen_stack_check_code(list:Taasmoutput);
+    procedure gen_stack_check_size_para(list:Taasmoutput);
       var
         paraloc1   : tcgpara;
       begin
@@ -1817,6 +1818,20 @@ implementation
         paramanager.allocparaloc(list,paraloc1);
         cg.a_param_const(list,OS_INT,current_procinfo.calc_stackframe_size,paraloc1);
         paramanager.freeparaloc(list,paraloc1);
+        paraloc1.done;
+      end;
+
+
+    procedure gen_stack_check_call(list:Taasmoutput);
+      var
+        paraloc1   : tcgpara;
+      begin
+        paraloc1.init;
+        { Also alloc the register needed for the parameter }
+        paramanager.getintparaloc(pocall_default,1,paraloc1);
+        paramanager.allocparaloc(list,paraloc1);
+        paramanager.freeparaloc(list,paraloc1);
+        { Call the helper }
         cg.alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
         cg.a_call_name(list,'FPC_STACKCHECK');
         cg.dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
@@ -2326,7 +2341,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.250  2004-12-15 16:00:16  peter
+  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
+
+  Revision 1.250  2004/12/15 16:00:16  peter
     * external is again allowed in implementation
 
   Revision 1.249  2004/12/11 12:42:28  jonas

+ 20 - 3
compiler/psub.pas

@@ -780,6 +780,17 @@ implementation
             gen_free_symtable(aktproccode,procdef.localst);
             gen_free_symtable(aktproccode,procdef.parast);
 
+            { Already reserve all registers for stack checking code and
+              generate the call to the helper function }
+            if (cs_check_stack in entryswitches) and
+               not(po_assembler in procdef.procoptions) and
+               (current_procinfo.procdef.proctypeoption<>potype_proginit) then
+              begin
+                aktfilepos:=entrypos;
+                gen_stack_check_call(templist);
+                aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
+              end;
+
             { The procedure body is finished, we can now
               allocate the registers }
             cg.do_register_allocation(aktproccode,headertai);
@@ -790,13 +801,14 @@ implementation
             aktproccode.insertlistafter(headertai,templist);
             aktfilepos:=exitpos;
             gen_restore_used_regs(aktproccode);
-            { Add stack checking code }
+            { We know the size of the stack, now we can generate the
+              parameter that is passed to the stack checking code }
             if (cs_check_stack in entryswitches) and
                not(po_assembler in procdef.procoptions) and
                (current_procinfo.procdef.proctypeoption<>potype_proginit) then
               begin
                 aktfilepos:=entrypos;
-                gen_stack_check_code(templist);
+                gen_stack_check_size_para(templist);
                 aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
               end;
             { Add entry code (stack allocation) after header }
@@ -1447,7 +1459,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.227  2004-12-27 16:35:48  peter
+  Revision 1.228  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
+
+  Revision 1.227  2004/12/27 16:35:48  peter
     * set flag if a procedure references a symbol in staticsymtable
 
   Revision 1.226  2004/12/27 14:41:09  jonas

+ 12 - 1
compiler/symsym.pas

@@ -1323,6 +1323,12 @@ implementation
 
     function tabstractvarsym.is_regvar:boolean;
       begin
+        { Register variables are not allowed in the following cases:
+           - regvars are disabled
+           - exceptions are used (after an exception is raised the contents of the
+               registers is not valid anymore)
+           - it has a local copy
+           - the value needs to be in memory (i.e. reference counted) }
         result:=(cs_regvars in aktglobalswitches) and
                 not(pi_has_assembler_block in current_procinfo.flags) and
                 not(pi_uses_exceptions in current_procinfo.flags) and
@@ -2554,7 +2560,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.196  2004-12-07 16:11:52  peter
+  Revision 1.197  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
+
+  Revision 1.196  2004/12/07 16:11:52  peter
     * set vo_explicit_paraloc flag
 
   Revision 1.195  2004/11/29 20:50:37  peter