mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 09:19:39 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			271 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			271 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Helper routines for the optimizer
 | 
						|
 | 
						|
    Copyright (c) 2007 by Florian Klaempfl
 | 
						|
 | 
						|
    This program is free software; you can redistribute it and/or modify
 | 
						|
    it under the terms of the GNU General Public License as published by
 | 
						|
    the Free Software Foundation; either version 2 of the License, or
 | 
						|
    (at your option) any later version.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public License
 | 
						|
    along with this program; if not, write to the Free Software
 | 
						|
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 | 
						|
 ****************************************************************************
 | 
						|
}
 | 
						|
unit optutils;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
  interface
 | 
						|
 | 
						|
    uses
 | 
						|
      cclasses,
 | 
						|
      node;
 | 
						|
 | 
						|
    type
 | 
						|
      { this implementation should be really improved,
 | 
						|
        its purpose is to find equal nodes }
 | 
						|
      TIndexedNodeSet = class(TFPList)
 | 
						|
        function Add(node : tnode) : boolean;
 | 
						|
        function Includes(node : tnode) : tnode;
 | 
						|
        function Remove(node : tnode) : boolean;
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure SetNodeSucessors(p : tnode);
 | 
						|
    procedure PrintDFAInfo(var f : text;p : tnode);
 | 
						|
    procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
 | 
						|
 | 
						|
  implementation
 | 
						|
 | 
						|
    uses
 | 
						|
      verbose,
 | 
						|
      optbase,
 | 
						|
      nbas,nflw,nutils;
 | 
						|
 | 
						|
    function TIndexedNodeSet.Add(node : tnode) : boolean;
 | 
						|
      var
 | 
						|
        i : Integer;
 | 
						|
        p : tnode;
 | 
						|
      begin
 | 
						|
        node.allocoptinfo;
 | 
						|
        p:=Includes(node);
 | 
						|
        if assigned(p) then
 | 
						|
          begin
 | 
						|
            result:=false;
 | 
						|
            node.optinfo^.index:=p.optinfo^.index;
 | 
						|
          end
 | 
						|
        else
 | 
						|
          begin
 | 
						|
            i:=inherited Add(node);
 | 
						|
            node.optinfo^.index:=i;
 | 
						|
            result:=true;
 | 
						|
          end
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TIndexedNodeSet.Includes(node : tnode) : tnode;
 | 
						|
      var
 | 
						|
        i : longint;
 | 
						|
      begin
 | 
						|
        for i:=0 to Count-1 do
 | 
						|
          if tnode(List^[i]).isequal(node) then
 | 
						|
            begin
 | 
						|
              result:=tnode(List^[i]);
 | 
						|
              exit;
 | 
						|
            end;
 | 
						|
        result:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TIndexedNodeSet.Remove(node : tnode) : boolean;
 | 
						|
      var
 | 
						|
        p : tnode;
 | 
						|
      begin
 | 
						|
        result:=false;
 | 
						|
        p:=Includes(node);
 | 
						|
        if assigned(p) then
 | 
						|
          begin
 | 
						|
            if inherited Remove(p)<>-1 then
 | 
						|
              result:=true;
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
 | 
						|
      var
 | 
						|
        i : integer;
 | 
						|
      begin
 | 
						|
        for i:=0 to s.count-1 do
 | 
						|
          begin
 | 
						|
            writeln(f,'=============================== Node ',i,' ===============================');
 | 
						|
            printnode(f,tnode(s[i]));
 | 
						|
            writeln(f);
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function PrintNodeDFA(var n: tnode; arg: pointer): foreachnoderesult;
 | 
						|
      begin
 | 
						|
        if assigned(n.optinfo) and ((n.optinfo^.life<>nil) or (n.optinfo^.use<>nil) or (n.optinfo^.def<>nil)) then
 | 
						|
          begin
 | 
						|
            write(text(arg^),nodetype2str[n.nodetype],'(',n.fileinfo.line,',',n.fileinfo.column,') Life: ');
 | 
						|
            PrintDFASet(text(arg^),n.optinfo^.life);
 | 
						|
            write(text(arg^),' Def: ');
 | 
						|
            PrintDFASet(text(arg^),n.optinfo^.def);
 | 
						|
            write(text(arg^),' Use: ');
 | 
						|
            PrintDFASet(text(arg^),n.optinfo^.use);
 | 
						|
            writeln(text(arg^));
 | 
						|
          end;
 | 
						|
        result:=fen_false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure PrintDFAInfo(var f : text;p : tnode);
 | 
						|
      begin
 | 
						|
        foreachnodestatic(pm_postprocess,p,@PrintNodeDFA,@f);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure SetNodeSucessors(p : tnode);
 | 
						|
      var
 | 
						|
        Continuestack : TFPList;
 | 
						|
        Breakstack : TFPList;
 | 
						|
      { sets the successor nodes of a node tree block
 | 
						|
        returns the first node of the tree if it's a controll flow node }
 | 
						|
      function DoSet(p : tnode;succ : tnode) : tnode;
 | 
						|
        var
 | 
						|
          hp1,hp2 : tnode;
 | 
						|
        begin
 | 
						|
          result:=nil;
 | 
						|
          if p=nil then
 | 
						|
            exit;
 | 
						|
          case p.nodetype of
 | 
						|
            statementn:
 | 
						|
              begin
 | 
						|
                hp1:=p;
 | 
						|
                result:=p;
 | 
						|
                while assigned(hp1) do
 | 
						|
                  begin
 | 
						|
                    { does another statement follow? }
 | 
						|
                    if assigned(tstatementnode(hp1).next) then
 | 
						|
                      begin
 | 
						|
                        hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
 | 
						|
                        if assigned(hp2) then
 | 
						|
                          tstatementnode(hp1).successor:=hp2
 | 
						|
                        else
 | 
						|
                          tstatementnode(hp1).successor:=tstatementnode(hp1).next;
 | 
						|
                      end
 | 
						|
                    else
 | 
						|
                      begin
 | 
						|
                        hp2:=DoSet(tstatementnode(hp1).statement,succ);
 | 
						|
                        if assigned(hp2) then
 | 
						|
                          tstatementnode(hp1).successor:=hp2
 | 
						|
                        else
 | 
						|
                          tstatementnode(hp1).successor:=succ;
 | 
						|
                      end;
 | 
						|
                    hp1:=tstatementnode(hp1).next;
 | 
						|
                  end;
 | 
						|
              end;
 | 
						|
            blockn:
 | 
						|
              begin
 | 
						|
                result:=p;
 | 
						|
                DoSet(tblocknode(p).statements,succ);
 | 
						|
                p.successor:=succ;
 | 
						|
              end;
 | 
						|
            forn:
 | 
						|
              begin
 | 
						|
                Breakstack.Add(succ);
 | 
						|
                Continuestack.Add(p);
 | 
						|
                result:=p;
 | 
						|
                { the successor of the last node of the for body is the for node itself }
 | 
						|
                DoSet(tfornode(p).t2,p);
 | 
						|
                Breakstack.Delete(Breakstack.Count-1);
 | 
						|
                Continuestack.Delete(Continuestack.Count-1);
 | 
						|
              end;
 | 
						|
            breakn:
 | 
						|
              begin
 | 
						|
                result:=p;
 | 
						|
                p.successor:=tnode(Breakstack.Last);
 | 
						|
              end;
 | 
						|
            continuen:
 | 
						|
              begin
 | 
						|
                result:=p;
 | 
						|
                p.successor:=tnode(Continuestack.Last);
 | 
						|
              end;
 | 
						|
            whilerepeatn:
 | 
						|
              begin
 | 
						|
                Breakstack.Add(succ);
 | 
						|
                Continuestack.Add(p);
 | 
						|
                result:=p;
 | 
						|
                { the successor of the last node of the for body is the while node itself }
 | 
						|
                DoSet(twhilerepeatnode(p).right,p);
 | 
						|
                p.successor:=succ;
 | 
						|
                Breakstack.Delete(Breakstack.Count-1);
 | 
						|
                Continuestack.Delete(Continuestack.Count-1);
 | 
						|
              end;
 | 
						|
            ifn:
 | 
						|
              begin
 | 
						|
                result:=p;
 | 
						|
                DoSet(tifnode(p).right,succ);
 | 
						|
                DoSet(tifnode(p).t1,succ);
 | 
						|
                p.successor:=succ;
 | 
						|
              end;
 | 
						|
            labeln:
 | 
						|
              begin
 | 
						|
                result:=p;
 | 
						|
                if assigned(tlabelnode(p).left) then
 | 
						|
                  begin
 | 
						|
                    DoSet(tlabelnode(p).left,succ);
 | 
						|
                    p.successor:=tlabelnode(p).left;
 | 
						|
                  end
 | 
						|
                else
 | 
						|
                  p.successor:=succ;
 | 
						|
              end;
 | 
						|
            assignn:
 | 
						|
              begin
 | 
						|
                result:=p;
 | 
						|
                p.successor:=succ;
 | 
						|
              end;
 | 
						|
            goton:
 | 
						|
              begin
 | 
						|
                result:=p;
 | 
						|
                if not(assigned(tgotonode(p).labelnode)) then
 | 
						|
                  internalerror(2007050701);
 | 
						|
                p.successor:=tgotonode(p).labelnode;
 | 
						|
              end;
 | 
						|
            exitn:
 | 
						|
              begin
 | 
						|
                result:=p;
 | 
						|
                p.successor:=nil;
 | 
						|
              end;
 | 
						|
            inlinen,
 | 
						|
            calln,
 | 
						|
            withn,
 | 
						|
            casen,
 | 
						|
            tryexceptn,
 | 
						|
            raisen,
 | 
						|
            tryfinallyn,
 | 
						|
            onn,
 | 
						|
            nothingn:
 | 
						|
              internalerror(2007050501);
 | 
						|
          end;
 | 
						|
        end;
 | 
						|
 | 
						|
      begin
 | 
						|
        Breakstack:=TFPList.Create;
 | 
						|
        Continuestack:=TFPList.Create;
 | 
						|
        DoSet(p,nil);
 | 
						|
        Continuestack.Free;
 | 
						|
        Breakstack.Free;
 | 
						|
      end;
 | 
						|
 | 
						|
end.
 | 
						|
 |