Просмотр исходного кода

* several fixes to parameter handling on arm

florian 21 лет назад
Родитель
Сommit
abc41f1c3c
5 измененных файлов с 190 добавлено и 78 удалено
  1. 7 3
      compiler/arm/aasmcpu.pas
  2. 42 22
      compiler/arm/cpupara.pas
  3. 5 1
      compiler/fpcdefs.inc
  4. 97 43
      compiler/ncgcal.pas
  5. 39 9
      compiler/paramgr.pas

+ 7 - 3
compiler/arm/aasmcpu.pas

@@ -296,8 +296,9 @@ implementation
     function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
     function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
       begin
       begin
         { allow the register allocator to remove unnecessary moves }
         { allow the register allocator to remove unnecessary moves }
-        result:=((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
-                ((opcode=A_MVF) and (regtype = R_FPUREGISTER)) and
+        result:=(((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
+                 ((opcode=A_MVF) and (regtype = R_FPUREGISTER))
+                ) and
                 (condition=C_None) and
                 (condition=C_None) and
                 (ops=2) and
                 (ops=2) and
                 (oper[0]^.typ=top_reg) and
                 (oper[0]^.typ=top_reg) and
@@ -422,7 +423,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.27  2004-02-08 23:10:21  jonas
+  Revision 1.28  2004-02-09 22:48:45  florian
+    * several fixes to parameter handling on arm
+
+  Revision 1.27  2004/02/08 23:10:21  jonas
     * taicpu.is_same_reg_move() now gets a regtype parameter so it only
     * taicpu.is_same_reg_move() now gets a regtype parameter so it only
       removes moves of that particular register type. This is necessary so
       removes moves of that particular register type. This is necessary so
       we don't remove the live_start instruction of a register before it
       we don't remove the live_start instruction of a register before it

+ 42 - 22
compiler/arm/cpupara.pas

@@ -40,7 +40,7 @@ unit cpupara;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
           function getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override;
           function getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override;
           // procedure freeintparaloc(list: taasmoutput; nr : longint); override;
           // procedure freeintparaloc(list: taasmoutput; nr : longint); override;
-
+          procedure alloctempparaloc(list: taasmoutput;calloption : tproccalloption;paraitem : tparaitem;var locpara:tparalocation);override;
           function  create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function  create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
        end;
        end;
 
 
@@ -230,12 +230,12 @@ unit cpupara;
           begin
           begin
              if (hp.paratyp in [vs_var,vs_out]) then
              if (hp.paratyp in [vs_var,vs_out]) then
                begin
                begin
-                 paradef := voidpointertype.def;
-                 loc := LOC_REGISTER;
+                 paradef:=voidpointertype.def;
+                 loc:=LOC_REGISTER;
                end
                end
              else
              else
                begin
                begin
-                 paradef := hp.paratype.def;
+                 paradef:=hp.paratype.def;
                  loc:=getparaloc(p.proccalloption,paradef);
                  loc:=getparaloc(p.proccalloption,paradef);
                end;
                end;
              { make sure all alignment bytes are 0 as well }
              { make sure all alignment bytes are 0 as well }
@@ -248,28 +248,28 @@ unit cpupara;
                      if paraloc.size = OS_NO then
                      if paraloc.size = OS_NO then
                        paraloc.size := OS_ADDR;
                        paraloc.size := OS_ADDR;
                      is_64bit := paraloc.size in [OS_64,OS_S64,OS_F64];
                      is_64bit := paraloc.size in [OS_64,OS_S64,OS_F64];
+                     { this is not abi compliant }
                      if nextintreg<=(RS_R3-ord(is_64bit)) then
                      if nextintreg<=(RS_R3-ord(is_64bit)) then
                        begin
                        begin
-                          paraloc.loc:=LOC_REGISTER;
-                          { big endian }
-		          if is_64bit then
-                            begin
-                              paraloc.registerhigh:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
-                              inc(nextintreg);
-                            end;
-                          paraloc.registerlow:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
-                          inc(nextintreg);
+                         paraloc.loc:=LOC_REGISTER;
+                         paraloc.registerlow:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+                         inc(nextintreg);
+                         if is_64bit then
+                          begin
+                            paraloc.registerhigh:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+                            inc(nextintreg);
+                          end;
                        end
                        end
                      else
                      else
                         begin
                         begin
-                           nextintreg:=RS_R4;
-                           paraloc.loc:=LOC_REFERENCE;
-                           paraloc.reference.index:=NR_STACK_POINTER_REG;
-                           paraloc.reference.offset:=stack_offset;
-                           if not is_64bit then
-                             inc(stack_offset,4)
-                           else
-                             inc(stack_offset,8);
+                          nextintreg:=RS_R4;
+                          paraloc.loc:=LOC_REFERENCE;
+                          paraloc.reference.index:=NR_STACK_POINTER_REG;
+                          paraloc.reference.offset:=stack_offset;
+                          if not is_64bit then
+                            inc(stack_offset,4)
+                          else
+                            inc(stack_offset,8);
                        end;
                        end;
                   end;
                   end;
                 LOC_FPUREGISTER:
                 LOC_FPUREGISTER:
@@ -346,12 +346,32 @@ unit cpupara;
        p.funcret_paraloc[side]:=paraloc;
        p.funcret_paraloc[side]:=paraloc;
      end;
      end;
 
 
+
+   procedure tarmparamanager.alloctempparaloc(list: taasmoutput;calloption : tproccalloption;paraitem : tparaitem;var locpara:tparalocation);
+     var
+       href : treference;
+     begin
+       if (paraitem.paratyp in [vs_var,vs_out]) then
+         locpara.loc:=LOC_REGISTER
+       else
+         locpara.loc:=getparaloc(calloption,paraitem.paratype.def);
+
+       if locpara.loc=LOC_REFERENCE then
+         inherited alloctempparaloc(list,calloption,paraitem,locpara)
+       else
+         alloctempregs(list,locpara);
+     end;
+
+
 begin
 begin
    paramanager:=tarmparamanager.create;
    paramanager:=tarmparamanager.create;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.13  2004-01-24 01:32:49  florian
+  Revision 1.14  2004-02-09 22:48:45  florian
+    * several fixes to parameter handling on arm
+
+  Revision 1.13  2004/01/24 01:32:49  florian
     * genintparaloc fixed
     * genintparaloc fixed
 
 
   Revision 1.12  2004/01/20 23:18:00  florian
   Revision 1.12  2004/01/20 23:18:00  florian

+ 5 - 1
compiler/fpcdefs.inc

@@ -81,6 +81,7 @@
 
 
 {$ifdef arm}
 {$ifdef arm}
   {$define cpuneedsdiv32helper}
   {$define cpuneedsdiv32helper}
+  {$define cputargethasfixedstack}
   {$define noopt}
   {$define noopt}
   {$define oldset}
   {$define oldset}
 {$endif arm}
 {$endif arm}
@@ -93,7 +94,10 @@
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.31  2004-01-28 16:47:45  peter
+  Revision 1.32  2004-02-09 22:48:45  florian
+    * several fixes to parameter handling on arm
+
+  Revision 1.31  2004/01/28 16:47:45  peter
   Stacksize force to 1mb
   Stacksize force to 1mb
 
 
   Revision 1.30  2003/12/14 22:41:46  peter
   Revision 1.30  2003/12/14 22:41:46  peter

+ 97 - 43
compiler/ncgcal.pas

@@ -104,8 +104,18 @@ implementation
       begin
       begin
          { Allocate (temporary) paralocation }
          { Allocate (temporary) paralocation }
          tempparaloc:=paraitem.paraloc[callerside];
          tempparaloc:=paraitem.paraloc[callerside];
-         if (tempparaloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER]) then
-           paramanager.alloctempregs(exprasmlist,tempparaloc)
+         case tempparaloc.loc of
+           LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER:
+             paramanager.alloctempregs(exprasmlist,tempparaloc);
+{$ifdef cputargethasfixedstack}
+           LOC_REFERENCE:
+             begin
+               { currently, we copy the value always to a secure location }
+               if true then
+                 paramanager.alloctempparaloc(exprasmlist,aktcallnode.procdefinition.proccalloption,paraitem,tempparaloc);
+             end;
+{$endif cputargethasfixedstack}
+         end;
       end;
       end;
 
 
 
 
@@ -288,7 +298,6 @@ implementation
       end;
       end;
 
 
 
 
-
     procedure tcgcallparanode.secondcallparan;
     procedure tcgcallparanode.secondcallparan;
       var
       var
          otlabel,
          otlabel,
@@ -602,7 +611,7 @@ implementation
          oldpushedparasize : longint;
          oldpushedparasize : longint;
          { adress returned from an I/O-error }
          { adress returned from an I/O-error }
          { help reference pointer }
          { help reference pointer }
-         href : treference;
+         href,href2 : treference;
          pop_size : longint;
          pop_size : longint;
          pvreg,
          pvreg,
          vmtreg : tregister;
          vmtreg : tregister;
@@ -616,52 +625,94 @@ implementation
            ppn:=tcgcallparanode(left);
            ppn:=tcgcallparanode(left);
            while assigned(ppn) do
            while assigned(ppn) do
              begin
              begin
-               case ppn.tempparaloc.loc of
-                 LOC_REGISTER:
-                   begin
-                     paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
-                     paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
+               if (ppn.left.nodetype<>nothingn) then
+                 begin
+                   { better check for the real location of the parameter here, when stack passed parameters
+                     are saved temporary in registers, checking for the tempparaloc.loc is wrong
+                   }
+                   case ppn.paraitem.paraloc[callerside].loc of
+                     LOC_REGISTER:
+                       begin
+                         paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
+                         paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
 {$ifdef sparc}
 {$ifdef sparc}
-                     case ppn.tempparaloc.size of
-                       OS_F32 :
-                         ppn.tempparaloc.size:=OS_32;
-                       OS_F64 :
-                         ppn.tempparaloc.size:=OS_64;
-                     end;
+                         case ppn.tempparaloc.size of
+                           OS_F32 :
+                             ppn.tempparaloc.size:=OS_32;
+                           OS_F64 :
+                             ppn.tempparaloc.size:=OS_64;
+                         end;
 {$endif sparc}
 {$endif sparc}
 {$ifndef cpu64bit}
 {$ifndef cpu64bit}
-                     if ppn.tempparaloc.size in [OS_64,OS_S64] then
-                       begin
-                         cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerlow,
-                            ppn.paraitem.paraloc[callerside].registerlow);
-                         cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerhigh,
-                            ppn.paraitem.paraloc[callerside].registerhigh);
-                       end
-                     else
+                         if ppn.tempparaloc.size in [OS_64,OS_S64] then
+                           begin
+                             cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerlow,
+                                ppn.paraitem.paraloc[callerside].registerlow);
+                             cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerhigh,
+                                ppn.paraitem.paraloc[callerside].registerhigh);
+                           end
+                         else
 {$endif cpu64bit}
 {$endif cpu64bit}
