Browse Source

* support register parameters for inlined procedures + some inline
cleanups

Jonas Maebe 21 năm trước cách đây
mục cha
commit
f1bda1700a
4 tập tin đã thay đổi với 222 bổ sung165 xóa
  1. 42 17
      compiler/cgobj.pas
  2. 132 105
      compiler/ncgcal.pas
  3. 30 4
      compiler/ncgutil.pas
  4. 18 39
      compiler/paramgr.pas

+ 42 - 17
compiler/cgobj.pas

@@ -839,32 +839,44 @@ implementation
 {$ifndef cpu64bit}
               if (locpara.size in [OS_S64,OS_64]) then
                 begin
-                  getexplicitregister(list,locpara.registerlow);
-                  getexplicitregister(list,locpara.registerhigh);
-                  ungetregister(list,locpara.registerlow);
-                  ungetregister(list,locpara.registerhigh);
+                  if getsupreg(locpara.registerlow)<first_int_imreg then
+                    begin
+                      getexplicitregister(list,locpara.registerlow);
+                      getexplicitregister(list,locpara.registerhigh);
+                      ungetregister(list,locpara.registerlow);
+                      ungetregister(list,locpara.registerhigh);
+                    end;
                   cg64.a_load64_reg_ref(list,locpara.register64,ref)
                 end
               else
 {$endif cpu64bit}
                 begin
-                  getexplicitregister(list,locpara.register);
-                  ungetregister(list,locpara.register);
+                  if getsupreg(locpara.register)<first_int_imreg then
+                    begin
+                      getexplicitregister(list,locpara.register);
+                      ungetregister(list,locpara.register);
+                    end;
                   a_load_reg_ref(list,locpara.size,locpara.size,locpara.register,ref);
                 end;
             end;
           LOC_MMREGISTER,
           LOC_CMMREGISTER:
             begin
-              getexplicitregister(list,locpara.register);
-              ungetregister(list,locpara.register);
+              if getsupreg(locpara.register)<first_mm_imreg then
+                begin
+                  getexplicitregister(list,locpara.register);
+                  ungetregister(list,locpara.register);
+                end;
               a_loadmm_reg_ref(list,locpara.size,locpara.size,locpara.register,ref,shuffle);
             end;
           LOC_FPUREGISTER,
           LOC_CFPUREGISTER:
             begin
-              getexplicitregister(list,locpara.register);
-              ungetregister(list,locpara.register);
+              if getsupreg(locpara.register)<first_fpu_imreg then
+                begin
+                  getexplicitregister(list,locpara.register);
+                  ungetregister(list,locpara.register);
+                end;
               a_loadfpu_reg_ref(list,locpara.size,locpara.register,ref);
             end;
           else
@@ -883,8 +895,11 @@ implementation
             begin
               if not(locpara.size in [OS_S64,OS_64]) then
                 begin
