Преглед изворни кода

* several fixes to parameter handling on arm

florian пре 21 година
родитељ
комит
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;
       begin
         { 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
                 (ops=2) and
                 (oper[0]^.typ=top_reg) and
@@ -422,7 +423,10 @@ implementation
 end.
 {
   $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
       removes moves of that particular register type. This is necessary so
       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 getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;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;
        end;
 
@@ -230,12 +230,12 @@ unit cpupara;
           begin
              if (hp.paratyp in [vs_var,vs_out]) then
                begin
-                 paradef := voidpointertype.def;
-                 loc := LOC_REGISTER;
+                 paradef:=voidpointertype.def;
+                 loc:=LOC_REGISTER;
                end
              else
                begin
-                 paradef := hp.paratype.def;
+                 paradef:=hp.paratype.def;
                  loc:=getparaloc(p.proccalloption,paradef);
                end;
              { make sure all alignment bytes are 0 as well }
@@ -248,28 +248,28 @@ unit cpupara;
                      if paraloc.size = OS_NO then
                        paraloc.size := OS_ADDR;
                      is_64bit := paraloc.size in [OS_64,OS_S64,OS_F64];
+                     { this is not abi compliant }
                      if nextintreg<=(RS_R3-ord(is_64bit)) then
                        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
                      else
                         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;
                 LOC_FPUREGISTER:
@@ -346,12 +346,32 @@ unit cpupara;
        p.funcret_paraloc[side]:=paraloc;
      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
    paramanager:=tarmparamanager.create;
 end.
 {
   $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
 
   Revision 1.12  2004/01/20 23:18:00  florian

+ 5 - 1
compiler/fpcdefs.inc

@@ -81,6 +81,7 @@
 
 {$ifdef arm}
   {$define cpuneedsdiv32helper}
+  {$define cputargethasfixedstack}
   {$define noopt}
   {$define oldset}
 {$endif arm}
@@ -93,7 +94,10 @@
 
 {
   $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
 
   Revision 1.30  2003/12/14 22:41:46  peter

+ 97 - 43
compiler/ncgcal.pas

@@ -104,8 +104,18 @@ implementation
       begin
          { Allocate (temporary) paralocation }
          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;
 
 
@@ -288,7 +298,6 @@ implementation
       end;
 
 
-
     procedure tcgcallparanode.secondcallparan;
       var
          otlabel,
@@ -602,7 +611,7 @@ implementation
          oldpushedparasize : longint;
          { adress returned from an I/O-error }
          { help reference pointer }
-         href : treference;
+         href,href2 : treference;
          pop_size : longint;
          pvreg,
          vmtreg : tregister;
@@ -616,52 +625,94 @@ implementation
            ppn:=tcgcallparanode(left);
            while assigned(ppn) do
              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}
-                     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}
 {$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}
-                       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);
-                   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;
                ppn:=tcgcallparanode(ppn.right);
              end;
          end;
@@ -1157,7 +1208,10 @@ begin
 end.
 {
   $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 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 alloctempregs(list: taasmoutput;var locpara:tparalocation);virtual;
+          procedure alloctempparaloc(list: taasmoutput;calloption : tproccalloption;paraitem : tparaitem;var locpara:tparalocation);virtual;
        end;
 
 
@@ -132,7 +133,7 @@ implementation
 
     uses
        cpuinfo,systems,
-       cgobj,
+       cgobj,tgobj,
        defutil,verbose;
 
     { true if uses a parameter as return value }
@@ -339,17 +340,32 @@ implementation
 
 
     procedure tparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
+      var
+        href : treference;
       begin
         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);
           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
             internalerror(200306091);
         end;
@@ -458,6 +474,17 @@ implementation
       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;
       var
         hp : tparaitem;
@@ -504,7 +531,10 @@ end.
 
 {
    $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
      * tparalocation.lochigh is now used to indicate if registerhigh
        is used and what the type is