فهرست منبع

* call firstpass before allocation and codegeneration is started
* move leftover code from pass_2.generatecode() to psub

peter 22 سال پیش
والد
کامیت
9e66b09843
4فایلهای تغییر یافته به همراه214 افزوده شده و 214 حذف شده
  1. 5 72
      compiler/pass_2.pas
  2. 181 140
      compiler/psub.pas
  3. 21 1
      compiler/rgobj.pas
  4. 7 1
      compiler/x86/cgx86.pas

+ 5 - 72
compiler/pass_2.pas

@@ -37,10 +37,6 @@ uses
        allow_multi_pass2 : boolean;
        flowcontrol : tflowcontrol;
 
-{ produces assembler for the expression in variable p }
-{ and produces an assembler node at the end        }
-procedure generatecode(var p : tnode);
-
 { produces the actual code }
 function do_secondpass(var p : tnode) : boolean;
 procedure secondpass(var p : tnode);
@@ -210,78 +206,15 @@ implementation
          do_secondpass:=codegenerror;
       end;
 
-    procedure clearrefs(p : tnamedindexitem;arg:pointer);
-
-      begin
-         if (tsym(p).typ=varsym) then
-           if tvarsym(p).refs>1 then
-             tvarsym(p).refs:=1;
-      end;
-
-    procedure generatecode(var p : tnode);
-      begin
-         flowcontrol:=[];
-         { when size optimization only count occurrence }
-         if cs_littlesize in aktglobalswitches then
-           cg.t_times:=1
-         else
-           { reference for repetition is 100 }
-           cg.t_times:=100;
-         { clear register count }
-         symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}clearrefs,nil);
-         symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}clearrefs,nil);
-         { firstpass everything }
-         do_firstpass(p);
-
-         { after pass 1, we should have all necessary information to set the temp. start location }
-         current_procinfo.set_first_temp_offset;
-         { only do secondpass if there are no errors }
-         if ErrorCount=0 then
-           begin
-              { caller paraloc info is also necessary in the stackframe_entry }
-              { code of the ppc (and possibly other processors)               }
-              if not current_procinfo.procdef.has_paraloc_info then
-                begin
-                  paramanager.create_paraloc_info(current_procinfo.procdef,callerside);
-                  current_procinfo.procdef.has_paraloc_info:=true;
-                end;
-
-              { process register variable stuff (JM) }
-{              assign_regvars(p);}
-{              load_regvars(current_procinfo.aktentrycode,p);}
-
-              { for the i386 it must be done in genexitcode because it has  }
-              { to add 'fstp' instructions when using fpu regvars and those }
-              { must come after the "exitlabel" (JM)                        }
-{$ifndef i386}
-{              cleanup_regvars(current_procinfo.aktexitcode);}
-{$endif i386}
-
-{              current_procinfo.allocate_framepointer_reg;}
-
-              do_secondpass(p);
-
-{$ifdef EXTDEBUG}
-{
-              for sr:=first_int_imreg to last_int_imreg do
-                if not(sr in rg.unusedregsint) then
-                  Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,sr,R_SUBNONE))+' not released');
-}
-{$endif EXTDEBUG}
-
-{$ifdef i386}
-              if assigned(current_procinfo.procdef) then
-                current_procinfo.procdef.fpu_used:=p.registersfpu;
-{$endif i386}
-
-           end;
-         current_procinfo.aktproccode.concatlist(exprasmlist);
-      end;
 
 end.
 {
   $Log$
-  Revision 1.72  2003-10-19 01:34:30  florian
+  Revision 1.73  2003-10-30 16:22:40  peter
+    * call firstpass before allocation and codegeneration is started
+    * move leftover code from pass_2.generatecode() to psub
+
+  Revision 1.72  2003/10/19 01:34:30  florian
     * some ppc stuff fixed
     * memory leak fixed
 

+ 181 - 140
compiler/psub.pas

@@ -566,6 +566,14 @@ implementation
       end;
 
 
+    procedure clearrefs(p : tnamedindexitem;arg:pointer);
+      begin
+         if (tsym(p).typ=varsym) then
+           if tvarsym(p).refs>1 then
+             tvarsym(p).refs:=1;
+      end;
+
+
     procedure tcgprocinfo.generate_code;
       var
         oldprocinfo : tprocinfo;
@@ -605,168 +613,197 @@ implementation
         { add parast/localst to symtablestack }
         add_to_symtablestack;
 
-        { set the start offset to the start of the temp area in the stack }
-        tg:=ttgobj.create;
+        { when size optimization only count occurrence }
+        if cs_littlesize in aktglobalswitches then
+          cg.t_times:=1
+        else
+          { reference for repetition is 100 }
+          cg.t_times:=100;
 
-        { Create register allocator }
-        cg.init_register_allocators;
+        { clear register count }
+        symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}clearrefs,nil);
+        symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}clearrefs,nil);
 