-                       cg.a_load_reg_reg(exprasmlist,ppn.tempparaloc.size,ppn.tempparaloc.size,
+                           cg.a_load_reg_reg(exprasmlist,ppn.tempparaloc.size,ppn.tempparaloc.size,
+                               ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register);
+                       end;
+                     LOC_FPUREGISTER:
+                       begin
+                         paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
+                         paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
+                         cg.a_loadfpu_reg_reg(exprasmlist,ppn.tempparaloc.size,
                            ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register);
                            ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register);
-                   end;
-                 LOC_FPUREGISTER:
-                   begin
-                     paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
-                     paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
-                     cg.a_loadfpu_reg_reg(exprasmlist,ppn.tempparaloc.size,
-                       ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register);
-                   end;
-                 LOC_MMREGISTER:
-                   begin
+                       end;
+                     LOC_MMREGISTER:
+                       begin
 {
 {
-                     paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
-                     paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
-                     paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
-                     paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
-                     cg.a_loadmm_reg_reg(exprasmlist,ppn.tempparaloc.size,
-                       ppn.tempparaloc.size,ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register, shuffle???);
+                         paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
+                         paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
+                         paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
+                         paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
+                         cg.a_loadmm_reg_reg(exprasmlist,ppn.tempparaloc.size,
+                           ppn.tempparaloc.size,ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register, shuffle???);
 }
 }
