Browse Source

* removevaluepara added to fix the stackpointer so restoring of
saved registers works

peter 23 years ago
parent
commit
a4e309d6ae
2 changed files with 92 additions and 18 deletions
  1. 64 17
      compiler/ncgutil.pas
  2. 28 1
      compiler/x86/cgx86.pas

+ 64 - 17
compiler/ncgutil.pas

@@ -116,25 +116,30 @@ implementation
       begin
       begin
          { always calculate boolean AND and OR from left to right }
          { always calculate boolean AND and OR from left to right }
          if (p.nodetype in [orn,andn]) and
          if (p.nodetype in [orn,andn]) and
-            (p.left.resulttype.def.deftype=orddef) and
-            (torddef(p.left.resulttype.def).typ in [bool8bit,bool16bit,bool32bit]) then
+            is_boolean(p.left.resulttype.def) then
            begin
            begin
-             { p.swaped:=false}
              if nf_swaped in p.flags then
              if nf_swaped in p.flags then
                internalerror(234234);
                internalerror(234234);
            end
            end
          else
          else
-           if (((p.location.loc=LOC_FPUREGISTER) and
-                (p.right.registersfpu > p.left.registersfpu)) or
-               ((((p.left.registersfpu = 0) and
-                  (p.right.registersfpu = 0)) or
-                 (p.location.loc<>LOC_FPUREGISTER)) and
-                (p.left.registers32<p.right.registers32))) and
-           { the following check is appropriate, because all }
-           { 4 registers are rarely used and it is thereby   }
-           { achieved that the extra code is being dropped   }
-           { by exchanging not commutative operators     }
-               (p.right.registers32<=c_countusableregsint) then
+           if (
+               (p.location.loc=LOC_FPUREGISTER) and
+               (p.right.registersfpu > p.left.registersfpu)
+              ) or
+              (
+               (
+                (
+                 ((p.left.registersfpu = 0) and (p.right.registersfpu = 0)) or
+                 (p.location.loc<>LOC_FPUREGISTER)
+                ) and
+                (p.left.registers32<p.right.registers32)
+               ) and
+               { the following check is appropriate, because all }
+               { 4 registers are rarely used and it is thereby   }
+               { achieved that the extra code is being dropped   }
+               { by exchanging not commutative operators     }
+               (p.right.registers32<=c_countusableregsint)
+              ) then
             begin
             begin
               hp:=p.left;
               hp:=p.left;
               p.left:=p.right;
               p.left:=p.right;
@@ -764,7 +769,13 @@ implementation
                        if inlined then
                        if inlined then
                         begin
                         begin
                           reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
                           reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
-                          cg64.a_load64_loc_ref(exprasmlist,p.location,href);
+                          if p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+                            begin
+                              size:=align(p.resulttype.def.size,alignment);
+                              cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false)
+                            end
+                          else
+                            cg64.a_load64_loc_ref(exprasmlist,p.location,href);
                         end
                         end
                        else
                        else
                         cg64.a_param64_loc(exprasmlist,p.location,locpara);
                         cg64.a_param64_loc(exprasmlist,p.location,locpara);
@@ -795,7 +806,13 @@ implementation
                        if inlined then
                        if inlined then
                         begin
                         begin
                           reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
                           reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
-                          cg.a_load_loc_ref(exprasmlist,p.location,href);
+                          if p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+                            begin
+                              size:=align(p.resulttype.def.size,alignment);
+                              cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false)
+                            end
+                          else
+                            cg.a_load_loc_ref(exprasmlist,p.location,href);
                         end
                         end
                        else
                        else
                         cg.a_param_loc(exprasmlist,p.location,locpara);
                         cg.a_param_loc(exprasmlist,p.location,locpara);
@@ -857,6 +874,24 @@ implementation
       end;
       end;
 
 
 
 