-        current_procinfo.set_first_temp_offset;
-        current_procinfo.generate_parameter_info;
+        { firstpass everything }
+        flowcontrol:=[];
+        do_firstpass(code);
 
-        { Allocate space in temp/registers for parast and localst }
-        aktfilepos:=entrypos;
-        gen_alloc_parast(aktproccode,tparasymtable(current_procinfo.procdef.parast));
-        if current_procinfo.procdef.localst.symtabletype=localsymtable then
-          gen_alloc_localst(aktproccode,tlocalsymtable(current_procinfo.procdef.localst));
-        if (cs_asm_source in aktglobalswitches) then
-          aktproccode.concat(Tai_comment.Create(strpnew('Temps start at '+std_regname(current_procinfo.framepointer)+
-              tostr_with_plus(tg.lasttemp))));
-
-        { Generate code to load register parameters in temps and insert local
-          copies for values parameters. This must be done before the code for the
-          body is generated because the localloc is updated.
-          Note: The generated code will be inserted after the code generation of
-          the body is finished, because only then the position is known }
-        aktfilepos:=entrypos;
-        gen_load_para_value(templist);
+        { only do secondpass if there are no errors }
+        if ErrorCount=0 then
+          begin
+            { set the start offset to the start of the temp area in the stack }
+            tg:=ttgobj.create;
 
-        { generate code for the body }
-        generatecode(code);
+            { Create register allocator }
+            cg.init_register_allocators;
 
-        { The position of the loadpara_asmnode is now known }
-        aktproccode.insertlistafter(loadpara_asmnode.currenttai,templist);
+            current_procinfo.set_first_temp_offset;
+            current_procinfo.generate_parameter_info;
 