-                     internalerror(2003102910);
+                         internalerror(2003102910);
+                       end;
+                     LOC_REFERENCE:
+                       begin
+{$ifdef cputargethasfixedstack}
+                         { copy parameters in case they were moved to a temp. location because we've a fixed stack }
+                         paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
+                         paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
+                         case ppn.tempparaloc.loc of
+                           LOC_REFERENCE:
+                             begin
+                               reference_reset_base(href,ppn.tempparaloc.reference.index,ppn.tempparaloc.reference.offset);
+                               reference_reset_base(href2,ppn.paraitem.paraloc[callerside].reference.index,ppn.paraitem.paraloc[callerside].reference.offset);
+                               cg.g_concatcopy(exprasmlist,href,href2,ppn.paraitem.paratype.def.size,false,false);
+                             end;
+                           LOC_REGISTER:
+                             if ppn.tempparaloc.size in [OS_64,OS_S64] then
+                               begin
+                                 reference_reset_base(href,ppn.paraitem.paraloc[callerside].reference.index,ppn.paraitem.paraloc[callerside].reference.offset);
+                                 cg.a_load_reg_ref(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerlow,
+                                    href);
+                                 { we don't use a c64.load here because later (when fixed ;)) one dword could be on the stack and the
+                                   other in a cpu register }
+                                 reference_reset_base(href,ppn.paraitem.paraloc[callerside].reference.index,ppn.paraitem.paraloc[callerside].reference.offset+4);
+                                 cg.a_load_reg_ref(exprasmlist,OS_32,OS_32,ppn.tempparaloc.registerhigh,
+                                    href);
+                               end
+                             else
+                               cg.a_param_reg(exprasmlist,ppn.paraitem.paraloc[callerside].size,ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside]);
+                           LOC_FPUREGISTER:
+                             cg.a_paramfpu_reg(exprasmlist,ppn.paraitem.paraloc[callerside].size,ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside]);
+                           else
+                             internalerror(200402081);
+                         end;
+{$endif cputargethasfixedstack}
+                       end;
+                     else
+                       internalerror(200402091);
                    end;
                    end;