-                  getexplicitregister(list,locpara.register);
-                  ungetregister(list,locpara.register);
+                  if getsupreg(locpara.register)<first_int_imreg then
+                    begin
+                      getexplicitregister(list,locpara.register);
+                      ungetregister(list,locpara.register);
+                    end;
 {
                   This is now a normal imaginary register, allocated the usual way (JM)
                   getexplicitregister(list,reg);
@@ -898,8 +913,11 @@ implementation
           LOC_FPUREGISTER:
             begin
 
-              getexplicitregister(list,locpara.register);
-              ungetregister(list,locpara.register);
+              if getsupreg(locpara.register)<first_fpu_imreg then
+                begin
+                  getexplicitregister(list,locpara.register);
+                  ungetregister(list,locpara.register);
+                end;
 {
               This is now a normal imaginary register, allocated the usual way (JM)
               getexplicitregister(list,reg);
@@ -909,8 +927,11 @@ implementation
           LOC_MMREGISTER,
           LOC_CMMREGISTER:
             begin
-              getexplicitregister(list,locpara.register);
-              ungetregister(list,locpara.register);
+              if getsupreg(locpara.register)<first_mm_imreg then
+                begin
+                  getexplicitregister(list,locpara.register);
+                  ungetregister(list,locpara.register);
+                end;
 {
               This is now a normal imaginary register, allocated the usual way (JM)
               getexplicitregister(list,reg);
@@ -2174,7 +2195,11 @@ finalization
 end.
 {
   $Log$
-  Revision 1.167  2004-07-03 11:47:04  peter
+  Revision 1.168  2004-07-09 23:41:04  jonas
+    * support register parameters for inlined procedures + some inline
+      cleanups
+
+  Revision 1.167  2004/07/03 11:47:04  peter
     * fix rangecheck error when assigning u32bit=s32bit
 
   Revision 1.166  2004/06/20 08:55:28  florian

+ 132 - 105
compiler/ncgcal.pas

@@ -47,6 +47,8 @@ interface
           procedure release_para_temps;
           procedure normal_pass_2;
           procedure inlined_pass_2;
+          procedure pushparas;
+          procedure freeparas;
        protected
           framepointer_paraloc : tparalocation;
           refcountedtemp : treference;
@@ -636,6 +638,125 @@ implementation
       end;
 
 
+     procedure tcgcallnode.pushparas;
+       var
+         ppn : tcgcallparanode;
+       begin
+         { copy all resources to the allocated registers }
+         ppn:=tcgcallparanode(left);
+         while assigned(ppn) do
+           begin
+             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
+                       if not assigned(inlinecode) then
+                         begin
+                           paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
+                           paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
+                         end;
+  {$ifdef sparc}
+                       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
+  {$endif cpu64bit}
+                         cg.a_load_reg_reg(exprasmlist,ppn.tempparaloc.size,ppn.tempparaloc.size,
+                             ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register);
+                     end;
+                   LOC_FPUREGISTER:
+                     begin
+                       if not assigned(inlinecode) then
+                         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;
+                     end;
+                   LOC_MMREGISTER:
+                     begin
+                       if not assigned(inlinecode) then
+                         begin
+                           paramanager.freeparaloc(exprasmlist,ppn.tempparaloc);
+                           paramanager.allocparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
+                         end;
+                       cg.a_loadmm_reg_reg(exprasmlist,ppn.tempparaloc.size,
+                         ppn.tempparaloc.size,ppn.tempparaloc.register,ppn.paraitem.paraloc[callerside].register,mms_movescalar);
+                     end;
+                   LOC_REFERENCE:
+                     begin
+                       if not assigned(inlinecode) then
+                         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);
+                                 if ppn.paraitem.paraloc[callerside].size=OS_NO then
+                                   cg.a_param_copy_ref(exprasmlist,ppn.paraitem.paratype.def.size,href,ppn.paraitem.paraloc[callerside])
+                                 else
+                                   cg.a_param_ref(exprasmlist,ppn.paraitem.paraloc[callerside].size,href,ppn.paraitem.paraloc[callerside]);
+                               end;
+                             LOC_REGISTER:
+      {$ifndef cpu64bit}
+                               if ppn.tempparaloc.size in [OS_64,OS_S64] then
+                                 cg64.a_param64_reg(exprasmlist,ppn.tempparaloc.register64,ppn.paraitem.paraloc[callerside])
+                               else
+      {$endif cpu64bit}
+                                 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;
+                     end;
+                   else
+                     internalerror(200402091);
+                 end;
+               end;
+             ppn:=tcgcallparanode(ppn.right);
+           end;
+       end;
+
+     procedure tcgcallnode.freeparas;
+       var
+         ppn : tcgcallparanode;
+       begin
+         { free the resources allocated for the parameters }
+         ppn:=tcgcallparanode(left);
+         while assigned(ppn) do
+           begin
+             if not assigned(inlinecode) or
+                (ppn.paraitem.paraloc[callerside].loc <> LOC_REFERENCE) then
+               paramanager.freeparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
+             ppn:=tcgcallparanode(ppn.right);
+           end;
+       end;
+
+
+
     procedure tcgcallnode.normal_pass_2;
       var
          regs_to_push_fpu,
@@ -647,109 +768,6 @@ implementation
          vmtreg : tregister;
          oldaktcallnode : tcallnode;
 
-         procedure pushparas;
-         var
-           ppn : tcgcallparanode;
-         begin
-           { copy all resources to the allocated registers }
-           ppn:=tcgcallparanode(left);
-           while assigned(ppn) do
-             begin
-               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;
-{$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
-{$endif cpu64bit}
-                           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_MMREGISTER:
-                       begin
-                         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,mms_movescalar);
-                       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);
-                               if ppn.paraitem.paraloc[callerside].size=OS_NO then
-                                 cg.a_param_copy_ref(exprasmlist,ppn.paraitem.paratype.def.size,href,ppn.paraitem.paraloc[callerside])
-                               else
-                                 cg.a_param_ref(exprasmlist,ppn.paraitem.paraloc[callerside].size,href,ppn.paraitem.paraloc[callerside]);
-                             end;
-                           LOC_REGISTER:
-{$ifndef cpu64bit}
-                             if ppn.tempparaloc.size in [OS_64,OS_S64] then
-                               cg64.a_param64_reg(exprasmlist,ppn.tempparaloc.register64,ppn.paraitem.paraloc[callerside])
-                             else
-{$endif cpu64bit}
-                               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;
-               ppn:=tcgcallparanode(ppn.right);
-             end;
-         end;
-
-       procedure freeparas;
-         var
-           ppn : tcgcallparanode;
-         begin
-           { free the resources allocated for the parameters }
-           ppn:=tcgcallparanode(left);
-           while assigned(ppn) do
-             begin
-               paramanager.freeparaloc(exprasmlist,ppn.paraitem.paraloc[callerside]);
-               ppn:=tcgcallparanode(ppn.right);
-             end;
-         end;
-
       begin
          if not assigned(procdefinition) or
             not procdefinition.has_paraloc_info then
@@ -1067,7 +1085,10 @@ implementation
          oldaktcallnode:=aktcallnode;
          aktcallnode:=self;
          if assigned(left) then
-           tcallparanode(left).secondcallparan;
+           begin
+             tcallparanode(left).secondcallparan;
+             pushparas;
+           end;
          aktcallnode:=oldaktcallnode;
 
          { create temp procinfo that will be used for the inlinecode tree }
@@ -1112,6 +1133,8 @@ implementation
 {$endif GDB}
 
          gen_load_para_value(inlineentrycode);
+         { now that we've loaded the para's, free them }
+         freeparas;
          gen_initialize_code(inlineentrycode,true);
          if po_assembler in current_procinfo.procdef.procoptions then
            inlineentrycode.insert(Tai_marker.Create(asmblockstart));
@@ -1227,7 +1250,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.170  2004-06-29 20:56:46  peter
+  Revision 1.171  2004-07-09 23:41:04  jonas
+    * support register parameters for inlined procedures + some inline
+      cleanups
+
+  Revision 1.170  2004/06/29 20:56:46  peter
     * constructors don't return in parameter
 
   Revision 1.169  2004/06/20 08:55:29  florian

+ 30 - 4
compiler/ncgutil.pas

@@ -1925,6 +1925,8 @@ implementation
       var
         sym : tsym;
       begin
+        if (po_assembler in current_procinfo.procdef.procoptions) then
+          exit;
         sym:=tsym(st.symindex.first);
         while assigned(sym) do
           begin
@@ -1932,10 +1934,32 @@ implementation
               begin
                 with tvarsym(sym) do
                   begin
-{$warning TODO Allocate register paras}
+                    { for localloc <> LOC_REFERENCE, we need regvar support inside inlined procedures }
                     localloc.loc:=LOC_REFERENCE;
                     localloc.size:=int_cgsize(paramanager.push_size(varspez,vartype.def,pocall_inline));
                     tg.GetLocal(list,tcgsize2size[localloc.size],vartype.def,localloc.reference);
+                    case paraitem.paraloc[calleeside].loc of
+                      LOC_FPUREGISTER:
+                        begin
+                          paraitem.paraloc[calleeside].register := cg.getfpuregister(list,paraitem.paraloc[calleeside].size);
+                          paraitem.paraloc[callerside] := paraitem.paraloc[calleeside];
+                        end;
+                      LOC_REGISTER:
+                        begin
+                          paraitem.paraloc[calleeside].register := cg.getintregister(list,paraitem.paraloc[calleeside].size);
+                          paraitem.paraloc[callerside] := paraitem.paraloc[calleeside];
+                        end;
+                      LOC_MMREGISTER:
+                        begin
+                          paraitem.paraloc[calleeside].register := cg.getmmregister(list,paraitem.paraloc[calleeside].size);
+                          paraitem.paraloc[callerside] := paraitem.paraloc[calleeside];
+                        end;
+                      LOC_REFERENCE:
+                        begin
+                          paraitem.paraloc[calleeside] := localloc;
+                          paraitem.paraloc[callerside] := localloc;
+                        end;
+                    end;
                     if cs_asm_source in aktglobalswitches then
                       begin
                         case localloc.loc of
@@ -1944,8 +1968,6 @@ implementation
                                 std_regname(localloc.reference.index)+tostr_with_plus(localloc.reference.offset))));
                         end;
                       end;