-        { first generate entry and initialize code with the correct
-          position and switches }
-        aktfilepos:=entrypos;
-        aktlocalswitches:=entryswitches;
-        gen_entry_code(templist);
-        aktproccode.insertlistafter(entry_asmnode.currenttai,templist);
-        gen_initialize_code(templist,false);
-        aktproccode.insertlistafter(init_asmnode.currenttai,templist);
-
-        { now generate finalize and exit code with the correct position
-          and switches }
-        aktfilepos:=exitpos;
-        aktlocalswitches:=exitswitches;
-        gen_finalize_code(templist,false);
-        { the finalcode must be concated if there was no position available,
-          using insertlistafter will result in an insert at the start
-          when currentai=nil }
-        if assigned(final_asmnode.currenttai) then
-          aktproccode.insertlistafter(final_asmnode.currenttai,templist)
-        else
-          aktproccode.concatlist(templist);
-        { insert exit label at the correct position }
-        cg.a_label(templist,current_procinfo.aktexitlabel);
-        if assigned(exitlabel_asmnode.currenttai) then
-          aktproccode.insertlistafter(exitlabel_asmnode.currenttai,templist)
-        else
-          aktproccode.concatlist(templist);
-        { exit code }
-        gen_exit_code(templist);
-        aktproccode.concatlist(templist);
+            { Allocate space in temp/registers for parast and localst }
+            aktfilepos:=entrypos;
+            gen_alloc_parast(aktproccode,tparasymtable(current_procinfo.procdef.parast));
+            if current_procinfo.procdef.localst.symtabletype=localsymtable then
+              gen_alloc_localst(aktproccode,tlocalsymtable(current_procinfo.procdef.localst));
+            if (cs_asm_source in aktglobalswitches) then
+              aktproccode.concat(Tai_comment.Create(strpnew('Temps start at '+std_regname(current_procinfo.framepointer)+
+                  tostr_with_plus(tg.lasttemp))));
+
+            { Generate code to load register parameters in temps and insert local
+              copies for values parameters. This must be done before the code for the
+              body is generated because the localloc is updated.
+              Note: The generated code will be inserted after the code generation of
+              the body is finished, because only then the position is known }
+            aktfilepos:=entrypos;
+            gen_load_para_value(templist);
+
+            { caller paraloc info is also necessary in the stackframe_entry
+              code of the ppc (and possibly other processors)               }
+            if not procdef.has_paraloc_info then
+              begin
+                paramanager.create_paraloc_info(procdef,callerside);
+                procdef.has_paraloc_info:=true;
+              end;
+
+            { generate code for the node tree }
+            do_secondpass(code);
+            current_procinfo.aktproccode.concatlist(exprasmlist);
+{$ifdef i386}
+            procdef.fpu_used:=code.registersfpu;
+{$endif i386}
+
+            { The position of the loadpara_asmnode is now known }
+            aktproccode.insertlistafter(loadpara_asmnode.currenttai,templist);
+
+            { first generate entry and initialize code with the correct
+              position and switches }
+            aktfilepos:=entrypos;
+            aktlocalswitches:=entryswitches;
+            gen_entry_code(templist);
+            aktproccode.insertlistafter(entry_asmnode.currenttai,templist);
+            gen_initialize_code(templist,false);
+            aktproccode.insertlistafter(init_asmnode.currenttai,templist);
+
+            { now generate finalize and exit code with the correct position
+              and switches }
+            aktfilepos:=exitpos;
+            aktlocalswitches:=exitswitches;
+            gen_finalize_code(templist,false);
+            { the finalcode must be concated if there was no position available,
+              using insertlistafter will result in an insert at the start
+              when currentai=nil }
+            if assigned(final_asmnode.currenttai) then
+              aktproccode.insertlistafter(final_asmnode.currenttai,templist)
+            else
+              aktproccode.concatlist(templist);
+            { insert exit label at the correct position }
+            cg.a_label(templist,current_procinfo.aktexitlabel);
+            if assigned(exitlabel_asmnode.currenttai) then
+              aktproccode.insertlistafter(exitlabel_asmnode.currenttai,templist)
+            else
+              aktproccode.concatlist(templist);
+            { exit code }
+            gen_exit_code(templist);
+            aktproccode.concatlist(templist);
 
 {$ifdef OLDREGVARS}