-               end;
+                 end;
                ppn:=tcgcallparanode(ppn.right);
                ppn:=tcgcallparanode(ppn.right);
              end;
              end;
          end;
          end;
@@ -1157,7 +1208,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.152  2004-01-31 17:45:17  peter
+  Revision 1.153  2004-02-09 22:48:45  florian
+    * several fixes to parameter handling on arm
+
+  Revision 1.152  2004/01/31 17:45:17  peter
     * Change several $ifdef i386 to x86
     * Change several $ifdef i386 to x86
     * Change several OS_32 to OS_INT/OS_ADDR
     * Change several OS_32 to OS_INT/OS_ADDR
 
 

+ 39 - 9
compiler/paramgr.pas

@@ -121,6 +121,7 @@ unit paramgr;
           procedure splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);virtual;
           procedure splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);virtual;
 
 
           procedure alloctempregs(list: taasmoutput;var locpara:tparalocation);virtual;
           procedure alloctempregs(list: taasmoutput;var locpara:tparalocation);virtual;
+          procedure alloctempparaloc(list: taasmoutput;calloption : tproccalloption;paraitem : tparaitem;var locpara:tparalocation);virtual;
        end;
        end;
 
 
 
 
@@ -132,7 +133,7 @@ implementation
 
 
     uses
     uses
        cpuinfo,systems,
        cpuinfo,systems,
-       cgobj,
+       cgobj,tgobj,
        defutil,verbose;
        defutil,verbose;
 
 
     { true if uses a parameter as return value }
     { true if uses a parameter as return value }
@@ -339,17 +340,32 @@ implementation
 
 
 
 
     procedure tparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
     procedure tparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
+      var
+        href : treference;
       begin
       begin
         case loc.loc of
         case loc.loc of
-          LOC_REGISTER,
-          LOC_CREGISTER,
-          LOC_FPUREGISTER,
-          LOC_CFPUREGISTER,
-          LOC_MMREGISTER,
-          LOC_CMMREGISTER :
+          LOC_REGISTER, LOC_CREGISTER:
+            begin
+{$ifndef cpu64bit}
+              if (loc.size in [OS_64,OS_S64,OS_F64]) then
+                begin
+                  cg.ungetregister(list,loc.registerhigh);
+                  cg.ungetregister(list,loc.registerlow);
+                end
+              else
+{$endif cpu64bit}
+                cg.ungetregister(list,loc.register);
+            end;
+          LOC_MMREGISTER, LOC_CMMREGISTER,
+          LOC_FPUREGISTER, LOC_CFPUREGISTER:
             cg.ungetregister(list,loc.register);
             cg.ungetregister(list,loc.register);
           LOC_REFERENCE,LOC_CREFERENCE:
           LOC_REFERENCE,LOC_CREFERENCE:
-            { do nothing by default, most of the time it's the framepointer }
+            begin
+{$ifdef cputargethasfixedstack}
+              reference_reset_base(href,loc.reference.index,loc.reference.offset);
+              tg.ungettemp(list,href);
+{$endif cputargethasfixedstack}
+            end;
           else
           else
             internalerror(200306091);
             internalerror(200306091);
         end;
         end;
@@ -458,6 +474,17 @@ implementation
       end;
       end;
 
 
 
 
+   procedure tparamanager.alloctempparaloc(list: taasmoutput;calloption : tproccalloption;paraitem : tparaitem;var locpara:tparalocation);
+     var
+       href : treference;
+     begin
+       tg.gettemp(list,paraitem.paratype.def.size,tt_persistent,href);
+       locpara.loc:=LOC_REFERENCE;
+       locpara.reference.index:=href.base;
+       locpara.reference.offset:=href.offset;
+     end;
+
+
     function tparamanager.create_inline_paraloc_info(p : tabstractprocdef):longint;
     function tparamanager.create_inline_paraloc_info(p : tabstractprocdef):longint;
       var
       var
         hp : tparaitem;
         hp : tparaitem;
@@ -504,7 +531,10 @@ end.
 
 
 {
 {
    $Log$
    $Log$
-   Revision 1.69  2004-02-09 22:14:17  peter
+   Revision 1.70  2004-02-09 22:48:45  florian
+     * several fixes to parameter handling on arm
+
+   Revision 1.69  2004/02/09 22:14:17  peter
      * more x86_64 parameter fixes
      * more x86_64 parameter fixes
      * tparalocation.lochigh is now used to indicate if registerhigh
      * tparalocation.lochigh is now used to indicate if registerhigh
        is used and what the type is
        is used and what the type is