mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 10:19:31 +01:00 
			
		
		
		
	+ darwin/ppc64 support
    + val/str/read(ln)/write(ln) support for enums
    + simple cse at the node tree level
    + if-node simplify support
    + simple ssa support for memory locations
    + support for optional overflow/rangecheck boolean parameters for
      operators
    * a lot of unification of the ppc32/ppc64 code generators
........
r6380 | jonas | 2007-02-08 21:25:36 +0100 (Thu, 08 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncgld.pas
   M /branches/fpc_2_3/compiler/tgobj.pas
   A /branches/fpc_2_3/tests/webtbs/tw8283.pp
  + support for replacing the memory location of a temp (including
    local variables) with that of another temp to avoid unnecessary
    copies (mantis #8283)
........
r6381 | jonas | 2007-02-08 22:53:36 +0100 (Thu, 08 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/nflw.pas
   A /branches/fpc_2_3/tests/webtbs/tw8282.pp
  + simplify support for ifn (based on patch by Florian)
........
r6386 | peter | 2007-02-09 13:48:53 +0100 (Fri, 09 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/htypechk.pas
   M /branches/fpc_2_3/compiler/ncal.pas
   M /branches/fpc_2_3/compiler/symconst.pas
  * overflow,rangecheck optional parameters for operators, patch from 8281
........
r6391 | jonas | 2007-02-09 23:52:13 +0100 (Fri, 09 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/agppcgas.pas
   M /branches/fpc_2_3/compiler/powerpc64/cpunode.pas
   D /branches/fpc_2_3/compiler/powerpc64/nppcinl.pas
   M /branches/fpc_2_3/compiler/ppcgen/ngppcinl.pas
  * merged fsqrt(s) support to common powerpc unit, activate for ppc32
    if -Op970 is used (still default for ppc64, since default cpu there
    is already ppc970)
........
r6394 | jonas | 2007-02-10 18:58:47 +0100 (Sat, 10 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
   M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas
  * adapted a_jmp_name for darwin/ppc64
  * merged g_intf_wrapper for ppc32 and ppc64, and added darwin/ppc64
    support to it
........
r6396 | jonas | 2007-02-10 20:16:06 +0100 (Sat, 10 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/cgobj.pas
  + darwin/ppc64 support for g_indirect_sym_load
........
r6397 | jonas | 2007-02-10 20:22:49 +0100 (Sat, 10 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
   M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas
  + darwin/ppc64 support to ppc64's fixref
  * moved ppc32 a_load_store to cgppc and use it for darwin/ppc64 as
    well (its relocatable symbols are only 32 bits large)
........
r6399 | jonas | 2007-02-10 22:02:37 +0100 (Sat, 10 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems.pas
  + system_x86_64_darwin identifier
  + set default source system for system_x86_64_darwin and
    system_powerpc64_darwin
........
r6404 | jonas | 2007-02-10 23:01:23 +0100 (Sat, 10 Feb 2007) | 5 lines
Changed paths:
   M /branches/fpc_2_3/compiler/aasmdata.pas
   M /branches/fpc_2_3/compiler/aggas.pas
   M /branches/fpc_2_3/compiler/cgobj.pas
   M /branches/fpc_2_3/compiler/cgutils.pas
   M /branches/fpc_2_3/compiler/cresstr.pas
   M /branches/fpc_2_3/compiler/dbgdwarf.pas
   M /branches/fpc_2_3/compiler/dbgstabs.pas
   M /branches/fpc_2_3/compiler/ncgutil.pas
   M /branches/fpc_2_3/compiler/ogelf.pas
   M /branches/fpc_2_3/compiler/pdecvar.pas
   M /branches/fpc_2_3/compiler/pmodules.pas
   M /branches/fpc_2_3/compiler/symdef.pas
   M /branches/fpc_2_3/compiler/systems.pas
  + system_x86_64_darwin identifier
  + systems_darwin set which collects all darwin variants
  + added support for darwin/ppc64 and darwin/x86_64 where needed in
    the generic code
........
r6406 | jonas | 2007-02-10 23:24:32 +0100 (Sat, 10 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/cgobj.pas
  * ifdef cpu64 -> ifdef cpu64bit
........
r6409 | jonas | 2007-02-11 00:34:04 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/pdecvar.pas
  * fixed ppc64 compilation
........
r6413 | jonas | 2007-02-11 12:41:27 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/bsd/system.pp
   M /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc
   M /branches/fpc_2_3/rtl/darwin/signal.inc
  + darwin/ppc64 support for signal routines
........
r6415 | jonas | 2007-02-11 13:54:53 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_linux.pas
  * set abi of linux/ppc64 to abi_powerpc_sysv
........
r6416 | jonas | 2007-02-11 13:55:51 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/cputarg.pas
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
   M /branches/fpc_2_3/compiler/systems/t_bsd.pas
  + darwin/ppc64 source and target information
........
r6418 | jonas | 2007-02-11 14:19:55 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/powerpc64/math.inc
  * darwin/ppc64 compilation fixes
........
r6419 | jonas | 2007-02-11 14:22:22 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
   M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas
  * darwin/ppc64 needs the 32 bit version of a_loadaddr_ref_reg
........
r6420 | jonas | 2007-02-11 14:22:55 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/utils/fpcm/fpcmmain.pp
  + darwin/ppc64 support
........
r6426 | jonas | 2007-02-11 16:13:19 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/rappcgas.pas
  * fixed refaddr parsing for darwin/ppc64
........
r6427 | jonas | 2007-02-11 16:14:21 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/agppcgas.pas
   M /branches/fpc_2_3/compiler/powerpc64/agppcgas.pas
   A /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas
  * moved ppc32/ppc64 assembler writer helpers to a common unit
........
r6430 | jonas | 2007-02-11 17:53:23 +0100 (Sun, 11 Feb 2007) | 4 lines
Changed paths:
   D /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc
   D /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc
   A /branches/fpc_2_3/rtl/darwin/powerpc64
   A /branches/fpc_2_3/rtl/darwin/powerpc64/sig_cpu.inc
   A /branches/fpc_2_3/rtl/darwin/powerpc64/sighnd.inc
   A /branches/fpc_2_3/rtl/darwin/ppcgen
   A /branches/fpc_2_3/rtl/darwin/ppcgen/ppchnd.inc (from /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc:6422)
   A /branches/fpc_2_3/rtl/darwin/ppcgen/sig_ppc.inc (from /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc:6422)
   M /branches/fpc_2_3/rtl/darwin/signal.inc
  * fixed ppc/ppc64 signal include handling (both real files are in
    ppcgen, dummies in powerpc and powerpc64 which include those files)
    (1st step because pre-commit filter can't handle replaced files)
........
r6431 | jonas | 2007-02-11 17:53:47 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   A /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc
   A /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc
  * second step of signal include patch
........
r6432 | jonas | 2007-02-11 19:00:12 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/t_bsd.pas
  * changed darwin checks to use systems_darwin constant
........
r6433 | jonas | 2007-02-11 19:05:38 +0100 (Sun, 11 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
  * handle non-multiple-of-4 offsets with 64 bit loads/stores for
    darwin/ppc64
........
r6434 | jonas | 2007-02-11 19:05:56 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   D /branches/fpc_2_3/compiler/powerpc/agppcgas.pas
   D /branches/fpc_2_3/compiler/powerpc64/agppcgas.pas
   A /branches/fpc_2_3/compiler/ppcgen/agppcgas.pas (from /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas:6427)
   D /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas
  * completely merged ppc assembler writers
........
r6435 | jonas | 2007-02-11 19:06:40 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/darwin/console.pp
   M /branches/fpc_2_3/rtl/darwin/termiosproc.inc
  * fixed 64 bit compilation
........
r6436 | jonas | 2007-02-11 19:09:28 +0100 (Sun, 11 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/packages/extra/Makefile.fpc
  * universal interfaces aren't 64 bit ready yet -> only compile for
    darwin/ppc and darwin/i386
........
r6438 | jonas | 2007-02-11 19:22:34 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/ctest.o
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext3.o
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext4.o
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext5.o
  + compiled for darwin/ppc64
........
r6439 | jonas | 2007-02-11 20:24:42 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas
  * patch from Thomas to fix linux/ppc64
........
r6440 | jonas | 2007-02-11 20:25:15 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems.pas
  * fixed setting source OS for darwin/ppc64
........
r6444 | florian | 2007-02-11 22:24:20 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/globtype.pas
   M /branches/fpc_2_3/compiler/nopt.pas
   M /branches/fpc_2_3/compiler/nutils.pas
   M /branches/fpc_2_3/compiler/optcse.pas
   M /branches/fpc_2_3/compiler/psub.pas
+ first node cse implementation
........
r6445 | jonas | 2007-02-11 22:30:07 +0100 (Sun, 11 Feb 2007) | 6 lines
Changed paths:
   M /branches/fpc_2_3/compiler/cresstr.pas
  * hack to work around strange darwin/ppc64 linker bug: it seems to
    have problems if you put a global symbol at the end of a section
    without any data following (at least in case of the resource strings
    section) -> add dummy byte at the end for darwin/ppc64 (otherwise
    it messes up the address of the first symbol stub entry)
........
r6449 | jonas | 2007-02-11 23:23:44 +0100 (Sun, 11 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
  * cpupowerpc is defined for both ppc32 and ppc64 ->
    changed to cpupowerpc32 to avoid defining source
    wrongly on ppc64
........
r6450 | jonas | 2007-02-11 23:26:34 +0100 (Sun, 11 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ppcgen/ngppcset.pas
  * disable jump tables for darwin/ppc64 for now, don't work
    yet for some reason
........
r6451 | florian | 2007-02-11 23:54:37 +0100 (Sun, 11 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncal.pas
   M /branches/fpc_2_3/compiler/nutils.pas
   M /branches/fpc_2_3/compiler/optcse.pas
* improved cse
* better complexity calculation for subscript nodes with classes or interfaces
........
r6456 | jonas | 2007-02-12 19:33:22 +0100 (Mon, 12 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/nutils.pas
  + support for notn,shln,shrn,equaln,unequaln,gtn,gten,ltn,lten in
    node_cplexity()
  * mark muln,divn,modn as more complex
........
r6469 | jonas | 2007-02-13 15:56:01 +0100 (Tue, 13 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/optcse.pas
  * fixed when cross-compiling a 64 bit compiler from a 32 bit platform
........
r6471 | jonas | 2007-02-13 16:17:16 +0100 (Tue, 13 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/cputarg.pas
  * include stabs support (can work on darwin/ppc64, but doesn't work
    yet)
........
r6473 | jonas | 2007-02-13 16:45:48 +0100 (Tue, 13 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
   M /branches/fpc_2_3/compiler/powerpc64/cpupara.pas
  * R2 is a volatile and usable register under darwin/ppc64
  * R13 is a reserved non-volatile register under darwin/ppc64 (tls)
........
r6479 | jonas | 2007-02-13 20:40:50 +0100 (Tue, 13 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
  * maxCrecordalign seems to have to be 8 rather 4, in spite of what
    the ABI docs say (although they are contradictory to some extent)
........
r6487 | jonas | 2007-02-14 15:57:40 +0100 (Wed, 14 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/tests/webtbs/tw8153a.pp
  * fixed for darwin/ppc64
........
r6488 | jonas | 2007-02-14 15:58:56 +0100 (Wed, 14 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/tests/webtbs/tw7851a.pp
  * fixed for darwin/ppc64
........
r6494 | jonas | 2007-02-15 19:36:55 +0100 (Thu, 15 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
  * set default debug info for darwin/ppc64 to dwarf2 since
    it works better than stabs currently
........
r6500 | jonas | 2007-02-15 21:38:16 +0100 (Thu, 15 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/version.pas
  * updated version to 2.3.0
........
r6505 | jonas | 2007-02-15 22:39:28 +0100 (Thu, 15 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/version.pas
  * changed version to 2.3.1
........
r6511 | jonas | 2007-02-16 15:17:24 +0100 (Fri, 16 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/itcpugas.pas
  * system_powerpc_darwin -> system_powerpc64_darwin
........
r6546 | daniel | 2007-02-18 15:48:54 +0100 (Sun, 18 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncginl.pas
   M /branches/fpc_2_3/compiler/ncgld.pas
   M /branches/fpc_2_3/compiler/ncgrtti.pas
   M /branches/fpc_2_3/compiler/ncnv.pas
   M /branches/fpc_2_3/compiler/ninl.pas
   M /branches/fpc_2_3/compiler/nld.pas
   M /branches/fpc_2_3/compiler/nutils.pas
   M /branches/fpc_2_3/compiler/pinline.pas
   M /branches/fpc_2_3/rtl/inc/astrings.inc
   M /branches/fpc_2_3/rtl/inc/compproc.inc
   M /branches/fpc_2_3/rtl/inc/sstrings.inc
   M /branches/fpc_2_3/rtl/inc/text.inc
   M /branches/fpc_2_3/rtl/inc/wstrings.inc
  + Val/str/read/write support for enumeration types.
........
r6547 | daniel | 2007-02-18 17:01:20 +0100 (Sun, 18 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/inc/sstrings.inc
  * Fix val code that I broke.
........
r6571 | daniel | 2007-02-20 09:27:44 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/inc/astrings.inc
   M /branches/fpc_2_3/rtl/inc/sstrings.inc
   M /branches/fpc_2_3/rtl/inc/text.inc
   M /branches/fpc_2_3/rtl/inc/wstrings.inc
  * o2s -> ord2str, s2o -> str2ord
........
r6572 | daniel | 2007-02-20 09:33:30 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncgld.pas
   M /branches/fpc_2_3/compiler/ncgrtti.pas
   M /branches/fpc_2_3/compiler/ninl.pas
   M /branches/fpc_2_3/compiler/nld.pas
  * o2s -> ord2str, s2o -> str2ord
........
r6574 | daniel | 2007-02-20 12:07:58 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/inc/compproc.inc
  * o2s -> ord2str, s2o -> str2ord
........
r6578 | daniel | 2007-02-20 22:18:49 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/inc/text.inc
  * Change longint to valsint.
........
r6579 | daniel | 2007-02-20 22:29:09 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ninl.pas
  * Handle ordinal currency types.
........
r6580 | jonas | 2007-02-20 22:29:11 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncgrtti.pas
  * fixed compilation for cpurequiresproperalignment
........
r6581 | jonas | 2007-02-20 22:30:21 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ninl.pas
  * fixed typo
........
r6582 | daniel | 2007-02-20 22:36:19 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ninl.pas
  * Set is_real to true.
........
r6590 | jonas | 2007-02-21 20:23:54 +0100 (Wed, 21 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
  * set tf_dwarf_only_local_labels for darwin/ppc64
git-svn-id: trunk@6720 -
		
	
			
		
			
				
	
	
		
			1513 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			1513 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 1998-2002 by Florian Klaempfl
 | 
						|
 | 
						|
    Type checking and register allocation for nodes that influence
 | 
						|
    the flow
 | 
						|
 | 
						|
    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 nflw;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
    uses
 | 
						|
      cclasses,
 | 
						|
      node,cpubase,
 | 
						|
      symnot,
 | 
						|
      symtype,symbase,symdef,symsym,
 | 
						|
      optunrol;
 | 
						|
 | 
						|
    type
 | 
						|
       { flags used by loop nodes }
 | 
						|
       tloopflag = (
 | 
						|
         { set if it is a for ... downto ... do loop }
 | 
						|
         lnf_backward,
 | 
						|
         { Do we need to parse childs to set var state? }
 | 
						|
         lnf_varstate,
 | 
						|
         { Do a test at the begin of the loop?}
 | 
						|
         lnf_testatbegin,
 | 
						|
         { Negate the loop test? }
 | 
						|
         lnf_checknegate,
 | 
						|
         { Should the value of the loop variable on exit be correct. }
 | 
						|
         lnf_dont_mind_loopvar_on_exit);
 | 
						|
       tloopflags = set of tloopflag;
 | 
						|
 | 
						|
    const
 | 
						|
         { loop flags which must match to consider loop nodes equal regarding the flags }
 | 
						|
         loopflagsequal = [lnf_backward];
 | 
						|
 | 
						|
    type
 | 
						|
       tlabelnode = class;
 | 
						|
 | 
						|
       tloopnode = class(tbinarynode)
 | 
						|
          t1,t2 : tnode;
 | 
						|
          loopflags : tloopflags;
 | 
						|
          constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual;
 | 
						|
          destructor destroy;override;
 | 
						|
          function dogetcopy : tnode;override;
 | 
						|
          constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
 | 
						|
          procedure ppuwrite(ppufile:tcompilerppufile);override;
 | 
						|
          procedure buildderefimpl;override;
 | 
						|
          procedure derefimpl;override;
 | 
						|
          procedure insertintolist(l : tnodelist);override;
 | 
						|
          procedure printnodetree(var t:text);override;
 | 
						|
          function docompare(p: tnode): boolean; override;
 | 
						|
       end;
 | 
						|
 | 
						|
       twhilerepeatnode = class(tloopnode)
 | 
						|
          constructor create(l,r:Tnode;tab,cn:boolean);virtual;reintroduce;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
{$ifdef state_tracking}
 | 
						|
          function track_state_pass(exec_known:boolean):boolean;override;
 | 
						|
{$endif}
 | 
						|
       end;
 | 
						|
       twhilerepeatnodeclass = class of twhilerepeatnode;
 | 
						|
 | 
						|
       tifnode = class(tloopnode)
 | 
						|
          constructor create(l,r,_t1 : tnode);virtual;reintroduce;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
          function simplify : tnode;override;
 | 
						|
         private
 | 
						|
          function internalsimplify(warn: boolean) : tnode;
 | 
						|
       end;
 | 
						|
       tifnodeclass = class of tifnode;
 | 
						|
 | 
						|
       tfornode = class(tloopnode)
 | 
						|
          { if count isn divisable by unrolls then
 | 
						|
            the for loop must jump to this label to get the correct
 | 
						|
            number of executions }
 | 
						|
          entrylabel : tnode;
 | 
						|
          loopvar_notid:cardinal;
 | 
						|
          constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;reintroduce;
 | 
						|
          procedure loop_var_access(not_type:Tnotification_flag;symbol:Tsym);
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
       end;
 | 
						|
       tfornodeclass = class of tfornode;
 | 
						|
 | 
						|
       texitnode = class(tunarynode)
 | 
						|
          constructor create(l:tnode);virtual;
 | 
						|
          constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
 | 
						|
          procedure ppuwrite(ppufile:tcompilerppufile);override;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
       end;
 | 
						|
       texitnodeclass = class of texitnode;
 | 
						|
 | 
						|
       tbreaknode = class(tnode)
 | 
						|
          constructor create;virtual;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
       end;
 | 
						|
       tbreaknodeclass = class of tbreaknode;
 | 
						|
 | 
						|
       tcontinuenode = class(tnode)
 | 
						|
          constructor create;virtual;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
       end;
 | 
						|
       tcontinuenodeclass = class of tcontinuenode;
 | 
						|
 | 
						|
       tgotonode = class(tnode)
 | 
						|
          { we still need this for resolving forward gotos }
 | 
						|
          labelsym : tlabelsym;
 | 
						|
          labelnode : tlabelnode;
 | 
						|
          exceptionblock : integer;
 | 
						|
{          internlab : tinterngotolabel;}
 | 
						|
          constructor create(p : tlabelnode);virtual;
 | 
						|
          { as long as we don't know the label node we can't resolve it }
 | 
						|
          constructor create_sym(p : tlabelsym);virtual;
 | 
						|
{          constructor createintern(g:tinterngotolabel);}
 | 
						|
          constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
 | 
						|
          procedure ppuwrite(ppufile:tcompilerppufile);override;
 | 
						|
          procedure buildderefimpl;override;
 | 
						|
          procedure derefimpl;override;
 | 
						|
          function dogetcopy : tnode;override;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
          function docompare(p: tnode): boolean; override;
 | 
						|
       end;
 | 
						|
       tgotonodeclass = class of tgotonode;
 | 
						|
 | 
						|
       tlabelnode = class(tunarynode)
 | 
						|
          exceptionblock : integer;
 | 
						|
          { when copying trees, this points to the newly created copy of a label }
 | 
						|
          copiedto : tlabelnode;
 | 
						|
          { contains all goto nodesrefering to this label }
 | 
						|
          referinggotonodes : TFPObjectList;
 | 
						|
          constructor create(l:tnode);virtual;
 | 
						|
          constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
 | 
						|
          procedure ppuwrite(ppufile:tcompilerppufile);override;
 | 
						|
          procedure buildderefimpl;override;
 | 
						|
          procedure derefimpl;override;
 | 
						|
          function dogetcopy : tnode;override;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
          function docompare(p: tnode): boolean; override;
 | 
						|
       end;
 | 
						|
       tlabelnodeclass = class of tlabelnode;
 | 
						|
 | 
						|
       traisenode = class(ttertiarynode)
 | 
						|
          constructor create(l,taddr,tframe:tnode);virtual;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
 | 
						|
          property frametree : tnode read third write third;
 | 
						|
       end;
 | 
						|
       traisenodeclass = class of traisenode;
 | 
						|
 | 
						|
       ttryexceptnode = class(tloopnode)
 | 
						|
          constructor create(l,r,_t1 : tnode);virtual;reintroduce;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
       end;
 | 
						|
       ttryexceptnodeclass = class of ttryexceptnode;
 | 
						|
 | 
						|
       ttryfinallynode = class(tloopnode)
 | 
						|
          implicitframe : boolean;
 | 
						|
          constructor create(l,r:tnode);virtual;reintroduce;
 | 
						|
          constructor create_implicit(l,r,_t1:tnode);virtual;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
       end;
 | 
						|
       ttryfinallynodeclass = class of ttryfinallynode;
 | 
						|
 | 
						|
       tonnode = class(tbinarynode)
 | 
						|
          excepTSymtable : TSymtable;
 | 
						|
          excepttype : tobjectdef;
 | 
						|
          constructor create(l,r:tnode);virtual;
 | 
						|
          destructor destroy;override;
 | 
						|
          constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
 | 
						|
          function pass_typecheck:tnode;override;
 | 
						|
          function pass_1 : tnode;override;
 | 
						|
          function dogetcopy : tnode;override;
 | 
						|
          function docompare(p: tnode): boolean; override;
 | 
						|
       end;
 | 
						|
       tonnodeclass = class of tonnode;
 | 
						|
 | 
						|
    var
 | 
						|
       cwhilerepeatnode : twhilerepeatnodeclass;
 | 
						|
       cifnode : tifnodeclass;
 | 
						|
       cfornode : tfornodeclass;
 | 
						|
       cexitnode : texitnodeclass;
 | 
						|
       cbreaknode : tbreaknodeclass;
 | 
						|
       ccontinuenode : tcontinuenodeclass;
 | 
						|
       cgotonode : tgotonodeclass;
 | 
						|
       clabelnode : tlabelnodeclass;
 | 
						|
       craisenode : traisenodeclass;
 | 
						|
       ctryexceptnode : ttryexceptnodeclass;
 | 
						|
       ctryfinallynode : ttryfinallynodeclass;
 | 
						|
       connode : tonnodeclass;
 | 
						|
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
    uses
 | 
						|
      globtype,systems,
 | 
						|
      cutils,verbose,globals,
 | 
						|
      symconst,paramgr,defcmp,defutil,htypechk,pass_1,
 | 
						|
      ncal,nadd,ncon,nmem,nld,ncnv,nbas,cgobj,nutils,
 | 
						|
    {$ifdef prefetchnext}
 | 
						|
      ninl,
 | 
						|
    {$endif prefetchnext}
 | 
						|
    {$ifdef state_tracking}
 | 
						|
      nstate,
 | 
						|
    {$endif}
 | 
						|
      cgbase,procinfo
 | 
						|
      ;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                                 TLOOPNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode);
 | 
						|
 | 
						|
      begin
 | 
						|
         inherited create(tt,l,r);
 | 
						|
         t1:=_t1;
 | 
						|
         t2:=_t2;
 | 
						|
         fileinfo:=l.fileinfo;
 | 
						|
      end;
 | 
						|
 | 
						|
    destructor tloopnode.destroy;
 | 
						|
 | 
						|
      begin
 | 
						|
         t1.free;
 | 
						|
         t2.free;
 | 
						|
         inherited destroy;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor tloopnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuload(t,ppufile);
 | 
						|
        t1:=ppuloadnode(ppufile);
 | 
						|
        t2:=ppuloadnode(ppufile);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tloopnode.ppuwrite(ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuwrite(ppufile);
 | 
						|
        ppuwritenode(ppufile,t1);
 | 
						|
        ppuwritenode(ppufile,t2);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tloopnode.buildderefimpl;
 | 
						|
      begin
 | 
						|
        inherited buildderefimpl;
 | 
						|
        if assigned(t1) then
 | 
						|
          t1.buildderefimpl;
 | 
						|
        if assigned(t2) then
 | 
						|
          t2.buildderefimpl;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tloopnode.derefimpl;
 | 
						|
      begin
 | 
						|
        inherited derefimpl;
 | 
						|
        if assigned(t1) then
 | 
						|
          t1.derefimpl;
 | 
						|
        if assigned(t2) then
 | 
						|
          t2.derefimpl;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tloopnode.dogetcopy : tnode;
 | 
						|
 | 
						|
      var
 | 
						|
         p : tloopnode;
 | 
						|
 | 
						|
      begin
 | 
						|
         p:=tloopnode(inherited dogetcopy);
 | 
						|
         if assigned(t1) then
 | 
						|
           p.t1:=t1.dogetcopy
 | 
						|
         else
 | 
						|
           p.t1:=nil;
 | 
						|
         if assigned(t2) then
 | 
						|
           p.t2:=t2.dogetcopy
 | 
						|
         else
 | 
						|
           p.t2:=nil;
 | 
						|
         p.loopflags:=loopflags;
 | 
						|
         dogetcopy:=p;
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure tloopnode.insertintolist(l : tnodelist);
 | 
						|
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tloopnode.printnodetree(var t:text);
 | 
						|
      begin
 | 
						|
        write(t,printnodeindention,'(');
 | 
						|
        printnodeindent;
 | 
						|
        printnodeinfo(t);
 | 
						|
        writeln(t);
 | 
						|
        printnode(t,left);
 | 
						|
        printnode(t,right);
 | 
						|
        printnode(t,t1);
 | 
						|
        printnode(t,t2);
 | 
						|
        printnodeunindent;
 | 
						|
        writeln(t,printnodeindention,')');
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tloopnode.docompare(p: tnode): boolean;
 | 
						|
      begin
 | 
						|
        docompare :=
 | 
						|
          inherited docompare(p) and
 | 
						|
          (loopflags*loopflagsequal=tloopnode(p).loopflags*loopflagsequal) and
 | 
						|
          t1.isequal(tloopnode(p).t1) and
 | 
						|
          t2.isequal(tloopnode(p).t2);
 | 
						|
      end;
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                               TWHILEREPEATNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor Twhilerepeatnode.create(l,r:Tnode;tab,cn:boolean);
 | 
						|
      begin
 | 
						|
          inherited create(whilerepeatn,l,r,nil,nil);
 | 
						|
          if tab then
 | 
						|
              include(loopflags, lnf_testatbegin);
 | 
						|
          if cn then
 | 
						|
              include(loopflags,lnf_checknegate);
 | 
						|
      end;
 | 
						|
 | 
						|
    function twhilerepeatnode.pass_typecheck:tnode;
 | 
						|
      var
 | 
						|
         t:Tunarynode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         resultdef:=voidtype;
 | 
						|
 | 
						|
         typecheckpass(left);
 | 
						|
 | 
						|
         { tp procvar support }
 | 
						|
         maybe_call_procvar(left,true);
 | 
						|
 | 
						|
         {A not node can be removed.}
 | 
						|
         if left.nodetype=notn then
 | 
						|
           begin
 | 
						|
             t:=Tunarynode(left);
 | 
						|
             left:=Tunarynode(left).left;
 | 
						|
             t.left:=nil;
 | 
						|
             t.destroy;
 | 
						|
             {Symdif operator, in case you are wondering:}
 | 
						|
             loopflags:=loopflags >< [lnf_checknegate];
 | 
						|
           end;
 | 
						|
         { loop instruction }
 | 
						|
         if assigned(right) then
 | 
						|
           typecheckpass(right);
 | 
						|
         set_varstate(left,vs_read,[vsf_must_be_valid]);
 | 
						|
         if codegenerror then
 | 
						|
           exit;
 | 
						|
 | 
						|
         if not is_boolean(left.resultdef) then
 | 
						|
           begin
 | 
						|
             if left.resultdef.typ=variantdef then
 | 
						|
               inserttypeconv(left,booltype)
 | 
						|
             else
 | 
						|
               CGMessage1(type_e_boolean_expr_expected,left.resultdef.typename);
 | 
						|
           end;
 | 
						|
 | 
						|
         { Give warnings for code that will never be executed for
 | 
						|
           while false do }
 | 
						|
         if (lnf_testatbegin in loopflags) and
 | 
						|
            (left.nodetype=ordconstn) and
 | 
						|
            (tordconstnode(left).value=0) and
 | 
						|
            assigned(right) then
 | 
						|
           CGMessagePos(right.fileinfo,cg_w_unreachable_code);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{$ifdef prefetchnext}
 | 
						|
    type
 | 
						|
      passignmentquery = ^tassignmentquery;
 | 
						|
      tassignmentquery = record
 | 
						|
        towhat: tnode;
 | 
						|
        source: tassignmentnode;
 | 
						|
        statementcount: cardinal;
 | 
						|
      end;
 | 
						|
 | 
						|
    function checkassignment(var n: tnode; arg: pointer): foreachnoderesult;
 | 
						|
      var
 | 
						|
        query: passignmentquery absolute arg;
 | 
						|
        temp, prederef: tnode;
 | 
						|
      begin
 | 
						|
        result := fen_norecurse_false;
 | 
						|
        if (n.nodetype in [assignn,inlinen,forn,calln,whilerepeatn,casen,ifn]) then
 | 
						|
          inc(query^.statementcount);
 | 
						|
        { make sure there's something else in the loop besides going to the }
 | 
						|
        { next item                                                         }
 | 
						|
        if (query^.statementcount > 1) and
 | 
						|
           (n.nodetype = assignn) then
 | 
						|
          begin
 | 
						|
            { skip type conversions of assignment target }
 | 
						|
            temp := tassignmentnode(n).left;
 | 
						|
            while (temp.nodetype = typeconvn) do
 | 
						|
              temp := ttypeconvnode(temp).left;
 | 
						|
 | 
						|
            { assignment to x of the while assigned(x) check? }
 | 
						|
            if not(temp.isequal(query^.towhat)) then
 | 
						|
              exit;
 | 
						|
 | 
						|
            { right hand side of assignment dereferenced field of }
 | 
						|
            { x? (no derefn in case of class)                     }
 | 
						|
            temp := tassignmentnode(n).right;
 | 
						|
            while (temp.nodetype = typeconvn) do
 | 
						|
              temp := ttypeconvnode(temp).left;
 | 
						|
            if (temp.nodetype <> subscriptn) then
 | 
						|
              exit;
 | 
						|
 | 
						|
            prederef := tsubscriptnode(temp).left;
 | 
						|
            temp := prederef;
 | 
						|
            while (temp.nodetype = typeconvn) do
 | 
						|
              temp := ttypeconvnode(temp).left;
 | 
						|
 | 
						|
            { see tests/test/prefetch1.pp }
 | 
						|
            if (temp.nodetype = derefn) then
 | 
						|
              temp := tderefnode(temp).left
 | 
						|
            else
 | 
						|
              temp := prederef;
 | 
						|
 | 
						|
            if temp.isequal(query^.towhat) then
 | 
						|
              begin
 | 
						|
                query^.source := tassignmentnode(n);
 | 
						|
                result := fen_norecurse_true;
 | 
						|
               end
 | 
						|
          end
 | 
						|
        { don't check nodes which can't contain an assignment or whose }
 | 
						|
        { final assignment can vary a lot                              }
 | 
						|
        else if not(n.nodetype in [calln,inlinen,casen,whilerepeatn,forn]) then
 | 
						|
          result := fen_false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function findassignment(where: tnode; towhat: tnode): tassignmentnode;
 | 
						|
      var
 | 
						|
        query: tassignmentquery;
 | 
						|
      begin
 | 
						|
        query.towhat := towhat;
 | 
						|
        query.source := nil;
 | 
						|
        query.statementcount := 0;
 | 
						|
        if foreachnodestatic(where,@checkassignment,@query) then
 | 
						|
          result := query.source
 | 
						|
        else
 | 
						|
           result := nil;
 | 
						|
      end;
 | 
						|
{$endif prefetchnext}
 | 
						|
 | 
						|
 | 
						|
    function twhilerepeatnode.pass_1 : tnode;
 | 
						|
      var
 | 
						|
{$ifdef prefetchnext}
 | 
						|
         runnernode, prefetchcode: tnode;
 | 
						|
         assignmentnode: tassignmentnode;
 | 
						|
         prefetchstatements: tstatementnode;
 | 
						|
{$endif prefetchnext}
 | 
						|
         old_t_times : longint;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
         old_t_times:=cg.t_times;
 | 
						|
 | 
						|
         { calc register weight }
 | 
						|
         if not(cs_opt_size in current_settings.optimizerswitches) then
 | 
						|
           cg.t_times:=cg.t_times*8;
 | 
						|
 | 
						|
         firstpass(left);
 | 
						|
         if codegenerror then
 | 
						|
           exit;
 | 
						|
         registersint:=left.registersint;
 | 
						|
         registersfpu:=left.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
         registersmmx:=left.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
 | 
						|
         { loop instruction }
 | 
						|
         if assigned(right) then
 | 
						|
           begin
 | 
						|
              firstpass(right);
 | 
						|
              if codegenerror then
 | 
						|
                exit;
 | 
						|
 | 
						|
              if registersint<right.registersint then
 | 
						|
                registersint:=right.registersint;
 | 
						|
              if registersfpu<right.registersfpu then
 | 
						|
                registersfpu:=right.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
              if registersmmx<right.registersmmx then
 | 
						|
                registersmmx:=right.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
 | 
						|
         cg.t_times:=old_t_times;
 | 
						|
{$ifdef prefetchnext}
 | 
						|
         { do at the end so all complex typeconversions are already }
 | 
						|
         { converted to calln's                                     }
 | 
						|
         if (cs_opt_level1 in current_settings.optimizerswitches) and
 | 
						|
            (lnf_testatbegin in loopflags) then
 | 
						|
           begin
 | 
						|
             { get first component of the while check }
 | 
						|
             runnernode := left;
 | 
						|
             while (runnernode.nodetype in [andn,orn,notn,xorn,typeconvn]) do
 | 
						|
               runnernode := tunarynode(runnernode).left;
 | 
						|
             { is it an assigned(x) check? }
 | 
						|
             if ((runnernode.nodetype = inlinen) and
 | 
						|
                 (tinlinenode(runnernode).inlinenumber = in_assigned_x)) or
 | 
						|
                ((runnernode.nodetype = unequaln) and
 | 
						|
                 (taddnode(runnernode).right.nodetype = niln)) then
 | 
						|
               begin
 | 
						|
                 runnernode := tunarynode(runnernode).left;
 | 
						|
                 { in case of in_assigned_x, there's a callparan in between }
 | 
						|
                 if (runnernode.nodetype = callparan) then
 | 
						|
                   runnernode := tcallparanode(runnernode).left;
 | 
						|
                 while (runnernode.nodetype = typeconvn) do
 | 
						|
                   runnernode := ttypeconvnode(runnernode).left;
 | 
						|
                 { is there an "x := x(^).somefield"? }
 | 
						|
                 assignmentnode := findassignment(right,runnernode);
 | 
						|
                 if assigned(assignmentnode) then
 | 
						|
                   begin
 | 
						|
                     prefetchcode := internalstatements(prefetchstatements);
 | 
						|
                     addstatement(prefetchstatements,geninlinenode(in_prefetch_var,false,
 | 
						|
                       cderefnode.create(ctypeconvnode.create(assignmentnode.right.getcopy,voidpointertype))));
 | 
						|
                     addstatement(prefetchstatements,right);
 | 
						|
                     right := prefetchcode;
 | 
						|
                     typecheckpass(right);
 | 
						|
                   end;
 | 
						|
               end;
 | 
						|
           end;
 | 
						|
{$endif prefetchnext}
 | 
						|
      end;
 | 
						|
 | 
						|
{$ifdef state_tracking}
 | 
						|
    function Twhilerepeatnode.track_state_pass(exec_known:boolean):boolean;
 | 
						|
 | 
						|
    var condition:Tnode;
 | 
						|
        code:Tnode;
 | 
						|
        done:boolean;
 | 
						|
        value:boolean;
 | 
						|
        change:boolean;
 | 
						|
        firsttest:boolean;
 | 
						|
        factval:Tnode;
 | 
						|
 | 
						|
    begin
 | 
						|
        track_state_pass:=false;
 | 
						|
        done:=false;
 | 
						|
        firsttest:=true;
 | 
						|
        {For repeat until statements, first do a pass through the code.}
 | 
						|
        if not(lnf_testatbegin in flags) then
 | 
						|
            begin
 | 
						|
                code:=right.getcopy;
 | 
						|
                if code.track_state_pass(exec_known) then
 | 
						|
                    track_state_pass:=true;
 | 
						|
                code.destroy;
 | 
						|
            end;
 | 
						|
        repeat
 | 
						|
            condition:=left.getcopy;
 | 
						|
            code:=right.getcopy;
 | 
						|
            change:=condition.track_state_pass(exec_known);
 | 
						|
            factval:=aktstate.find_fact(left);
 | 
						|
            if factval<>nil then
 | 
						|
                begin
 | 
						|
                    condition.destroy;
 | 
						|
                    condition:=factval.getcopy;
 | 
						|
                    change:=true;
 | 
						|
                end;
 | 
						|
            if change then
 | 
						|
                begin
 | 
						|
                    track_state_pass:=true;
 | 
						|
                    {Force new resultdef pass.}
 | 
						|
                    condition.resultdef:=nil;
 | 
						|
                    do_typecheckpass(condition);
 | 
						|
                end;
 | 
						|
            if is_constboolnode(condition) then
 | 
						|
                begin
 | 
						|
                    {Try to turn a while loop into a repeat loop.}
 | 
						|
                    if firsttest then
 | 
						|
                        exclude(flags,testatbegin);
 | 
						|
                    value:=(Tordconstnode(condition).value<>0) xor checknegate;
 | 
						|
                    if value then
 | 
						|
                        begin
 | 
						|
                            if code.track_state_pass(exec_known) then
 | 
						|
                                track_state_pass:=true;
 | 
						|
                        end
 | 
						|
                    else
 | 
						|
                        done:=true;
 | 
						|
                end
 | 
						|
            else
 | 
						|
                begin
 | 
						|
                    {Remove any modified variables from the state.}
 | 
						|
                    code.track_state_pass(false);
 | 
						|
                    done:=true;
 | 
						|
                end;
 | 
						|
            code.destroy;
 | 
						|
            condition.destroy;
 | 
						|
            firsttest:=false;
 | 
						|
        until done;
 | 
						|
        {The loop condition is also known, for example:
 | 
						|
         while i<10 do
 | 
						|
            begin
 | 
						|
                ...
 | 
						|
            end;
 | 
						|
 | 
						|
         When the loop is done, we do know that i<10 = false.
 | 
						|
        }
 | 
						|
        condition:=left.getcopy;
 | 
						|
        if condition.track_state_pass(exec_known) then
 | 
						|
            begin
 | 
						|
                track_state_pass:=true;
 | 
						|
                {Force new resultdef pass.}
 | 
						|
                condition.resultdef:=nil;
 | 
						|
                do_typecheckpass(condition);
 | 
						|
            end;
 | 
						|
        if not is_constboolnode(condition) then
 | 
						|
            aktstate.store_fact(condition,
 | 
						|
             cordconstnode.create(byte(checknegate),booltype,true))
 | 
						|
        else
 | 
						|
            condition.destroy;
 | 
						|
    end;
 | 
						|
{$endif}
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                               TIFNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tifnode.create(l,r,_t1 : tnode);
 | 
						|
      begin
 | 
						|
         inherited create(ifn,l,r,_t1,nil);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tifnode.internalsimplify(warn: boolean) : tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        { optimize constant expressions }
 | 
						|
        if left.nodetype=ordconstn then
 | 
						|
          begin
 | 
						|
             if tordconstnode(left).value=1 then
 | 
						|
               begin
 | 
						|
                  if assigned(right) then
 | 
						|
                    result:=right
 | 
						|
                  else
 | 
						|
                    result:=cnothingnode.create;
 | 
						|
                  right:=nil;
 | 
						|
                  if warn and assigned(t1) then
 | 
						|
                    CGMessagePos(t1.fileinfo,cg_w_unreachable_code);
 | 
						|
               end
 | 
						|
             else
 | 
						|
               begin
 | 
						|
                  if assigned(t1) then
 | 
						|
                    result:=t1
 | 
						|
                  else
 | 
						|
                    result:=cnothingnode.create;
 | 
						|
                  t1:=nil;
 | 
						|
                  if warn and assigned(right) then
 | 
						|
                    CGMessagePos(right.fileinfo,cg_w_unreachable_code);
 | 
						|
               end;
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tifnode.simplify : tnode;
 | 
						|
      begin
 | 
						|
        result:=internalsimplify(false);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tifnode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         resultdef:=voidtype;
 | 
						|
 | 
						|
         typecheckpass(left);
 | 
						|
 | 
						|
         { tp procvar support }
 | 
						|
         maybe_call_procvar(left,true);
 | 
						|
 | 
						|
         { if path }
 | 
						|
         if assigned(right) then
 | 
						|
           typecheckpass(right);
 | 
						|
         { else path }
 | 
						|
         if assigned(t1) then
 | 
						|
           typecheckpass(t1);
 | 
						|
         set_varstate(left,vs_read,[vsf_must_be_valid]);
 | 
						|
         if codegenerror then
 | 
						|
           exit;
 | 
						|
 | 
						|
         if not is_boolean(left.resultdef) then
 | 
						|
           begin
 | 
						|
             if left.resultdef.typ=variantdef then
 | 
						|
               inserttypeconv(left,booltype)
 | 
						|
             else
 | 
						|
               Message1(type_e_boolean_expr_expected,left.resultdef.typename);
 | 
						|
           end;
 | 
						|
         result:=internalsimplify(true);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tifnode.pass_1 : tnode;
 | 
						|
      var
 | 
						|
         old_t_times : longint;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
         old_t_times:=cg.t_times;
 | 
						|
         firstpass(left);
 | 
						|
         registersint:=left.registersint;
 | 
						|
         registersfpu:=left.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
         registersmmx:=left.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
 | 
						|
         { determines registers weigths }
 | 
						|
         if not(cs_opt_size in current_settings.optimizerswitches) then
 | 
						|
           cg.t_times:=cg.t_times div 2;
 | 
						|
         if cg.t_times=0 then
 | 
						|
           cg.t_times:=1;
 | 
						|
 | 
						|
         { if path }
 | 
						|
         if assigned(right) then
 | 
						|
           begin
 | 
						|
              firstpass(right);
 | 
						|
 | 
						|
              if registersint<right.registersint then
 | 
						|
                registersint:=right.registersint;
 | 
						|
              if registersfpu<right.registersfpu then
 | 
						|
                registersfpu:=right.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
              if registersmmx<right.registersmmx then
 | 
						|
                registersmmx:=right.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
 | 
						|
         { else path }
 | 
						|
         if assigned(t1) then
 | 
						|
           begin
 | 
						|
              firstpass(t1);
 | 
						|
 | 
						|
              if registersint<t1.registersint then
 | 
						|
                registersint:=t1.registersint;
 | 
						|
              if registersfpu<t1.registersfpu then
 | 
						|
                registersfpu:=t1.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
              if registersmmx<t1.registersmmx then
 | 
						|
                registersmmx:=t1.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
 | 
						|
         { leave if we've got an error in one of the paths }
 | 
						|
 | 
						|
         if codegenerror then
 | 
						|
           exit;
 | 
						|
 | 
						|
         cg.t_times:=old_t_times;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                              TFORNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
 | 
						|
 | 
						|
      begin
 | 
						|
         inherited create(forn,l,r,_t1,_t2);
 | 
						|
         if back then
 | 
						|
           include(loopflags,lnf_backward);
 | 
						|
         include(loopflags,lnf_testatbegin);
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure Tfornode.loop_var_access(not_type:Tnotification_flag;
 | 
						|
                                       symbol:Tsym);
 | 
						|
 | 
						|
    begin
 | 
						|
      {If there is a read access, the value of the loop counter is important;
 | 
						|
       at the end of the loop the loop variable should contain the value it
 | 
						|
       had in the last iteration.}
 | 
						|
      if not_type=vn_onwrite then
 | 
						|
        begin
 | 
						|
          writeln('Loopvar does not matter on exit');
 | 
						|
        end
 | 
						|
      else
 | 
						|
        begin
 | 
						|
          exclude(loopflags,lnf_dont_mind_loopvar_on_exit);
 | 
						|
          writeln('Loopvar does matter on exit');
 | 
						|
        end;
 | 
						|
      Tabstractvarsym(symbol).unregister_notification(loopvar_notid);
 | 
						|
    end;
 | 
						|
 | 
						|
    function tfornode.pass_typecheck:tnode;
 | 
						|
      var
 | 
						|
        unrollres : tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         resultdef:=voidtype;
 | 
						|
 | 
						|
         { loop unrolling }
 | 
						|
         if cs_opt_loopunroll in current_settings.optimizerswitches then
 | 
						|
           begin
 | 
						|
             unrollres:=unroll_loop(self);
 | 
						|
             if assigned(unrollres) then
 | 
						|
               begin
 | 
						|
                 typecheckpass(unrollres);
 | 
						|
                 result:=unrollres;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
           end;
 | 
						|
 | 
						|
         { process the loopvar, from and to, varstates are already set }
 | 
						|
         typecheckpass(left);
 | 
						|
         typecheckpass(right);
 | 
						|
         typecheckpass(t1);
 | 
						|
 | 
						|
         {Can we spare the first comparision?}
 | 
						|
         if (t1.nodetype=ordconstn) and
 | 
						|
            (right.nodetype=ordconstn) and
 | 
						|
            (
 | 
						|
             (
 | 
						|
              (lnf_backward in loopflags) and
 | 
						|
              (Tordconstnode(right).value>=Tordconstnode(t1).value)
 | 
						|
             ) or
 | 
						|
             (
 | 
						|
               not(lnf_backward in loopflags) and
 | 
						|
               (Tordconstnode(right).value<=Tordconstnode(t1).value)
 | 
						|
             )
 | 
						|
            ) then
 | 
						|
           exclude(loopflags,lnf_testatbegin);
 | 
						|
 | 
						|
         { Make sure that the loop var and the
 | 
						|
           from and to values are compatible types }
 | 
						|
         check_ranges(right.fileinfo,right,left.resultdef);
 | 
						|
         inserttypeconv(right,left.resultdef);
 | 
						|
 | 
						|
         check_ranges(t1.fileinfo,t1,left.resultdef);
 | 
						|
         inserttypeconv(t1,left.resultdef);
 | 
						|
 | 
						|
         if assigned(t2) then
 | 
						|
           typecheckpass(t2);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tfornode.pass_1 : tnode;
 | 
						|
      var
 | 
						|
         old_t_times : longint;
 | 
						|
     begin
 | 
						|
         result:=nil;
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
 | 
						|
         firstpass(left);
 | 
						|
         if left.registersint>registersint then
 | 
						|
           registersint:=left.registersint;
 | 
						|
         if left.registersfpu>registersfpu then
 | 
						|
           registersfpu:=left.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
         if left.registersmmx>registersmmx then
 | 
						|
           registersmmx:=left.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
 | 
						|
         firstpass(right);
 | 
						|
         if right.registersint>registersint then
 | 
						|
           registersint:=right.registersint;
 | 
						|
         if right.registersfpu>registersfpu then
 | 
						|
           registersfpu:=right.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
         if right.registersmmx>registersmmx then
 | 
						|
           registersmmx:=right.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
 | 
						|
         firstpass(t1);
 | 
						|
         if t1.registersint>registersint then
 | 
						|
           registersint:=t1.registersint;
 | 
						|
         if t1.registersfpu>registersfpu then
 | 
						|
           registersfpu:=t1.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
         if t1.registersmmx>registersmmx then
 | 
						|
           registersmmx:=t1.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
 | 
						|
         if assigned(t2) then
 | 
						|
          begin
 | 
						|
            { Calc register weight }
 | 
						|
            old_t_times:=cg.t_times;
 | 
						|
            if not(cs_opt_size in current_settings.optimizerswitches) then
 | 
						|
              cg.t_times:=cg.t_times*8;
 | 
						|
            firstpass(t2);
 | 
						|
            if codegenerror then
 | 
						|
             exit;
 | 
						|
            if t2.registersint>registersint then
 | 
						|
              registersint:=t2.registersint;
 | 
						|
            if t2.registersfpu>registersfpu then
 | 
						|
              registersfpu:=t2.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
            if t2.registersmmx>registersmmx then
 | 
						|
              registersmmx:=t2.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
            cg.t_times:=old_t_times;
 | 
						|
          end;
 | 
						|
 | 
						|
         { we need at least one register for comparisons PM }
 | 
						|
         if registersint=0 then
 | 
						|
           inc(registersint);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                             TEXITNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor texitnode.create(l:tnode);
 | 
						|
      begin
 | 
						|
        inherited create(exitn,l);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuload(t,ppufile);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuwrite(ppufile);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function texitnode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        if assigned(left) then
 | 
						|
          begin
 | 
						|
            { add assignment to funcretsym }
 | 
						|
            inserttypeconv(left,current_procinfo.procdef.returndef);
 | 
						|
            left:=cassignmentnode.create(
 | 
						|
                cloadnode.create(current_procinfo.procdef.funcretsym,current_procinfo.procdef.funcretsym.owner),
 | 
						|
                left);
 | 
						|
            typecheckpass(left);
 | 
						|
            set_varstate(left,vs_read,[vsf_must_be_valid]);
 | 
						|
          end;
 | 
						|
        resultdef:=voidtype;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function texitnode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
         if assigned(left) then
 | 
						|
           begin
 | 
						|
              firstpass(left);
 | 
						|
              if codegenerror then
 | 
						|
               exit;
 | 
						|
              registersint:=left.registersint;
 | 
						|
              registersfpu:=left.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
              registersmmx:=left.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                             TBREAKNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tbreaknode.create;
 | 
						|
 | 
						|
      begin
 | 
						|
        inherited create(breakn);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tbreaknode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        resultdef:=voidtype;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tbreaknode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        expectloc:=LOC_VOID;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                             TCONTINUENODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tcontinuenode.create;
 | 
						|
      begin
 | 
						|
        inherited create(continuen);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tcontinuenode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        resultdef:=voidtype;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tcontinuenode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        expectloc:=LOC_VOID;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                             TGOTONODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tgotonode.create(p : tlabelnode);
 | 
						|
      begin
 | 
						|
        inherited create(goton);
 | 
						|
        exceptionblock:=aktexceptblock;
 | 
						|
        labelnode:=p;
 | 
						|
        labelsym:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor tgotonode.create_sym(p : tlabelsym);
 | 
						|
      begin
 | 
						|
        inherited create(goton);
 | 
						|
        exceptionblock:=aktexceptblock;
 | 
						|
        if assigned(p.code) then
 | 
						|
          labelnode:=tlabelnode(p.code)
 | 
						|
        else
 | 
						|
          labelnode:=nil;
 | 
						|
        labelsym:=p;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor tgotonode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuload(t,ppufile);
 | 
						|
        labelnode:=tlabelnode(ppuloadnoderef(ppufile));
 | 
						|
        exceptionblock:=ppufile.getbyte;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tgotonode.ppuwrite(ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuwrite(ppufile);
 | 
						|
        ppuwritenoderef(ppufile,labelnode);
 | 
						|
        ppufile.putbyte(exceptionblock);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tgotonode.buildderefimpl;
 | 
						|
      begin
 | 
						|
        inherited buildderefimpl;
 | 
						|
        //!!! deref(labelnode);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tgotonode.derefimpl;
 | 
						|
      begin
 | 
						|
        inherited derefimpl;
 | 
						|
        //!!! deref(labelnode);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tgotonode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        resultdef:=voidtype;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tgotonode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        expectloc:=LOC_VOID;
 | 
						|
        include(current_procinfo.flags,pi_has_goto);
 | 
						|
 | 
						|
        if not(assigned(labelnode)) then
 | 
						|
          begin
 | 
						|
            if assigned(labelsym) and assigned(labelsym.code) then
 | 
						|
              labelnode:=tlabelnode(labelsym.code)
 | 
						|
            else
 | 
						|
              internalerror(200506183);
 | 
						|
          end;
 | 
						|
 | 
						|
        { check if we don't mess with exception blocks }
 | 
						|
        if assigned(labelnode) and
 | 
						|
           (exceptionblock<>labelnode.exceptionblock) then
 | 
						|
          CGMessage(cg_e_goto_inout_of_exception_block);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
   function tgotonode.dogetcopy : tnode;
 | 
						|
     var
 | 
						|
       p : tgotonode;
 | 
						|
     begin
 | 
						|
        p:=tgotonode(inherited dogetcopy);
 | 
						|
        p.exceptionblock:=exceptionblock;
 | 
						|
 | 
						|
        { force a valid labelnode }
 | 
						|
        if not(assigned(labelnode)) then
 | 
						|
          begin
 | 
						|
            if assigned(labelsym) and assigned(labelsym.code) then
 | 
						|
              labelnode:=tlabelnode(labelsym.code)
 | 
						|
            else
 | 
						|
              internalerror(200610291);
 | 
						|
          end;
 | 
						|
        p.labelnode:=tlabelnode(labelnode.dogetcopy);
 | 
						|
        result:=p;
 | 
						|
     end;
 | 
						|
 | 
						|
 | 
						|
    function tgotonode.docompare(p: tnode): boolean;
 | 
						|
      begin
 | 
						|
        docompare := false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                             TLABELNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tlabelnode.create(l:tnode);
 | 
						|
      begin
 | 
						|
        inherited create(labeln,l);
 | 
						|
        exceptionblock:=aktexceptblock;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor tlabelnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuload(t,ppufile);
 | 
						|
        exceptionblock:=ppufile.getbyte;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tlabelnode.ppuwrite(ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuwrite(ppufile);
 | 
						|
        ppufile.putbyte(exceptionblock);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tlabelnode.buildderefimpl;
 | 
						|
      begin
 | 
						|
        inherited buildderefimpl;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tlabelnode.derefimpl;
 | 
						|
      begin
 | 
						|
        inherited derefimpl;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tlabelnode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
        result:=nil;
 | 
						|
        { left could still be unassigned }
 | 
						|
        if assigned(left) then
 | 
						|
         typecheckpass(left);
 | 
						|
        resultdef:=voidtype;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tlabelnode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
         if assigned(left) then
 | 
						|
          begin
 | 
						|
            firstpass(left);
 | 
						|
            registersint:=left.registersint;
 | 
						|
            registersfpu:=left.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
            registersmmx:=left.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
   function tlabelnode.dogetcopy : tnode;
 | 
						|
     begin
 | 
						|
        if not(assigned(copiedto)) then
 | 
						|
          copiedto:=tlabelnode(inherited dogetcopy);
 | 
						|
        copiedto.exceptionblock:=exceptionblock;
 | 
						|
 | 
						|
        result:=copiedto;
 | 
						|
     end;
 | 
						|
 | 
						|
 | 
						|
    function tlabelnode.docompare(p: tnode): boolean;
 | 
						|
      begin
 | 
						|
        docompare := false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                            TRAISENODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor traisenode.create(l,taddr,tframe:tnode);
 | 
						|
      begin
 | 
						|
         inherited create(raisen,l,taddr,tframe);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function traisenode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         resultdef:=voidtype;
 | 
						|
         if assigned(left) then
 | 
						|
           begin
 | 
						|
              { first para must be a _class_ }
 | 
						|
              typecheckpass(left);
 | 
						|
              set_varstate(left,vs_read,[vsf_must_be_valid]);
 | 
						|
              if codegenerror then
 | 
						|
               exit;
 | 
						|
              if not(is_class(left.resultdef)) then
 | 
						|
                CGMessage1(type_e_class_type_expected,left.resultdef.typename);
 | 
						|
              { insert needed typeconvs for addr,frame }
 | 
						|
              if assigned(right) then
 | 
						|
               begin
 | 
						|
                 { addr }
 | 
						|
                 typecheckpass(right);
 | 
						|
                 inserttypeconv(right,voidpointertype);
 | 
						|
                 { frame }
 | 
						|
                 if assigned(frametree) then
 | 
						|
                  begin
 | 
						|
                    typecheckpass(frametree);
 | 
						|
                    inserttypeconv(frametree,voidpointertype);
 | 
						|
                  end;
 | 
						|
               end;
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function traisenode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         include(current_procinfo.flags,pi_do_call);
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
         if assigned(left) then
 | 
						|
           begin
 | 
						|
              { first para must be a _class_ }
 | 
						|
              firstpass(left);
 | 
						|
              { insert needed typeconvs for addr,frame }
 | 
						|
              if assigned(right) then
 | 
						|
               begin
 | 
						|
                 { addr }
 | 
						|
                 firstpass(right);
 | 
						|
                 { frame }
 | 
						|
                 if assigned(frametree) then
 | 
						|
                  firstpass(frametree);
 | 
						|
               end;
 | 
						|
              left_right_max;
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                             TTRYEXCEPTNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor ttryexceptnode.create(l,r,_t1 : tnode);
 | 
						|
      begin
 | 
						|
         inherited create(tryexceptn,l,r,_t1,nil);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function ttryexceptnode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         typecheckpass(left);
 | 
						|
         { on statements }
 | 
						|
         if assigned(right) then
 | 
						|
           typecheckpass(right);
 | 
						|
         { else block }
 | 
						|
         if assigned(t1) then
 | 
						|
           typecheckpass(t1);
 | 
						|
         resultdef:=voidtype;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function ttryexceptnode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         include(current_procinfo.flags,pi_do_call);
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
         firstpass(left);
 | 
						|
         { on statements }
 | 
						|
         if assigned(right) then
 | 
						|
           begin
 | 
						|
              firstpass(right);
 | 
						|
              registersint:=max(registersint,right.registersint);
 | 
						|
              registersfpu:=max(registersfpu,right.registersfpu);
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
              registersmmx:=max(registersmmx,right.registersmmx);
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
         { else block }
 | 
						|
         if assigned(t1) then
 | 
						|
           begin
 | 
						|
              firstpass(t1);
 | 
						|
              registersint:=max(registersint,t1.registersint);
 | 
						|
              registersfpu:=max(registersfpu,t1.registersfpu);
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
              registersmmx:=max(registersmmx,t1.registersmmx);
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                           TTRYFINALLYNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor ttryfinallynode.create(l,r:tnode);
 | 
						|
      begin
 | 
						|
        inherited create(tryfinallyn,l,r,nil,nil);
 | 
						|
        implicitframe:=false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor ttryfinallynode.create_implicit(l,r,_t1:tnode);
 | 
						|
      begin
 | 
						|
        inherited create(tryfinallyn,l,r,_t1,nil);
 | 
						|
        implicitframe:=true;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function ttryfinallynode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         include(current_procinfo.flags,pi_do_call);
 | 
						|
         resultdef:=voidtype;
 | 
						|
 | 
						|
         typecheckpass(left);
 | 
						|
         // "try block" is "used"? (JM)
 | 
						|
         set_varstate(left,vs_readwritten,[vsf_must_be_valid]);
 | 
						|
 | 
						|
         typecheckpass(right);
 | 
						|
         // "except block" is "used"? (JM)
 | 
						|
         set_varstate(right,vs_readwritten,[vsf_must_be_valid]);
 | 
						|
 | 
						|
         { special finally block only executed when there was an exception }
 | 
						|
         if assigned(t1) then
 | 
						|
           begin
 | 
						|
             typecheckpass(t1);
 | 
						|
             // "finally block" is "used"? (JM)
 | 
						|
             set_varstate(t1,vs_readwritten,[vsf_must_be_valid]);
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function ttryfinallynode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
         firstpass(left);
 | 
						|
 | 
						|
         firstpass(right);
 | 
						|
         left_right_max;
 | 
						|
 | 
						|
         if assigned(t1) then
 | 
						|
           begin
 | 
						|
             firstpass(t1);
 | 
						|
             registersint:=max(registersint,t1.registersint);
 | 
						|
             registersfpu:=max(registersfpu,t1.registersfpu);
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
             registersmmx:=max(registersmmx,t1.registersmmx);
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                TONNODE
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tonnode.create(l,r:tnode);
 | 
						|
      begin
 | 
						|
         inherited create(onn,l,r);
 | 
						|
         excepTSymtable:=nil;
 | 
						|
         excepttype:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    destructor tonnode.destroy;
 | 
						|
      begin
 | 
						|
        { copied nodes don't need to release the symtable }
 | 
						|
        if assigned(excepTSymtable) then
 | 
						|
         excepTSymtable.free;
 | 
						|
        inherited destroy;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor tonnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
 | 
						|
      begin
 | 
						|
        inherited ppuload(t,ppufile);
 | 
						|
        excepTSymtable:=nil;
 | 
						|
        excepttype:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tonnode.dogetcopy : tnode;
 | 
						|
      var
 | 
						|
         n : tonnode;
 | 
						|
      begin
 | 
						|
         n:=tonnode(inherited dogetcopy);
 | 
						|
         n.excepTSymtable:=excepTSymtable.getcopy;
 | 
						|
         n.excepttype:=excepttype;
 | 
						|
         result:=n;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tonnode.pass_typecheck:tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         resultdef:=voidtype;
 | 
						|
         if not(is_class(excepttype)) then
 | 
						|
           CGMessage1(type_e_class_type_expected,excepttype.typename);
 | 
						|
         if assigned(left) then
 | 
						|
           typecheckpass(left);
 | 
						|
         if assigned(right) then
 | 
						|
           typecheckpass(right);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tonnode.pass_1 : tnode;
 | 
						|
      begin
 | 
						|
         result:=nil;
 | 
						|
         include(current_procinfo.flags,pi_do_call);
 | 
						|
         expectloc:=LOC_VOID;
 | 
						|
         registersint:=0;
 | 
						|
         registersfpu:=0;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
         registersmmx:=0;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
         if assigned(left) then
 | 
						|
           begin
 | 
						|
              firstpass(left);
 | 
						|
              registersint:=left.registersint;
 | 
						|
              registersfpu:=left.registersfpu;
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
              registersmmx:=left.registersmmx;
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
 | 
						|
         if assigned(right) then
 | 
						|
           begin
 | 
						|
              firstpass(right);
 | 
						|
              registersint:=max(registersint,right.registersint);
 | 
						|
              registersfpu:=max(registersfpu,right.registersfpu);
 | 
						|
{$ifdef SUPPORT_MMX}
 | 
						|
              registersmmx:=max(registersmmx,right.registersmmx);
 | 
						|
{$endif SUPPORT_MMX}
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tonnode.docompare(p: tnode): boolean;
 | 
						|
      begin
 | 
						|
        docompare := false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
begin
 | 
						|
   cwhilerepeatnode:=twhilerepeatnode;
 | 
						|
   cifnode:=tifnode;
 | 
						|
   cfornode:=tfornode;
 | 
						|
   cexitnode:=texitnode;
 | 
						|
   cgotonode:=tgotonode;
 | 
						|
   clabelnode:=tlabelnode;
 | 
						|
   craisenode:=traisenode;
 | 
						|
   ctryexceptnode:=ttryexceptnode;
 | 
						|
   ctryfinallynode:=ttryfinallynode;
 | 
						|
   connode:=tonnode;
 | 
						|
end.
 |