summaryrefslogtreecommitdiff
path: root/compiler/node.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/node.pas')
-rw-r--r--compiler/node.pas1157
1 files changed, 1157 insertions, 0 deletions
diff --git a/compiler/node.pas b/compiler/node.pas
new file mode 100644
index 0000000000..330833d5cf
--- /dev/null
+++ b/compiler/node.pas
@@ -0,0 +1,1157 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Basic node handling
+
+ 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 node;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,
+ cpubase,cgbase,cgutils,
+ aasmbase,
+ symtype;
+
+ type
+ tnodetype = (
+ emptynode, {No node (returns nil when loading from ppu)}
+ addn, {Represents the + operator}
+ muln, {Represents the * operator}
+ subn, {Represents the - operator}
+ divn, {Represents the div operator}
+ symdifn, {Represents the >< operator}
+ modn, {Represents the mod operator}
+ assignn, {Represents an assignment}
+ loadn, {Represents the use of a variabele}
+ rangen, {Represents a range (i.e. 0..9)}
+ ltn, {Represents the < operator}
+ lten, {Represents the <= operator}
+ gtn, {Represents the > operator}
+ gten, {Represents the >= operator}
+ equaln, {Represents the = operator}
+ unequaln, {Represents the <> operator}
+ inn, {Represents the in operator}
+ orn, {Represents the or operator}
+ xorn, {Represents the xor operator}
+ shrn, {Represents the shr operator}
+ shln, {Represents the shl operator}
+ slashn, {Represents the / operator}
+ andn, {Represents the and operator}
+ subscriptn, {Field in a record/object}
+ derefn, {Dereferences a pointer}
+ addrn, {Represents the @ operator}
+ ordconstn, {Represents an ordinal value}
+ typeconvn, {Represents type-conversion/typecast}
+ calln, {Represents a call node}
+ callparan, {Represents a parameter}
+ realconstn, {Represents a real value}
+ unaryminusn, {Represents a sign change (i.e. -2)}
+ asmn, {Represents an assembler node }
+ vecn, {Represents array indexing}
+ pointerconstn, {Represents a pointer constant}
+ stringconstn, {Represents a string constant}
+ notn, {Represents the not operator}
+ inlinen, {Internal procedures (i.e. writeln)}
+ niln, {Represents the nil pointer}
+ errorn, {This part of the tree could not be
+ parsed because of a compiler error}
+ typen, {A type name. Used for i.e. typeof(obj)}
+ setelementn, {A set element(s) (i.e. [a,b] and also [a..b])}
+ setconstn, {A set constant (i.e. [1,2])}
+ blockn, {A block of statements}
+ statementn, {One statement in a block of nodes}
+ ifn, {An if statement}
+ breakn, {A break statement}
+ continuen, {A continue statement}
+ whilerepeatn, {A while or repeat statement}
+ forn, {A for loop}
+ exitn, {An exit statement}
+ withn, {A with statement}
+ casen, {A case statement}
+ labeln, {A label}
+ goton, {A goto statement}
+ tryexceptn, {A try except block}
+ raisen, {A raise statement}
+ tryfinallyn, {A try finally statement}
+ onn, {For an on statement in exception code}
+ isn, {Represents the is operator}
+ asn, {Represents the as typecast}
+ caretn, {Represents the ^ operator}
+ starstarn, {Represents the ** operator exponentiation }
+ arrayconstructorn, {Construction node for [...] parsing}
+ arrayconstructorrangen, {Range element to allow sets in array construction tree}
+ tempcreaten, { for temps in the result/firstpass }
+ temprefn, { references to temps }
+ tempdeleten, { for temps in the result/firstpass }
+ addoptn, { added for optimizations where we cannot suppress }
+ nothingn, {NOP, Do nothing}
+ loadvmtaddrn, {Load the address of the VMT of a class/object}
+ guidconstn, {A GUID COM Interface constant }
+ rttin, {Rtti information so they can be accessed in result/firstpass}
+ loadparentfpn { Load the framepointer of the parent for nested procedures }
+ );
+
+ const
+ nodetype2str : array[tnodetype] of string[24] = (
+ '<emptynode>',
+ 'addn',
+ 'muln',
+ 'subn',
+ 'divn',
+ 'symdifn',
+ 'modn',
+ 'assignn',
+ 'loadn',
+ 'rangen',
+ 'ltn',
+ 'lten',
+ 'gtn',
+ 'gten',
+ 'equaln',
+ 'unequaln',
+ 'inn',
+ 'orn',
+ 'xorn',
+ 'shrn',
+ 'shln',
+ 'slashn',
+ 'andn',
+ 'subscriptn',
+ 'derefn',
+ 'addrn',
+ 'ordconstn',
+ 'typeconvn',
+ 'calln',
+ 'callparan',
+ 'realconstn',
+ 'unaryminusn',
+ 'asmn',
+ 'vecn',
+ 'pointerconstn',
+ 'stringconstn',
+ 'notn',
+ 'inlinen',
+ 'niln',
+ 'errorn',
+ 'typen',
+ 'setelementn',
+ 'setconstn',
+ 'blockn',
+ 'statementn',
+ 'ifn',
+ 'breakn',
+ 'continuen',
+ 'whilerepeatn',
+ 'forn',
+ 'exitn',
+ 'withn',
+ 'casen',
+ 'labeln',
+ 'goton',
+ 'tryexceptn',
+ 'raisen',
+ 'tryfinallyn',
+ 'onn',
+ 'isn',
+ 'asn',
+ 'caretn',
+ 'starstarn',
+ 'arrayconstructn',
+ 'arrayconstructrangen',
+ 'tempcreaten',
+ 'temprefn',
+ 'tempdeleten',
+ 'addoptn',
+ 'nothingn',
+ 'loadvmtaddrn',
+ 'guidconstn',
+ 'rttin',
+ 'loadparentfpn');
+
+ type
+ { all boolean field of ttree are now collected in flags }
+ tnodeflag = (
+ nf_swapable, { tbinop operands can be swaped }
+ nf_swaped, { tbinop operands are swaped }
+ nf_error,
+
+ { general }
+ nf_pass1_done,
+ nf_write, { Node is written to }
+ nf_isproperty,
+
+ { taddrnode }
+ nf_typedaddr,
+
+ { tderefnode }
+ nf_no_checkpointer,
+
+ { tvecnode }
+ nf_memindex,
+ nf_memseg,
+ nf_callunique,
+
+ { tloadnode }
+ nf_absolute,
+ nf_is_self,
+ nf_load_self_pointer,
+
+ { taddnode }
+ nf_is_currency,
+ nf_has_pointerdiv,
+
+ { tassignmentnode }
+ nf_concat_string,
+ nf_use_strconcat,
+
+ { tarrayconstructnode }
+ nf_forcevaria,
+ nf_novariaallowed,
+
+ { ttypeconvnode }
+ nf_explicit,
+ nf_internal, { no warnings/hints generated }
+ nf_load_procvar,
+
+ { tinlinenode }
+ nf_inlineconst,
+
+ { tasmnode }
+ nf_get_asm_position,
+
+ { tblocknode }
+ nf_block_with_exit
+ );
+
+ tnodeflags = set of tnodeflag;
+
+ const
+ { contains the flags which must be equal for the equality }
+ { of nodes }
+ flagsequal : tnodeflags = [nf_error];
+
+ type
+ tnodelist = class
+ end;
+
+ { later (for the newcg) tnode will inherit from tlinkedlist_item }
+ tnode = class
+ public
+ { type of this node }
+ nodetype : tnodetype;
+ { type of the current code block, general/const/type }
+ blocktype : tblock_type;
+ { expected location of the result of this node (pass1) }
+ expectloc : tcgloc;
+ { the location of the result of this node (pass2) }
+ location : tlocation;
+ { the parent node of this is node }
+ { this field is set by concattolist }
+ parent : tnode;
+ { there are some properties about the node stored }
+ flags : tnodeflags;
+ ppuidx : longint;
+ { the number of registers needed to evalute the node }
+ registersint,registersfpu,registersmm : longint; { must be longint !!!! }
+{$ifdef SUPPORT_MMX}
+ registersmmx : longint;
+{$endif SUPPORT_MMX}
+ resulttype : ttype;
+ fileinfo : tfileposinfo;
+ localswitches : tlocalswitches;
+{$ifdef extdebug}
+ maxfirstpasscount,
+ firstpasscount : longint;
+{$endif extdebug}
+ constructor create(t:tnodetype);
+ { this constructor is only for creating copies of class }
+ { the fields are copied by getcopy }
+ constructor createforcopy;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);virtual;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ procedure buildderefimpl;virtual;
+ procedure derefimpl;virtual;
+ procedure derefnode;virtual;
+
+ { toggles the flag }
+ procedure toggleflag(f : tnodeflag);
+
+ { the 1.1 code generator may override pass_1 }
+ { and it need not to implement det_* then }
+ { 1.1: pass_1 returns a value<>0 if the node has been transformed }
+ { 2.0: runs det_resulttype and det_temp }
+ function pass_1 : tnode;virtual;abstract;
+ { dermines the resulttype of the node }
+ function det_resulttype : tnode;virtual;abstract;
+
+ { tries to simplify the node, returns a value <>nil if a simplified
+ node has been created }
+ function simplify : tnode;virtual;
+{$ifdef state_tracking}
+ { Does optimizations by keeping track of the variable states
+ in a procedure }
+ function track_state_pass(exec_known:boolean):boolean;virtual;
+{$endif}
+ { For a t1:=t2 tree, mark the part of the tree t1 that gets
+ written to (normally the loadnode) as write access. }
+ procedure mark_write;virtual;
+ { dermines the number of necessary temp. locations to evaluate
+ the node }
+ procedure det_temp;virtual;abstract;
+
+ procedure pass_2;virtual;abstract;
+
+ { comparing of nodes }
+ function isequal(p : tnode) : boolean;
+ { to implement comparisation, override this method }
+ function docompare(p : tnode) : boolean;virtual;
+ { wrapper for getcopy }
+ function getcopy : tnode;
+
+ { does the real copying of a node }
+ function _getcopy : tnode;virtual;
+
+ procedure insertintolist(l : tnodelist);virtual;
+ { writes a node for debugging purpose, shouldn't be called }
+ { direct, because there is no test for nil, use printnode }
+ { to write a complete tree }
+ procedure printnodeinfo(var t:text);virtual;
+ procedure printnodedata(var t:text);virtual;
+ procedure printnodetree(var t:text);virtual;
+ procedure concattolist(l : tlinkedlist);virtual;
+ function ischild(p : tnode) : boolean;virtual;
+ end;
+
+ tnodeclass = class of tnode;
+
+ tnodeclassarray = array[tnodetype] of tnodeclass;
+
+ { this node is the anchestor for all nodes with at least }
+ { one child, you have to use it if you want to use }
+ { true- and falselabel }
+ punarynode = ^tunarynode;
+ tunarynode = class(tnode)
+ left : tnode;
+ constructor create(t:tnodetype;l : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure derefnode;override;
+ procedure concattolist(l : tlinkedlist);override;
+ function ischild(p : tnode) : boolean;override;
+ function docompare(p : tnode) : boolean;override;
+ function _getcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure left_max;
+ procedure printnodedata(var t:text);override;
+ end;
+
+ pbinarynode = ^tbinarynode;
+ tbinarynode = class(tunarynode)
+ right : tnode;
+ constructor create(t:tnodetype;l,r : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure derefnode;override;
+ procedure concattolist(l : tlinkedlist);override;
+ function ischild(p : tnode) : boolean;override;
+ function docompare(p : tnode) : boolean;override;
+ procedure swapleftright;
+ function _getcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure left_right_max;
+ procedure printnodedata(var t:text);override;
+ procedure printnodelist(var t:text);
+ end;
+
+ tbinopnode = class(tbinarynode)
+ constructor create(t:tnodetype;l,r : tnode);virtual;
+ function docompare(p : tnode) : boolean;override;
+ end;
+
+ var
+ { array with all class types for tnodes }
+ nodeclass : tnodeclassarray;
+
+ function nodeppuidxget(i:longint):tnode;
+ function ppuloadnode(ppufile:tcompilerppufile):tnode;
+ procedure ppuwritenode(ppufile:tcompilerppufile;n:tnode);
+ function ppuloadnodetree(ppufile:tcompilerppufile):tnode;
+ procedure ppuwritenodetree(ppufile:tcompilerppufile;n:tnode);
+ procedure ppuwritenoderef(ppufile:tcompilerppufile;n:tnode);
+ function ppuloadnoderef(ppufile:tcompilerppufile) : tnode;
+
+ const
+ printnodespacing = ' ';
+ var
+ { indention used when writing the tree to the screen }
+ printnodeindention : string;
+
+ procedure printnodeindent;
+ procedure printnodeunindent;
+ procedure printnode(var t:text;n:tnode);
+
+ function is_constnode(p : tnode) : boolean;
+ function is_constintnode(p : tnode) : boolean;
+ function is_constcharnode(p : tnode) : boolean;
+ function is_constrealnode(p : tnode) : boolean;
+ function is_constboolnode(p : tnode) : boolean;
+ function is_constenumnode(p : tnode) : boolean;
+ function is_constwidecharnode(p : tnode) : boolean;
+
+
+implementation
+
+ uses
+ cutils,verbose,ppu,
+ symconst,
+ defutil;
+
+ const
+ ppunodemarker = 255;
+
+
+{****************************************************************************
+ Helpers
+ ****************************************************************************}
+
+ var
+ nodeppudata : tdynamicarray;
+ nodeppuidx : longint;
+
+
+ procedure nodeppuidxcreate;
+ begin
+ nodeppudata:=tdynamicarray.create(1024);
+ nodeppuidx:=0;
+ end;
+
+
+ procedure nodeppuidxfree;
+ begin
+ nodeppudata.free;
+ nodeppudata:=nil;
+ end;
+
+
+ procedure nodeppuidxadd(n:tnode);
+ begin
+ if n.ppuidx<0 then
+ internalerror(200311072);
+ nodeppudata.seek(n.ppuidx*sizeof(pointer));
+ nodeppudata.write(n,sizeof(pointer));
+ end;
+
+
+ function nodeppuidxget(i:longint):tnode;
+ begin
+ if i<0 then
+ internalerror(200311072);
+ nodeppudata.seek(i*sizeof(pointer));
+ if nodeppudata.read(result,sizeof(pointer))<>sizeof(pointer) then
+ internalerror(200311073);
+ end;
+
+
+ function ppuloadnode(ppufile:tcompilerppufile):tnode;
+ var
+ b : byte;
+ t : tnodetype;
+ hppuidx : longint;
+ begin
+ { marker }
+ b:=ppufile.getbyte;
+ if b<>ppunodemarker then
+ internalerror(200208151);
+ { load nodetype }
+ t:=tnodetype(ppufile.getbyte);
+ if t>high(tnodetype) then
+ internalerror(200208152);
+ if t<>emptynode then
+ begin
+ if not assigned(nodeclass[t]) then
+ internalerror(200208153);
+ hppuidx:=ppufile.getlongint;
+ //writeln('load: ',nodetype2str[t]);
+ { generate node of the correct class }
+ result:=nodeclass[t].ppuload(t,ppufile);
+ result.ppuidx:=hppuidx;
+ nodeppuidxadd(result);
+ end
+ else
+ result:=nil;
+ end;
+
+
+ procedure ppuwritenode(ppufile:tcompilerppufile;n:tnode);
+ begin
+ { marker, read by ppuloadnode }
+ ppufile.putbyte(ppunodemarker);
+ { type, read by ppuloadnode }
+ if assigned(n) then
+ begin
+ if n.ppuidx=-1 then
+ internalerror(200311071);
+ n.ppuidx:=nodeppuidx;
+ inc(nodeppuidx);
+ ppufile.putbyte(byte(n.nodetype));
+ ppufile.putlongint(n.ppuidx);
+ //writeln('write: ',nodetype2str[n.nodetype]);
+ n.ppuwrite(ppufile);
+ end
+ else
+ ppufile.putbyte(byte(emptynode));
+ end;
+
+
+ procedure ppuwritenoderef(ppufile:tcompilerppufile;n:tnode);
+ begin
+ { writing of node references isn't implemented yet (FK) }
+ internalerror(200506181);
+ end;
+
+
+ function ppuloadnoderef(ppufile:tcompilerppufile) : tnode;
+ begin
+ { reading of node references isn't implemented yet (FK) }
+ internalerror(200506182);
+ end;
+
+
+ function ppuloadnodetree(ppufile:tcompilerppufile):tnode;
+ begin
+ if ppufile.readentry<>ibnodetree then
+ Message(unit_f_ppu_read_error);
+ nodeppuidxcreate;
+ result:=ppuloadnode(ppufile);
+ result.derefnode;
+ nodeppuidxfree;
+ end;
+
+
+ procedure ppuwritenodetree(ppufile:tcompilerppufile;n:tnode);
+ begin
+ nodeppuidx:=0;
+ ppuwritenode(ppufile,n);
+ ppufile.writeentry(ibnodetree);
+ end;
+
+
+ procedure printnodeindent;
+ begin
+ printnodeindention:=printnodeindention+printnodespacing;
+ end;
+
+
+ procedure printnodeunindent;
+ begin
+ delete(printnodeindention,1,length(printnodespacing));
+ end;
+
+
+ procedure printnode(var t:text;n:tnode);
+ begin
+ if assigned(n) then
+ n.printnodetree(t)
+ else
+ writeln(t,printnodeindention,'nil');
+ end;
+
+
+ function is_constnode(p : tnode) : boolean;
+ begin
+ is_constnode:=(p.nodetype in [niln,ordconstn,realconstn,stringconstn,setconstn,guidconstn]);
+ end;
+
+
+ function is_constintnode(p : tnode) : boolean;
+ begin
+ is_constintnode:=(p.nodetype=ordconstn) and is_integer(p.resulttype.def);
+ end;
+
+
+ function is_constcharnode(p : tnode) : boolean;
+ begin
+ is_constcharnode:=(p.nodetype=ordconstn) and is_char(p.resulttype.def);
+ end;
+
+
+ function is_constwidecharnode(p : tnode) : boolean;
+ begin
+ is_constwidecharnode:=(p.nodetype=ordconstn) and is_widechar(p.resulttype.def);
+ end;
+
+
+ function is_constrealnode(p : tnode) : boolean;
+ begin
+ is_constrealnode:=(p.nodetype=realconstn);
+ end;
+
+
+ function is_constboolnode(p : tnode) : boolean;
+ begin
+ is_constboolnode:=(p.nodetype=ordconstn) and is_boolean(p.resulttype.def);
+ end;
+
+
+ function is_constenumnode(p : tnode) : boolean;
+ begin
+ is_constenumnode:=(p.nodetype=ordconstn) and (p.resulttype.def.deftype=enumdef);
+ end;
+
+{****************************************************************************
+ TNODE
+ ****************************************************************************}
+
+ constructor tnode.create(t:tnodetype);
+
+ begin
+ inherited create;
+ nodetype:=t;
+ blocktype:=block_type;
+ { updated by firstpass }
+ expectloc:=LOC_INVALID;
+ { updated by secondpass }
+ location.loc:=LOC_INVALID;
+ { save local info }
+ fileinfo:=aktfilepos;
+ localswitches:=aktlocalswitches;
+ resulttype.reset;
+ registersint:=0;
+ registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=0;
+{$endif SUPPORT_MMX}
+{$ifdef EXTDEBUG}
+ maxfirstpasscount:=0;
+ firstpasscount:=0;
+{$endif EXTDEBUG}
+ flags:=[];
+ ppuidx:=-1;
+ end;
+
+ constructor tnode.createforcopy;
+
+ begin
+ end;
+
+ constructor tnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+
+ begin
+ nodetype:=t;
+ { tnode fields }
+ blocktype:=tblock_type(ppufile.getbyte);
+ ppufile.getposinfo(fileinfo);
+ ppufile.getsmallset(localswitches);
+ ppufile.gettype(resulttype);
+ ppufile.getsmallset(flags);
+ { updated by firstpass }
+ expectloc:=LOC_INVALID;
+ { updated by secondpass }
+ location.loc:=LOC_INVALID;
+ registersint:=0;
+ registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=0;
+{$endif SUPPORT_MMX}
+{$ifdef EXTDEBUG}
+ maxfirstpasscount:=0;
+ firstpasscount:=0;
+{$endif EXTDEBUG}
+ ppuidx:=-1;
+ end;
+
+
+ procedure tnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ ppufile.putbyte(byte(block_type));
+ ppufile.putposinfo(fileinfo);
+ ppufile.putsmallset(localswitches);
+ ppufile.puttype(resulttype);
+ ppufile.putsmallset(flags);
+ end;
+
+
+ procedure tnode.buildderefimpl;
+ begin
+ resulttype.buildderef;
+ end;
+
+
+ procedure tnode.derefimpl;
+ begin
+ resulttype.resolve;
+ end;
+
+
+ procedure tnode.derefnode;
+ begin
+ end;
+
+
+ procedure tnode.toggleflag(f : tnodeflag);
+ begin
+ if f in flags then
+ exclude(flags,f)
+ else
+ include(flags,f);
+ end;
+
+
+ function tnode.simplify : tnode;
+ begin
+ result:=nil;
+ end;
+
+
+ destructor tnode.destroy;
+ begin
+{$ifdef EXTDEBUG}
+ if firstpasscount>maxfirstpasscount then
+ maxfirstpasscount:=firstpasscount;
+{$endif EXTDEBUG}
+ end;
+
+
+ procedure tnode.concattolist(l : tlinkedlist);
+ begin
+ end;
+
+
+ function tnode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=false;
+ end;
+
+
+ procedure tnode.mark_write;
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'mark_write not implemented for '+nodetype2str[nodetype]);
+{$endif EXTDEBUG}
+ end;
+
+
+ procedure tnode.printnodeinfo(var t:text);
+ begin
+ write(t,nodetype2str[nodetype]);
+ if assigned(resulttype.def) then
+ write(t,', resulttype = "',resulttype.def.gettypename,'"')
+ else
+ write(t,', resulttype = <nil>');
+ write(t,', pos = (',fileinfo.line,',',fileinfo.column,')',
+ ', loc = ',tcgloc2str[location.loc],
+ ', expectloc = ',tcgloc2str[expectloc],
+ ', intregs = ',registersint,
+ ', fpuregs = ',registersfpu);
+ end;
+
+
+ procedure tnode.printnodedata(var t:text);
+ begin
+ end;
+
+
+ procedure tnode.printnodetree(var t:text);
+ begin
+ write(t,printnodeindention,'(');
+ printnodeinfo(t);
+ writeln(t);
+ printnodeindent;
+ printnodedata(t);
+ printnodeunindent;
+ writeln(t,printnodeindention,')');
+ end;
+
+
+ function tnode.isequal(p : tnode) : boolean;
+ begin
+ isequal:=
+ (not assigned(self) and not assigned(p)) or
+ (assigned(self) and assigned(p) and
+ { optimized subclasses have the same nodetype as their }
+ { superclass (for compatibility), so also check the classtype (JM) }
+ (p.classtype=classtype) and
+ (p.nodetype=nodetype) and
+ (flags*flagsequal=p.flags*flagsequal) and
+ docompare(p));
+ end;
+
+{$ifdef state_tracking}
+ function Tnode.track_state_pass(exec_known:boolean):boolean;
+ begin
+ track_state_pass:=false;
+ end;
+{$endif state_tracking}
+
+
+ function tnode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=true;
+ end;
+
+
+ function tnode.getcopy : tnode;
+ begin
+ result:=_getcopy;
+ end;
+
+
+ function tnode._getcopy : tnode;
+ var
+ p : tnode;
+ begin
+ { this is quite tricky because we need a node of the current }
+ { node type and not one of tnode! }
+ p:=tnodeclass(classtype).createforcopy;
+ p.nodetype:=nodetype;
+ p.expectloc:=expectloc;
+ p.location:=location;
+ p.parent:=parent;
+ p.flags:=flags;
+ p.registersint:=registersint;
+ p.registersfpu:=registersfpu;
+{$ifdef SUPPORT_MMX}
+ p.registersmmx:=registersmmx;
+ p.registersmm:=registersmm;
+{$endif SUPPORT_MMX}
+ p.resulttype:=resulttype;
+ p.fileinfo:=fileinfo;
+ p.localswitches:=localswitches;
+{$ifdef extdebug}
+ p.firstpasscount:=firstpasscount;
+{$endif extdebug}
+{ p.list:=list; }
+ result:=p;
+ end;
+
+
+ procedure tnode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+{****************************************************************************
+ TUNARYNODE
+ ****************************************************************************}
+
+ constructor tunarynode.create(t:tnodetype;l : tnode);
+ begin
+ inherited create(t);
+ left:=l;
+ end;
+
+
+ constructor tunarynode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ left:=ppuloadnode(ppufile);
+ end;
+
+
+ destructor tunarynode.destroy;
+ begin
+ left.free;
+ inherited destroy;
+ end;
+
+
+ procedure tunarynode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,left);
+ end;
+
+
+ procedure tunarynode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(left) then
+ left.buildderefimpl;
+ end;
+
+
+ procedure tunarynode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(left) then
+ left.derefimpl;
+ end;
+
+
+ procedure tunarynode.derefnode;
+ begin
+ inherited derefnode;
+ if assigned(left) then
+ left.derefnode;
+ end;
+
+
+ function tunarynode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p) and
+ ((left=nil) or left.isequal(tunarynode(p).left))
+ );
+ end;
+
+
+ function tunarynode._getcopy : tnode;
+ var
+ p : tunarynode;
+ begin
+ p:=tunarynode(inherited _getcopy);
+ if assigned(left) then
+ p.left:=left._getcopy
+ else
+ p.left:=nil;
+ result:=p;
+ end;
+
+
+ procedure tunarynode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ procedure tunarynode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ printnode(t,left);
+ end;
+
+
+ procedure tunarynode.left_max;
+ begin
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+
+ procedure tunarynode.concattolist(l : tlinkedlist);
+ begin
+ left.parent:=self;
+ left.concattolist(l);
+ inherited concattolist(l);
+ end;
+
+
+ function tunarynode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=p=left;
+ end;
+
+
+{****************************************************************************
+ TBINARYNODE
+ ****************************************************************************}
+
+ constructor tbinarynode.create(t:tnodetype;l,r : tnode);
+ begin
+ inherited create(t,l);
+ right:=r
+ end;
+
+
+ constructor tbinarynode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ right:=ppuloadnode(ppufile);
+ end;
+
+
+ destructor tbinarynode.destroy;
+ begin
+ right.free;
+ inherited destroy;
+ end;
+
+
+ procedure tbinarynode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,right);
+ end;
+
+
+ procedure tbinarynode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(right) then
+ right.buildderefimpl;
+ end;
+
+
+ procedure tbinarynode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(right) then
+ right.derefimpl;
+ end;
+
+
+ procedure tbinarynode.derefnode;
+ begin
+ inherited derefnode;
+ if assigned(right) then
+ right.derefnode;
+ end;
+
+
+ procedure tbinarynode.concattolist(l : tlinkedlist);
+ begin
+ { we could change that depending on the number of }
+ { required registers }
+ left.parent:=self;
+ left.concattolist(l);
+ left.parent:=self;
+ left.concattolist(l);
+ inherited concattolist(l);
+ end;
+
+
+ function tbinarynode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=(p=right);
+ end;
+
+
+ function tbinarynode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p) and
+ ((right=nil) or right.isequal(tbinarynode(p).right))
+ );
+ end;
+
+
+ function tbinarynode._getcopy : tnode;
+ var
+ p : tbinarynode;
+ begin
+ p:=tbinarynode(inherited _getcopy);
+ if assigned(right) then
+ p.right:=right._getcopy
+ else
+ p.right:=nil;
+ result:=p;
+ end;
+
+
+ procedure tbinarynode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ procedure tbinarynode.swapleftright;
+ var
+ swapp : tnode;
+ begin
+ swapp:=right;
+ right:=left;
+ left:=swapp;
+ if nf_swaped in flags then
+ exclude(flags,nf_swaped)
+ else
+ include(flags,nf_swaped);
+ end;
+
+
+ procedure tbinarynode.left_right_max;
+ begin
+ if assigned(left) then
+ begin
+ if assigned(right) then
+ begin
+ registersint:=max(left.registersint,right.registersint);
+ registersfpu:=max(left.registersfpu,right.registersfpu);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(left.registersmmx,right.registersmmx);
+{$endif SUPPORT_MMX}
+ end
+ else
+ begin
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+ end;
+ end;
+
+
+ procedure tbinarynode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ printnode(t,right);
+ end;
+
+
+ procedure tbinarynode.printnodelist(var t:text);
+ var
+ hp : tbinarynode;
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ write(t,printnodeindention,'(');
+ printnodeindent;
+ hp.printnodeinfo(t);
+ writeln(t);
+ printnode(t,hp.left);
+ writeln(t);
+ printnodeunindent;
+ writeln(t,printnodeindention,')');
+ hp:=tbinarynode(hp.right);
+ end;
+ end;
+
+
+{****************************************************************************
+ TBINOPYNODE
+ ****************************************************************************}
+
+ constructor tbinopnode.create(t:tnodetype;l,r : tnode);
+ begin
+ inherited create(t,l,r);
+ end;
+
+
+ function tbinopnode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p)) or
+ { if that's in the flags, is p then always a tbinopnode (?) (JM) }
+ ((nf_swapable in flags) and
+ left.isequal(tbinopnode(p).right) and
+ right.isequal(tbinopnode(p).left));
+ end;
+
+end.