mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 15:39:24 +01:00 
			
		
		
		
	* 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 -
This commit is contained in:
		
							parent
							
								
									ad52fe0f23
								
							
						
					
					
						commit
						1c01d52ea6
					
				@ -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
 | 
					            tprocinfo(procinfo).destroy_tree;
 | 
				
			||||||
             begin
 | 
					 | 
				
			||||||
               hpi:=tprocinfo(procinfo).parent;
 | 
					 | 
				
			||||||
               tprocinfo(procinfo).free;
 | 
					 | 
				
			||||||
               procinfo:=hpi;
 | 
					 | 
				
			||||||
             end;
 | 
					 | 
				
			||||||
          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
 | 
					            tprocinfo(procinfo).destroy_tree;
 | 
				
			||||||
             begin
 | 
					 | 
				
			||||||
               hpi:=tprocinfo(procinfo).parent;
 | 
					 | 
				
			||||||
               tprocinfo(procinfo).free;
 | 
					 | 
				
			||||||
               procinfo:=hpi;
 | 
					 | 
				
			||||||
             end;
 | 
					 | 
				
			||||||
          end;
 | 
					          end;
 | 
				
			||||||
        if assigned(asmdata) then
 | 
					        if assigned(asmdata) then
 | 
				
			||||||
          begin
 | 
					          begin
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
					        if not isnestedproc then
 | 
				
			||||||
          tcgprocinfo(current_procinfo.parent).nestedprocs.insert(current_procinfo)
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          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));
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user