-                    paraitem.paraloc[callerside]:=localloc;
-                    paraitem.paraloc[calleeside]:=localloc;
                   end;
               end;
             sym:=tsym(sym.indexnext);
@@ -2067,7 +2089,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.210  2004-07-04 12:24:59  jonas
+  Revision 1.211  2004-07-09 23:41:04  jonas
+    * support register parameters for inlined procedures + some inline
+      cleanups
+
+  Revision 1.210  2004/07/04 12:24:59  jonas
     * fixed one regvar problem, but regvars are still broken since the dwarf
       merge...
 

+ 18 - 39
compiler/paramgr.pas

@@ -305,16 +305,21 @@ implementation
       begin
         case loc.loc of
           LOC_REGISTER,
-          LOC_CREGISTER,
+          LOC_CREGISTER:
+            begin
+              if getsupreg(loc.register)<first_int_imreg then
+                cg.getexplicitregister(list,loc.register);
+            end;
           LOC_FPUREGISTER,
-          LOC_CFPUREGISTER,
+          LOC_CFPUREGISTER:
+            begin
+              if getsupreg(loc.register)<first_fpu_imreg then
+                cg.getexplicitregister(list,loc.register);
+            end;
           LOC_MMREGISTER,
           LOC_CMMREGISTER :
             begin
