2
0
Эх сурвалжийг харах

* Improvements of tprocinfo class:
* Moved nestedprocs from tcgprocinfo to tprocinfo, in order to be able to access the entire nested procedure hierarchy without depending on psub.pas or code generator.
* Creating an instance of tprocinfo automatically inserts it into list of parent's nested procedures.
* nestedprocs list is created on demand. Public read-only access is provided by has_nestedprocs and get_first_nestedproc functions.
+ Method destroy_tree is provided for destroying the entire hierarchy of procinfo's. It can be called on any procinfo object in the tree.
+ Also added methods save_jump_labels and restore_jump_labels for asmlabel maintenance, which is currently being repeatedly done all over the codegenerator.

git-svn-id: trunk@17197 -

sergei 14 жил өмнө
parent
commit
1c01d52ea6

+ 2 - 14
compiler/fmodule.pas

@@ -544,7 +544,6 @@ implementation
     destructor tmodule.Destroy;
     destructor tmodule.Destroy;
       var
       var
         i : longint;
         i : longint;
-        hpi : tprocinfo;
       begin
       begin
         if assigned(unitmap) then
         if assigned(unitmap) then
           freemem(unitmap);
           freemem(unitmap);
@@ -582,12 +581,7 @@ implementation
                 current_specializedef:=nil;
                 current_specializedef:=nil;
               end;
               end;
             { release procinfo tree }
             { release procinfo tree }
-            while assigned(procinfo) do
-             begin
-               hpi:=tprocinfo(procinfo).parent;
-               tprocinfo(procinfo).free;
-               procinfo:=hpi;
-             end;
+            tprocinfo(procinfo).destroy_tree;
           end;
           end;
         DoneDebugInfo(self);
         DoneDebugInfo(self);
         used_units.free;
         used_units.free;
@@ -642,7 +636,6 @@ implementation
 
 
     procedure tmodule.reset;
     procedure tmodule.reset;
       var
       var
-        hpi : tprocinfo;
         i   : longint;
         i   : longint;
       begin
       begin
         if assigned(scanner) then
         if assigned(scanner) then
@@ -664,12 +657,7 @@ implementation
                 current_specializedef:=nil;
                 current_specializedef:=nil;
               end;
               end;
             { release procinfo tree }
             { release procinfo tree }
-            while assigned(procinfo) do
-             begin
-               hpi:=tprocinfo(procinfo).parent;
-               tprocinfo(procinfo).free;
-               procinfo:=hpi;
-             end;
+            tprocinfo(procinfo).destroy_tree;
           end;
           end;
         if assigned(asmdata) then
         if assigned(asmdata) then
           begin
           begin

+ 65 - 0
compiler/procinfo.pas

@@ -47,10 +47,17 @@ unit procinfo;
 
 
 
 
     type
     type
+       tsavedlabels = array[Boolean] of TAsmLabel;
+
        {# This object gives information on the current routine being
        {# This object gives information on the current routine being
           compiled.
           compiled.
        }
        }
        tprocinfo = class(tlinkedlistitem)
        tprocinfo = class(tlinkedlistitem)