-        { note: this must be done only after as much code as possible has  }
-        {   been generated. The result is that when you ungetregister() a  }
-        {   regvar, it will actually free the regvar (and alse free the    }
-        {   the regvars at the same time). Doing this too early will       }
-        {   confuse the register allocator, as the regvars will still be   }
-        {   used. It should be done before loading the result regs (so     }
-        {   they don't conflict with the regvars) and before               }
-        {   gen_entry_code (that one has to be able to allocate the        }
-        {   regvars again) (JM)                                            }
-        free_regvars(aktproccode);
+            { note: this must be done only after as much code as possible has  }
+            {   been generated. The result is that when you ungetregister() a  }
+            {   regvar, it will actually free the regvar (and alse free the    }
+            {   the regvars at the same time). Doing this too early will       }
+            {   confuse the register allocator, as the regvars will still be   }
+            {   used. It should be done before loading the result regs (so     }
+            {   they don't conflict with the regvars) and before               }
+            {   gen_entry_code (that one has to be able to allocate the        }
+            {   regvars again) (JM)                                            }
+            free_regvars(aktproccode);
 {$endif OLDREGVARS}
 
-        { add code that will load the return value, this is not done
-          for assembler routines when they didn't reference the result
-          variable }
-        usesacc:=false;
-        usesfpu:=false;
-        usesacchi:=false;
-        gen_load_return_value(templist,usesacc,usesacchi,usesfpu);
-        aktproccode.concatlist(templist);
+            { add code that will load the return value, this is not done
+              for assembler routines when they didn't reference the result
+              variable }
+            usesacc:=false;
+            usesfpu:=false;
+            usesacchi:=false;
+            gen_load_return_value(templist,usesacc,usesacchi,usesfpu);
+            aktproccode.concatlist(templist);
 
-        { generate symbol and save end of header position }
-        aktfilepos:=entrypos;
-        gen_proc_symbol(templist);
-        headertai:=tai(templist.last);
-        { insert symbol }
-        aktproccode.insertlist(templist);
+            { generate symbol and save end of header position }
+            aktfilepos:=entrypos;
+            gen_proc_symbol(templist);
+            headertai:=tai(templist.last);
+            { insert symbol }
+            aktproccode.insertlist(templist);
 
-        { Free space in temp/registers for parast and localst, must be
-          done after gen_entry_code }
-        aktfilepos:=exitpos;
-        if current_procinfo.procdef.localst.symtabletype=localsymtable then
-          gen_free_localst(aktproccode,tlocalsymtable(current_procinfo.procdef.localst));
-        gen_free_parast(aktproccode,tparasymtable(current_procinfo.procdef.parast));
+            { Free space in temp/registers for parast and localst, must be
+              done after gen_entry_code }
+            aktfilepos:=exitpos;
+            if current_procinfo.procdef.localst.symtabletype=localsymtable then
+              gen_free_localst(aktproccode,tlocalsymtable(current_procinfo.procdef.localst));
+            gen_free_parast(aktproccode,tparasymtable(current_procinfo.procdef.parast));
 
-        { The procedure body is finished, we can now
-          allocate the registers }
-        if not(cs_no_regalloc in aktglobalswitches) then
-          begin
-            cg.do_register_allocation(aktproccode,headertai);
+            { The procedure body is finished, we can now
+              allocate the registers }
+            if not(cs_no_regalloc in aktglobalswitches) then
+              begin
+                cg.do_register_allocation(aktproccode,headertai);
 (*
 {$ifndef NoOpt}
-            if (cs_optimize in aktglobalswitches) and
-            { do not optimize pure assembler procedures }
-               not(pi_is_assembler in current_procinfo.flags)  then
-              optimize(aktproccode);
+                if (cs_optimize in aktglobalswitches) and
+                { do not optimize pure assembler procedures }
+                   not(pi_is_assembler in current_procinfo.flags)  then
+                  optimize(aktproccode);
 {$endif NoOpt}
 *)
-          end;
+              end;
 
-        {$warning fixme translate_regvars}
-{        translate_regvars(aktproccode,rg.colour);}
-        { Add save and restore of used registers }
-        aktfilepos:=entrypos;
-        gen_save_used_regs(templist);
-        aktproccode.insertlistafter(headertai,templist);
-        aktfilepos:=exitpos;
-        gen_restore_used_regs(aktproccode,usesacc,usesacchi,usesfpu);
-        { Add stack allocation code after header }
-        aktfilepos:=entrypos;
-        gen_stackalloc_code(templist);
-        aktproccode.insertlistafter(headertai,templist);
-        { Add exit code at the end }
-        aktfilepos:=exitpos;
-        gen_stackfree_code(templist,usesacc,usesacchi);
-        aktproccode.concatlist(templist);
-        { Add end symbol and debug info }
-        aktfilepos:=exitpos;
-        gen_proc_symbol_end(templist);
-        aktproccode.concatlist(templist);
+            { Add save and restore of used registers }
+            aktfilepos:=entrypos;
+            gen_save_used_regs(templist);
+            aktproccode.insertlistafter(headertai,templist);
+            aktfilepos:=exitpos;
+            gen_restore_used_regs(aktproccode,usesacc,usesacchi,usesfpu);
+            { Add stack allocation code after header }
+            aktfilepos:=entrypos;
+            gen_stackalloc_code(templist);
+            aktproccode.insertlistafter(headertai,templist);
+            { Add exit code at the end }
+            aktfilepos:=exitpos;
+            gen_stackfree_code(templist,usesacc,usesacchi);
+            aktproccode.concatlist(templist);
+            { Add end symbol and debug info }
+            aktfilepos:=exitpos;
+            gen_proc_symbol_end(templist);
+            aktproccode.concatlist(templist);
 
-        { save local data (casetable) also in the same file }
-        if assigned(aktlocaldata) and
-           (not aktlocaldata.empty) then
-         begin
-           { because of the limited constant size of the arm, all data access is done pc relative }
-           if target_info.cpu=cpu_arm then
-             aktproccode.concatlist(aktlocaldata)
-           else
+            { save local data (casetable) also in the same file }
+            if assigned(aktlocaldata) and
+               (not aktlocaldata.empty) then
              begin
-               aktproccode.concat(Tai_section.Create(sec_data));
-               aktproccode.concatlist(aktlocaldata);
-               aktproccode.concat(Tai_section.Create(sec_code));
-             end;
-        end;
+               { because of the limited constant size of the arm, all data access is done pc relative }
+               if target_info.cpu=cpu_arm then
+                 aktproccode.concatlist(aktlocaldata)
+               else
+                 begin
+                   aktproccode.concat(Tai_section.Create(sec_data));
+                   aktproccode.concatlist(aktlocaldata);
+                   aktproccode.concat(Tai_section.Create(sec_code));
+                 end;
+            end;
 
-        { add the procedure to the codesegment }
-        if (cs_create_smart in aktmoduleswitches) then
-          codesegment.concat(Tai_cut.Create);
-        codesegment.concatlist(aktproccode);
+            { add the procedure to the codesegment }
+            if (cs_create_smart in aktmoduleswitches) then
+              codesegment.concat(Tai_cut.Create);
+            codesegment.concatlist(aktproccode);
 
-        { only now we can remove the temps }
-        tg.resettempgen;
+            { only now we can remove the temps }
+            tg.resettempgen;
 
-        { stop tempgen and ra }
-        tg.free;
-        cg.done_register_allocators;
-        tg:=nil;
+            { stop tempgen and ra }
+            tg.free;
+            cg.done_register_allocators;
+            tg:=nil;
+          end;
 
         { restore symtablestack }
         remove_from_symtablestack;
@@ -1266,7 +1303,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.167  2003-10-24 17:40:23  peter
+  Revision 1.168  2003-10-30 16:22:40  peter
+    * call firstpass before allocation and codegeneration is started
+    * move leftover code from pass_2.generatecode() to psub
+
+  Revision 1.167  2003/10/24 17:40:23  peter
     * cleanup of the entry and exit code insertion
 
   Revision 1.166  2003/10/21 15:14:33  peter

+ 21 - 1
compiler/rgobj.pas

@@ -235,6 +235,7 @@ unit rgobj;
         procedure translate_registers(list:Taasmoutput);
         {# Adds an interference edge.}
         procedure add_edge(u,v:Tsuperregister);
+        procedure check_unreleasedregs;
 
         unusedregs        : Tsuperregisterset;
 
@@ -1801,10 +1802,29 @@ implementation
         end;
     end;
 
+
+    procedure Trgobj.check_unreleasedregs;
+{$ifdef EXTDEBUG}
+      var
+        sr : tsuperregister;
+{$endif EXTDEBUG}
+      begin
+{$ifdef EXTDEBUG}
+        for sr:=first_imaginary to maxreg-1 do
+          if not(supregset_in(unusedregs,sr)) then
+            Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,sr,R_SUBNONE))+' not released');
+{$endif EXTDEBUG}
+      end;
+
+
 end.
 {
   $Log$
-  Revision 1.92  2003-10-29 21:29:14  jonas
+  Revision 1.93  2003-10-30 16:22:40  peter
+    * call firstpass before allocation and codegeneration is started
+    * move leftover code from pass_2.generatecode() to psub
+
+  Revision 1.92  2003/10/29 21:29:14  jonas
     * some ALLOWDUPREG improvements
 
   Revision 1.91  2003/10/21 15:15:36  peter

+ 7 - 1
compiler/x86/cgx86.pas

@@ -310,9 +310,11 @@ unit cgx86;
 
     begin
       { Int }
+      rgint.check_unreleasedregs;
       rgint.do_register_allocation(list,headertai);
       rgint.translate_registers(list);
       { SSE }
+      rgmm.check_unreleasedregs;
       rgmm.do_register_allocation(list,headertai);
       rgmm.translate_registers(list);
     end;
@@ -1735,7 +1737,11 @@ unit cgx86;
 end.
 {
   $Log$
-  Revision 1.84  2003-10-29 21:24:14  jonas
+  Revision 1.85  2003-10-30 16:22:40  peter
+    * call firstpass before allocation and codegeneration is started
+    * move leftover code from pass_2.generatecode() to psub
+
+  Revision 1.84  2003/10/29 21:24:14  jonas
     + support for fpu temp parameters
     + saving/restoring of fpu register before/after a procedure call