+    procedure removevalueparas(p : tnamedindexitem;arg:pointer);
+      var
+        href1 : treference;
+        list : taasmoutput;
+      begin
+        list:=taasmoutput(arg);
+        if (tsym(p).typ=varsym) and
+           (tvarsym(p).varspez=vs_value) and
+           (is_open_array(tvarsym(p).vartype.def) or
+            is_array_of_const(tvarsym(p).vartype.def)) and
+           (paramanager.push_addr_param(tvarsym(p).vartype.def,false)) then
+         begin
+           reference_reset_base(href1,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
+           cg.g_removevaluepara_openarray(list,href1,tarraydef(tvarsym(p).vartype.def).elesize);
+         end;
+      end;
+
+
     procedure initialize_threadvar(p : tnamedindexitem;arg:pointer);
     procedure initialize_threadvar(p : tnamedindexitem;arg:pointer);
       var
       var
         href : treference;
         href : treference;
@@ -1565,6 +1600,14 @@ implementation
           end;
           end;
 {$endif GDB}
 {$endif GDB}
 
 
+        { remove copies of call by value parameters when there are also
+          registers saved on the stack }
+        if ((po_saveregisters in aktprocdef.procoptions) or
+            (po_savestdregs in aktprocdef.procoptions)) and
+           not(po_assembler in aktprocdef.procoptions) and
+           not(aktprocdef.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_palmossyscall,pocall_system]) then
+          aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}removevalueparas,list);
+
         { for the save all registers we can simply use a pusha,popa which
         { for the save all registers we can simply use a pusha,popa which
           push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
           push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
         if (po_saveregisters in aktprocdef.procoptions) then
         if (po_saveregisters in aktprocdef.procoptions) then
@@ -1732,7 +1775,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.43  2002-08-25 19:25:18  peter
+  Revision 1.44  2002-09-01 14:42:41  peter
+    * removevaluepara added to fix the stackpointer so restoring of
+      saved registers works
+
+  Revision 1.43  2002/08/25 19:25:18  peter
     * sym.insert_in_data removed
     * sym.insert_in_data removed
     * symtable.insertvardata/insertconstdata added
     * symtable.insertvardata/insertconstdata added
     * removed insert_in_data call from symtable.insert, it needs to be
     * removed insert_in_data call from symtable.insert, it needs to be

+ 28 - 1
compiler/x86/cgx86.pas

@@ -107,6 +107,7 @@ unit cgx86;
 
 
         { entry/exit code helpers }
         { entry/exit code helpers }
         procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer);override;
         procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer);override;
+        procedure g_removevaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer);override;
         procedure g_interrupt_stackframe_entry(list : taasmoutput);override;
         procedure g_interrupt_stackframe_entry(list : taasmoutput);override;
         procedure g_interrupt_stackframe_exit(list : taasmoutput;selfused,accused,acchiused:boolean);override;
         procedure g_interrupt_stackframe_exit(list : taasmoutput;selfused,accused,acchiused:boolean);override;
         procedure g_profilecode(list : taasmoutput);override;
         procedure g_profilecode(list : taasmoutput);override;
@@ -1347,6 +1348,28 @@ unit cgx86;
       end;
       end;
 
 
 
 
+    procedure tcgx86.g_removevaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer);
+      var
+        lenref : treference;
+        power,len  : longint;
+      begin
+        lenref:=ref;
+        inc(lenref.offset,4);
+        { caluclate size and adjust stack space }
+        rg.getexplicitregisterint(list,R_EDI);
+        list.concat(Taicpu.op_ref_reg(A_MOV,S_L,lenref,R_EDI));
+        list.concat(Taicpu.op_reg(A_INC,S_L,R_EDI));
+        if (elesize<>1) then
+         begin
+           if ispowerof2(elesize, power) then
+             list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,R_EDI))
+           else
+             list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,R_EDI));
+         end;
+        list.concat(Taicpu.op_reg_reg(A_ADD,S_L,R_EDI,R_ESP));
+      end;
+
+
     procedure tcgx86.g_interrupt_stackframe_entry(list : taasmoutput);
     procedure tcgx86.g_interrupt_stackframe_entry(list : taasmoutput);
       begin
       begin
         { .... also the segment registers }
         { .... also the segment registers }
@@ -1651,7 +1674,11 @@ unit cgx86;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.13  2002-09-01 12:09:27  peter
+  Revision 1.14  2002-09-01 14:42:41  peter
+    * removevaluepara added to fix the stackpointer so restoring of
+      saved registers works
+
+  Revision 1.13  2002/09/01 12:09:27  peter
     + a_call_reg, a_call_loc added
     + a_call_reg, a_call_loc added
     * removed exprasmlist references
     * removed exprasmlist references