Browse Source

* 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 years ago
parent
commit
1c01d52ea6
4 changed files with 74 additions and 34 deletions
  1. 2 14
      compiler/fmodule.pas
  2. 65 0
      compiler/procinfo.pas
  3. 6 19
      compiler/psub.pas
  4. 1 1
      compiler/regvars.pas

+ 2 - 14
compiler/fmodule.pas

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

+ 65 - 0
compiler/procinfo.pas

@@ -47,10 +47,17 @@ unit procinfo;
 
 
     type
+       tsavedlabels = array[Boolean] of TAsmLabel;
+
        {# This object gives information on the current routine being
           compiled.
        }
        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 }
           parent : tprocinfo;
           {# the definition of the routine itself }
@@ -123,6 +130,18 @@ unit procinfo;
 
           { Allocate got register }
           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;
        tcprocinfo = class of tprocinfo;
 
@@ -165,15 +184,61 @@ implementation
         CurrTrueLabel:=nil;
         CurrFalseLabel:=nil;
         maxpushedparasize:=0;
+        if Assigned(parent) and (parent.procdef.parast.symtablelevel>=normal_function_level) then
+          parent.addnestedproc(Self);
       end;
 
 
     destructor tprocinfo.destroy;
       begin
+         nestedprocs.free;
          aktproccode.free;
          aktlocaldata.free;
       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);
       begin

+ 6 - 19
compiler/psub.pas

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