+       private
+          { list to store the procinfo's of the nested procedures }
+          nestedprocs : tlinkedlist;
+          procedure addnestedproc(child: tprocinfo);
+       public
           { pointer to parent in nested procedures }
           { pointer to parent in nested procedures }
           parent : tprocinfo;
           parent : tprocinfo;
           {# the definition of the routine itself }
           {# the definition of the routine itself }
@@ -123,6 +130,18 @@ unit procinfo;
 
 
           { Allocate got register }
           { Allocate got register }
           procedure allocate_got_register(list: TAsmList);virtual;
           procedure allocate_got_register(list: TAsmList);virtual;
+
+          { Destroy the entire procinfo tree, starting from the outermost parent }
+          procedure destroy_tree;
+
+          { Store CurrTrueLabel and CurrFalseLabel to saved and generate new ones }
+          procedure save_jump_labels(out saved: tsavedlabels);
+
+          { Restore CurrTrueLabel and CurrFalseLabel from saved }
+          procedure restore_jump_labels(const saved: tsavedlabels);
+
+          function get_first_nestedproc: tprocinfo;
+          function has_nestedprocs: boolean;
        end;
        end;
        tcprocinfo = class of tprocinfo;
        tcprocinfo = class of tprocinfo;
 
 
@@ -165,15 +184,61 @@ implementation
         CurrTrueLabel:=nil;
         CurrTrueLabel:=nil;
         CurrFalseLabel:=nil;
         CurrFalseLabel:=nil;
         maxpushedparasize:=0;
         maxpushedparasize:=0;
+        if Assigned(parent) and (parent.procdef.parast.symtablelevel>=normal_function_level) then
+          parent.addnestedproc(Self);
       end;
       end;
 
 
 
 
     destructor tprocinfo.destroy;
     destructor tprocinfo.destroy;
       begin
       begin
+         nestedprocs.free;
          aktproccode.free;
          aktproccode.free;
          aktlocaldata.free;
          aktlocaldata.free;
       end;
       end;
 
 
+    procedure tprocinfo.destroy_tree;
+      var
+        hp: tprocinfo;
+      begin
+        hp:=Self;
+        while Assigned(hp.parent) do
+          hp:=hp.parent;
+        hp.Free;
+      end;
+
+    procedure tprocinfo.addnestedproc(child: tprocinfo);
+      begin
+        if nestedprocs=nil then
+          nestedprocs:=TLinkedList.Create;
+        nestedprocs.insert(child);
+      end;
+
+    function tprocinfo.get_first_nestedproc: tprocinfo;
+      begin
+        if assigned(nestedprocs) then
+          result:=tprocinfo(nestedprocs.first)
+        else
+          result:=nil;
+      end;
+
+    function tprocinfo.has_nestedprocs: boolean;
+      begin
+        result:=assigned(nestedprocs) and (nestedprocs.count>0);
+      end;
+
+    procedure tprocinfo.save_jump_labels(out saved: tsavedlabels);
+      begin
+        saved[false]:=CurrFalseLabel;
+        saved[true]:=CurrTrueLabel;
+        current_asmdata.getjumplabel(CurrTrueLabel);
+        current_asmdata.getjumplabel(CurrFalseLabel);
+      end;
+
+    procedure tprocinfo.restore_jump_labels(const saved: tsavedlabels);
+      begin
+        CurrFalseLabel:=saved[false];
+        CurrTrueLabel:=saved[true];
+      end;
 
 
     procedure tprocinfo.allocate_push_parasize(size:longint);
     procedure tprocinfo.allocate_push_parasize(size:longint);
       begin
       begin

+ 6 - 19
compiler/psub.pas

@@ -45,10 +45,7 @@ interface
         stackcheck_asmnode,
         stackcheck_asmnode,
         init_asmnode,
         init_asmnode,
         final_asmnode : tasmnode;
         final_asmnode : tasmnode;
-        { list to store the procinfo's of the nested procedures }
-        nestedprocs : tlinkedlist;
         dfabuilder : TDFABuilder;
         dfabuilder : TDFABuilder;
-        constructor create(aparent:tprocinfo);override;
         destructor  destroy;override;
         destructor  destroy;override;
         procedure printproc(pass:string);
         procedure printproc(pass:string);
         procedure generate_code;
         procedure generate_code;
@@ -555,16 +552,8 @@ implementation
                                   TCGProcInfo
                                   TCGProcInfo
 ****************************************************************************}
 ****************************************************************************}
 
 
-    constructor tcgprocinfo.create(aparent:tprocinfo);
-      begin
-        inherited Create(aparent);
-        nestedprocs:=tlinkedlist.create;
-      end;
-
-
      destructor tcgprocinfo.destroy;
      destructor tcgprocinfo.destroy;
        begin
        begin
-         nestedprocs.free;
          if assigned(code) then
          if assigned(code) then
            code.free;
            code.free;
          inherited destroy;
          inherited destroy;
@@ -794,10 +783,10 @@ implementation
 
 
     function tcgprocinfo.has_assembler_child : boolean;
     function tcgprocinfo.has_assembler_child : boolean;
       var
       var
-        hp : tcgprocinfo;
+        hp : tprocinfo;
       begin
       begin
         result:=false;
         result:=false;
-        hp:=tcgprocinfo(nestedprocs.first);
+        hp:=get_first_nestedproc;
         while assigned(hp) do
         while assigned(hp) do
           begin
           begin
             if (hp.flags*[pi_has_assembler_block,pi_is_assembler])<>[] then
             if (hp.flags*[pi_has_assembler_block,pi_is_assembler])<>[] then
@@ -805,7 +794,7 @@ implementation
                 result:=true;
                 result:=true;
                 exit;
                 exit;
               end;
               end;
-            hp:=tcgprocinfo(hp.next);
+            hp:=tprocinfo(hp.next);
           end;
           end;
       end;
       end;
 
 
@@ -1549,7 +1538,7 @@ implementation
           { generate code for this procedure }
           { generate code for this procedure }
           pi.generate_code;
           pi.generate_code;
           { process nested procs }
           { process nested procs }
-          hpi:=tcgprocinfo(pi.nestedprocs.first);
+          hpi:=tcgprocinfo(pi.get_first_nestedproc);
           while assigned(hpi) do
           while assigned(hpi) do
            begin
            begin
              do_generate_code(hpi);
              do_generate_code(hpi);
@@ -1602,7 +1591,7 @@ implementation
         { We can't support inlining for procedures that have nested
         { We can't support inlining for procedures that have nested
           procedures because the nested procedures use a fixed offset
           procedures because the nested procedures use a fixed offset
           for accessing locals in the parent procedure (PFV) }
           for accessing locals in the parent procedure (PFV) }
-        if (tcgprocinfo(current_procinfo).nestedprocs.count>0) then
+        if current_procinfo.has_nestedprocs then
           begin
           begin
             if (df_generic in current_procinfo.procdef.defoptions) then
             if (df_generic in current_procinfo.procdef.defoptions) then
               Comment(V_Error,'Generic methods cannot have nested procedures')
               Comment(V_Error,'Generic methods cannot have nested procedures')
@@ -1618,9 +1607,7 @@ implementation
         { When it's a nested procedure then defer the code generation,
         { When it's a nested procedure then defer the code generation,
           when back at normal function level then generate the code
           when back at normal function level then generate the code
           for all defered nested procedures and the current procedure }
           for all defered nested procedures and the current procedure }
-        if isnestedproc then
-          tcgprocinfo(current_procinfo.parent).nestedprocs.insert(current_procinfo)
-        else
+        if not isnestedproc then
           begin
           begin
             if not(df_generic in current_procinfo.procdef.defoptions) then
             if not(df_generic in current_procinfo.procdef.defoptions) then
               do_generate_code(tcgprocinfo(current_procinfo));
               do_generate_code(tcgprocinfo(current_procinfo));

+ 1 - 1
compiler/regvars.pas

@@ -148,7 +148,7 @@ implementation
       if (cs_opt_regvar in current_settings.optimizerswitches) and
       if (cs_opt_regvar in current_settings.optimizerswitches) and
         { we have to store regvars back to memory in this case (the nested }
         { we have to store regvars back to memory in this case (the nested }
         { procedures can access the variables of the parent)               }
         { procedures can access the variables of the parent)               }
-        (tcgprocinfo(current_procinfo).nestedprocs.count = 0) and
+        (not current_procinfo.has_nestedprocs) and
          not(pi_has_assembler_block in current_procinfo.flags) and
          not(pi_has_assembler_block in current_procinfo.flags) and
          not(pi_uses_exceptions in current_procinfo.flags) then
          not(pi_uses_exceptions in current_procinfo.flags) then
         begin
         begin