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 21 năm trước cách đây
mục cha
commit
296e81146e
3 tập tin đã thay đổi với 55 bổ sung7 xóa
  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