-              { NR_NO means we don't need to allocate the parameter.
-                This is used for inlining parameters which allocates
-                the parameters in gen_alloc_parast (PFV) }
-              if loc.register<>NR_NO then
+              if getsupreg(loc.register)<first_mm_imreg then
                 cg.getexplicitregister(list,loc.register);
             end;
           LOC_REFERENCE,
@@ -495,40 +500,10 @@ implementation
 
 
     function tparamanager.create_inline_paraloc_info(p : tabstractprocdef):longint;
-      var
-        hp : tparaitem;
-        paraloc : tparalocation;
-        parasize : longint;
       begin
-        parasize:=0;
-        hp:=tparaitem(p.para.first);
-        while assigned(hp) do
-          begin
-            if push_addr_param(hp.paratyp,hp.paratype.def,p.proccalloption) then
-              paraloc.size:=OS_ADDR
-            else
-              paraloc.size:=def_cgsize(hp.paratype.def);
-            if paraloc.size=OS_NO then
-              internalerror(200309301);
-            { Indicate parameter is loaded in register, the register
-              will be allocated when the allocpara is called }
-            paraloc.loc:=LOC_REGISTER;
-            paraloc.register:=NR_NO;
-(*
-                paraloc.loc:=LOC_REFERENCE;
-                paraloc.reference.index:=NR_FRAME_POINTER_REG;
-                l:=push_size(hp.paratyp,hp.paratype.def,p.proccalloption);
-                varalign:=size_2_align(l);
-                paraloc.reference.offset:=parasize+target_info.first_parm_offset;
-                varalign:=used_align(varalign,p.paraalign,p.paraalign);
-                parasize:=align(parasize+l,varalign);
-*)
-            hp.paraloc[callerside]:=paraloc;
-            hp.paraloc[calleeside]:=paraloc;
-            hp:=tparaitem(hp.next);
-          end;
         { We need to return the size allocated }
-        result:=parasize;
+        create_paraloc_info(p,callerside);
+        result:=create_paraloc_info(p,calleeside);
       end;
 
 
@@ -540,7 +515,11 @@ end.
 
 {
    $Log$
-   Revision 1.76  2004-06-20 08:55:30  florian
+   Revision 1.77  2004-07-09 23:41:04  jonas
+     * support register parameters for inlined procedures + some inline
+       cleanups
+
+   Revision 1.76  2004/06/20 08:55:30  florian
      * logs truncated
 
    Revision 1.75  2004/06/16 20:07:09  florian