{ $Id$ Copyright (c) 1993-98 by Florian Klaempfl This units exports some routines to manage the parse tree 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. **************************************************************************** } {$ifdef tp} {E+,N+} {$endif} unit tree; interface uses objects,globals,symtable,cobjects,verbose,aasm,files {$ifdef i386} ,i386 {$endif} {$ifdef m68k} ,m68k {$endif} {$ifdef alpha} ,alpha {$endif} ; type tconstset = array[0..31] of byte; pconstset = ^tconstset; ttreetyp = (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.} doubleaddrn, {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.} fixconstn, {Represents a fixed value.} umminusn, {Represents a sign change (i.e. -2).} asmn, {Represents an assembler node } vecn, {Represents array indexing.} stringconstn, {Represents a string constant.} funcretn, {Represents the function result var.} selfn, {Represents the self parameter.} 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).} hnewn, {The new operation, constructor call.} hdisposen, {The dispose operation with destructor call.} newn, {The new operation, constructor call.} simpledisposen, {The dispose operation.} setelen, {A set element (i.e. [a,b]).} setconstrn, {A set constant (i.e. [1,2]).} blockn, {A block of statements.} anwein, {A linear list of nodes.} loopn, { used in genloopnode, must be converted } ifn, {An if statement.} breakn, {A break statement.} continuen, {A continue statement.} repeatn, {A repeat until block.} whilen, {A while do statement.} forn, {A for loop.} exitn, {An exit statement.} withn, {A with statement.} casen, {A case statement.} labeln, {A label.} goton, {A goto statement.} simplenewn, {The new operation.} tryexceptn, {A try except block.} raisen, {A raise statement.} switchesn, {??? Currently unused...} tryfinallyn, {A try finally statement.} isn, {Represents the is operator.} asn, {Represents the as typecast.} caretn, {Represents the ^ operator.} failn, {Represents the fail statement.} { added for optimizations where we cannot suppress } nothingn, loadvmtn); {???.} tconverttype = (tc_equal,tc_not_possible,tc_u8bit_2_s32bit, tc_only_rangechecks32bit,tc_s8bit_2_s32bit, tc_u16bit_2_s32bit,tc_s16bit_2_s32bit, tc_s32bit_2_s16bit,tc_s32bit_2_u8bit, tc_s32bit_2_u16bit,tc_string_to_string, tc_cstring_charpointer,tc_string_chararray, tc_array_to_pointer,tc_pointer_to_array, tc_char_to_string,tc_u8bit_2_s16bit, tc_u8bit_2_u16bit,tc_s8bit_2_s16bit, tc_s16bit_2_s8bit,tc_s16bit_2_u8bit, tc_u16bit_2_s8bit,tc_u16bit_2_u8bit, tc_s8bit_2_u16bit,tc_s32bit_2_s8bit, tc_s32bit_2_u32bit,tc_s16bit_2_u32bit, tc_s8bit_2_u32bit,tc_u16bit_2_u32bit, tc_u8bit_2_u32bit,tc_u32bit_2_s32bit, tc_int_2_real,tc_real_2_fix, tc_fix_2_real,tc_int_2_fix,tc_real_2_real, tc_chararray_2_string,tc_bool_2_u8bit, tc_proc2procvar, tc_cchar_charpointer); { allows to determine which elementes are to be replaced } tdisposetyp = (dt_nothing,dt_leftright,dt_left, dt_mbleft,dt_string,dt_typeconv,dt_inlinen, dt_mbleft_and_method,dt_constset,dt_loop,dt_case, dt_with); { different assignment types } tassigntyp = (at_normal,at_plus,at_minus,at_star,at_slash); pcaserecord = ^tcaserecord; tcaserecord = record { range } _low,_high : longint; { only used by gentreejmp } _at : plabel; { label of instruction } statement : plabel; { left and right tree node } less,greater : pcaserecord; end; ptree = ^ttree; ttree = record error : boolean; disposetyp : tdisposetyp; { is true, if the right and left operand are swaped } swaped : boolean; { the location of the result of this node } location : tlocation; { the number of registers needed to evalute the node } registers32,registersfpu : longint; { must be longint !!!! } {$ifdef SUPPORT_MMX} registersmmx : longint; {$endif SUPPORT_MMX} left,right : ptree; resulttype : pdef; inputfile : pinputfile; {$ifdef TP} line:word; {$else} line : longint; {$endif} pragmas : Tcswitches; {$ifdef extdebug} firstpasscount : longint; {$endif extdebug} case treetype : ttreetyp of callparan : (is_colon_para : boolean;exact_match_found : boolean); assignn : (assigntyp : tassigntyp); loadn : (symtableentry : psym;symtable : psymtable; is_absolute,is_first : boolean); calln : (symtableprocentry : pprocsym; symtableproc : psymtable;procdefinition : pprocdef; methodpointer : ptree; unit_specific : boolean); ordconstn : (value : longint); realconstn : (valued : bestreal;labnumber : longint;realtyp : tait); fixconstn : (valuef: longint); {$ifdef TEST_FUNCRET} funcretn : (funcretprocinfo : pointer;retdef : pdef); {$endif TEST_FUNCRET} subscriptn : (vs : pvarsym); vecn : (memindex,memseg:boolean); stringconstn : (values : pstring;labstrnumber : longint); typeconvn : (convtyp : tconverttype;explizit : boolean); inlinen : (inlinenumber : longint); { procinlinen : (proc : pprocsym); } setconstrn : (constset : pconstset); loopn : (t1,t2 : ptree;backward : boolean); asmn : (p_asm : paasmoutput); casen : (nodes : pcaserecord;elseblock : ptree); labeln,goton : (labelnr : plabel); withn : (withsymtable : psymtable;tablecount : longint); end; procedure init_tree; function gennode(t : ttreetyp;l,r : ptree) : ptree; function genlabelnode(t : ttreetyp;nr : plabel) : ptree; function genloadnode(v : pvarsym;st : psymtable) : ptree; function gensinglenode(t : ttreetyp;l : ptree) : ptree; function gensubscriptnode(varsym : pvarsym;l : ptree) : ptree; function genordinalconstnode(v : longint;def : pdef) : ptree; function genfixconstnode(v : longint;def : pdef) : ptree; function gentypeconvnode(node : ptree;t : pdef) : ptree; function gencallparanode(expr,next : ptree) : ptree; function genrealconstnode(v : bestreal) : ptree; function gencallnode(v : pprocsym;st : psymtable) : ptree; function genmethodcallnode(v : pprocsym;st : psymtable;mp : ptree) : ptree; function genstringconstnode(const s : string) : ptree; function genzeronode(t : ttreetyp) : ptree; function geninlinenode(number : longint;l : ptree) : ptree; { function genprocinlinenode(code : ptree;procsym : pprocsym) : ptree; } function gentypedconstloadnode(sym : ptypedconstsym;st : psymtable) : ptree; function genenumnode(v : penumsym) : ptree; function genselfnode(_class : pdef) : ptree; function gensetconstruktnode(s : pconstset;settype : psetdef) : ptree; function genloopnode(t : ttreetyp;l,r,n1: ptree;back : boolean) : ptree; function genasmnode(p_asm : paasmoutput) : ptree; function gencasenode(l,r : ptree;nodes : pcaserecord) : ptree; function genwithnode(symtable : psymtable;l,r : ptree;count : longint) : ptree; function getcopy(p : ptree) : ptree; function equal_trees(t1,t2 : ptree) : boolean; procedure disposetree(p : ptree); procedure putnode(p : ptree); function getnode : ptree; procedure clearnodes; procedure set_location(var destloc,sourceloc : tlocation); procedure swap_location(var destloc,sourceloc : tlocation); procedure set_file_line(from,_to : ptree); {$ifdef extdebug} const maxfirstpasscount : longint = 0; {$endif extdebug} {$I innr.inc} implementation const oldswitches : tcswitches = []; {**************************************************************************** this is a pool for the tree nodes to get more performance ****************************************************************************} var root : ptree; procedure init_tree; begin root:=nil; end; procedure clearnodes; var hp : ptree; begin hp:=root; while assigned(hp) do begin root:=hp^.left; dispose(hp); hp:=root; end; end; function getnode : ptree; var hp : ptree; begin if root=nil then new(hp) else begin hp:=root; root:=root^.left; end; { makes error tracking easier } fillchar(hp^,sizeof(ttree),#0); hp^.location.loc:=LOC_INVALID; { new node is error free } hp^.error:=false; { we know also the position } hp^.line:=current_module^.current_inputfile^.line_no; hp^.inputfile:=current_module^.current_inputfile; hp^.pragmas:=aktswitches; getnode:=hp; end; procedure putnode(p : ptree); begin { clean up the contents of a node } if p^.treetype=asmn then if assigned(p^.p_asm) then dispose(p^.p_asm,done); if p^.treetype=setconstrn then if assigned(p^.constset) then dispose(p^.constset); if (p^.location.loc=LOC_MEM) or (p^.location.loc=LOC_REFERENCE) and assigned(p^.location.reference.symbol) then stringdispose(p^.location.reference.symbol); if p^.disposetyp=dt_string then stringdispose(p^.values); {$ifdef extdebug} if p^.firstpasscount>maxfirstpasscount then maxfirstpasscount:=p^.firstpasscount; dispose(p); {$else extdebug} p^.left:=root; root:=p; {$endif extdebug} end; function getcopy(p : ptree) : ptree; var hp : ptree; begin hp:=getnode; hp^:=p^; if assigned(p^.location.reference.symbol) then hp^.location.reference.symbol:=stringdup(p^.location.reference.symbol^); case p^.disposetyp of dt_leftright : begin if assigned(p^.left) then hp^.left:=getcopy(p^.left); if assigned(p^.right) then hp^.right:=getcopy(p^.right); end; dt_nothing : ; dt_left : if assigned(p^.left) then hp^.left:=getcopy(p^.left); dt_mbleft : if assigned(p^.left) then hp^.left:=getcopy(p^.left); dt_mbleft_and_method : begin if assigned(p^.left) then hp^.left:=getcopy(p^.left); hp^.methodpointer:=getcopy(p^.methodpointer); end; dt_loop : begin if assigned(p^.left) then hp^.left:=getcopy(p^.left); if assigned(p^.right) then hp^.right:=getcopy(p^.right); if assigned(p^.t1) then hp^.t1:=getcopy(p^.t1); if assigned(p^.t2) then hp^.t2:=getcopy(p^.t2); end; dt_string : hp^.values:=stringdup(p^.values^); dt_typeconv : hp^.left:=getcopy(p^.left); dt_inlinen : if assigned(p^.left) then hp^.left:=getcopy(p^.left); else internalerror(11); end; getcopy:=hp; end; procedure deletecaselabels(p : pcaserecord); begin if assigned(p^.greater) then deletecaselabels(p^.greater); if assigned(p^.less) then deletecaselabels(p^.less); dispose(p); end; procedure disposetree(p : ptree); begin if not(assigned(p)) then exit; case p^.disposetyp of dt_leftright : begin if assigned(p^.left) then disposetree(p^.left); if assigned(p^.right) then disposetree(p^.right); end; dt_case : begin if assigned(p^.left) then disposetree(p^.left); if assigned(p^.right) then disposetree(p^.right); if assigned(p^.nodes) then deletecaselabels(p^.nodes); if assigned(p^.elseblock) then disposetree(p^.elseblock); end; dt_nothing : ; dt_left : if assigned(p^.left) then disposetree(p^.left); dt_mbleft : if assigned(p^.left) then disposetree(p^.left); dt_mbleft_and_method : begin if assigned(p^.left) then disposetree(p^.left); disposetree(p^.methodpointer); end; dt_string : stringdispose(p^.values); dt_constset : begin if assigned(p^.constset) then begin dispose(p^.constset); p^.constset:=nil; end; if assigned(p^.left) then disposetree(p^.left); end; dt_typeconv : disposetree(p^.left); dt_inlinen : if assigned(p^.left) then disposetree(p^.left); dt_loop : begin if assigned(p^.left) then disposetree(p^.left); if assigned(p^.right) then disposetree(p^.right); if assigned(p^.t1) then disposetree(p^.t1); if assigned(p^.t2) then disposetree(p^.t2); end; dt_with : begin if assigned(p^.left) then disposetree(p^.left); if assigned(p^.right) then disposetree(p^.right); if assigned(p^.withsymtable) then dispose(p^.withsymtable,done); end; else internalerror(12); end; putnode(p); end; procedure set_file_line(from,_to : ptree); begin if from<>nil then begin _to^.line:=from^.line; _to^.inputfile:=from^.inputfile; end; end; function genwithnode(symtable : psymtable;l,r : ptree;count : longint) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_with; p^.treetype:=withn; p^.left:=l; p^.right:=r; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; p^.withsymtable:=symtable; p^.tablecount:=count; set_file_line(l,p); genwithnode:=p; end; function genfixconstnode(v : longint;def : pdef) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_nothing; p^.treetype:=fixconstn; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=def; p^.value:=v; genfixconstnode:=p; end; function gencallparanode(expr,next : ptree) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_leftright; p^.treetype:=callparan; p^.left:=expr; p^.right:=next; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.registersfpu:=0; p^.resulttype:=nil; p^.exact_match_found:=false; p^.is_colon_para:=false; set_file_line(expr,p); gencallparanode:=p; end; function gennode(t : ttreetyp;l,r : ptree) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_leftright; p^.treetype:=t; p^.left:=l; p^.right:=r; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; gennode:=p; end; function gencasenode(l,r : ptree;nodes : pcaserecord) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_case; p^.treetype:=casen; p^.left:=l; p^.right:=r; p^.nodes:=nodes; p^.registers32:=0; p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; set_file_line(l,p); gencasenode:=p; end; function genloopnode(t : ttreetyp;l,r,n1 : ptree;back : boolean) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_loop; p^.treetype:=t; p^.left:=l; p^.right:=r; p^.t1:=n1; p^.t2:=nil; p^.registers32:=0; p^.backward:=back; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; set_file_line(l,p); genloopnode:=p; end; function genordinalconstnode(v : longint;def : pdef) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_nothing; p^.treetype:=ordconstn; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=def; p^.value:=v; genordinalconstnode:=p; end; function genenumnode(v : penumsym) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_nothing; p^.treetype:=ordconstn; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=v^.definition; p^.value:=v^.value; genenumnode:=p; end; function genrealconstnode(v : bestreal) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_nothing; p^.treetype:=realconstn; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} {$ifdef i386} p^.resulttype:=c64floatdef; p^.valued:=v; { default value is double } p^.realtyp:=ait_real_64bit; {$endif} {$ifdef m68k} p^.resulttype:=new(pfloatdef,init(s32real)); p^.valued:=v; { default value is double } p^.realtyp:=ait_real_32bit; {$endif} p^.labnumber:=-1; genrealconstnode:=p; end; function genstringconstnode(const s : string) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_string; p^.treetype:=stringconstn; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=cstringdef; p^.values:=stringdup(s); p^.labstrnumber:=-1; genstringconstnode:=p; end; function gensinglenode(t : ttreetyp;l : ptree) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_left; p^.treetype:=t; p^.left:=l; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; gensinglenode:=p; end; function genasmnode(p_asm : paasmoutput) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_nothing; p^.treetype:=asmn; p^.registers32:=4; p^.p_asm:=p_asm; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=8; {$ifdef SUPPORT_MMX} p^.registersmmx:=8; {$endif SUPPORT_MMX} p^.resulttype:=nil; genasmnode:=p; end; function genloadnode(v : pvarsym;st : psymtable) : ptree; var p : ptree; begin p:=getnode; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.treetype:=loadn; p^.resulttype:=v^.definition; p^.symtableentry:=v; p^.symtable:=st; p^.is_first := False; p^.disposetyp:=dt_nothing; genloadnode:=p; end; function gentypedconstloadnode(sym : ptypedconstsym;st : psymtable) : ptree; var p : ptree; begin p:=getnode; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.treetype:=loadn; p^.resulttype:=sym^.definition; p^.symtableentry:=pvarsym(sym); p^.symtable:=st; p^.disposetyp:=dt_nothing; gentypedconstloadnode:=p; end; function gentypeconvnode(node : ptree;t : pdef) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_typeconv; p^.treetype:=typeconvn; p^.left:=node; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.convtyp:=tc_equal; p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=t; p^.convtyp:=tc_equal; p^.explizit:=false; set_file_line(node,p); gentypeconvnode:=p; end; function gencallnode(v : pprocsym;st : psymtable) : ptree; var p : ptree; begin p:=getnode; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.treetype:=calln; p^.symtableprocentry:=v; p^.symtableproc:=st; p^.unit_specific:=false; p^.disposetyp := dt_leftright; p^.methodpointer:=nil; p^.left:=nil; p^.right:=nil; p^.procdefinition:=nil; gencallnode:=p; end; function genmethodcallnode(v : pprocsym;st : psymtable;mp : ptree) : ptree; var p : ptree; begin p:=getnode; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.treetype:=calln; p^.symtableprocentry:=v; p^.symtableproc:=st; p^.disposetyp:=dt_mbleft_and_method; p^.left:=nil; p^.right:=nil; p^.methodpointer:=mp; p^.procdefinition:=nil; genmethodcallnode:=p; end; function gensubscriptnode(varsym : pvarsym;l : ptree) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_left; p^.treetype:=subscriptn; p^.left:=l; p^.registers32:=0; p^.vs:=varsym; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; gensubscriptnode:=p; end; function genzeronode(t : ttreetyp) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_nothing; p^.treetype:=t; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; genzeronode:=p; end; function genlabelnode(t : ttreetyp;nr : plabel) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_nothing; p^.treetype:=t; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; { for security } { nr^.is_used:=true;} p^.labelnr:=nr; genlabelnode:=p; end; function genselfnode(_class : pdef) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_nothing; p^.treetype:=selfn; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=_class; genselfnode:=p; end; function geninlinenode(number : longint;l : ptree) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_inlinen; p^.treetype:=inlinen; p^.left:=l; p^.inlinenumber:=number; p^.registers32:=0; { p^.registers16:=0; p^.registers8:=0; } p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=nil; geninlinenode:=p; end; { function genprocinlinenode(code : ptree;proc : pprocsym) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_inlinen; p^.treetype:=inlinen; p^.inlineproc:=proc; p^.left:=code; p^.registers32:=code^.registers32; p^.registersfpu:=code^.registersfpu; $ifdef SUPPORT_MMX p^.registersmmx:=0; $endif SUPPORT_MMX p^.resulttype:=proc^.definition^.returntype; genprocinlinenode:=p; end; } function gensetconstruktnode(s : pconstset;settype : psetdef) : ptree; var p : ptree; begin p:=getnode; p^.disposetyp:=dt_constset; p^.treetype:=setconstrn; p^.registers32:=0; p^.registersfpu:=0; {$ifdef SUPPORT_MMX} p^.registersmmx:=0; {$endif SUPPORT_MMX} p^.resulttype:=settype; p^.left:=nil; new(p^.constset); p^.constset^:=s^; gensetconstruktnode:=p; end; function equal_trees(t1,t2 : ptree) : boolean; begin if t1^.treetype=t2^.treetype then begin case t1^.treetype of addn, muln, equaln, orn, xorn, andn, unequaln: begin equal_trees:=(equal_trees(t1^.left,t2^.left) and equal_trees(t1^.right,t2^.right)) or (equal_trees(t1^.right,t2^.left) and equal_trees(t1^.left,t2^.right)); end; subn, divn, modn, assignn, ltn, lten, gtn, gten, inn, shrn, shln, slashn, rangen: begin equal_trees:=(equal_trees(t1^.left,t2^.left) and equal_trees(t1^.right,t2^.right)); end; umminusn, notn, derefn, addrn: begin equal_trees:=(equal_trees(t1^.left,t2^.left)); end; loadn: begin equal_trees:=(t1^.symtableentry=t2^.symtableentry) { not necessary and (t1^.symtable=t2^.symtable)}; end; { subscriptn, ordconstn,typeconvn,calln,callparan, realconstn,asmn,vecn, stringconstn,funcretn,selfn, inlinen,niln,errorn, typen,hnewn,hdisposen,newn, disposen,setelen,setconstrn } else equal_trees:=false; end; end else equal_trees:=false; end; {This is needed if you want to be able to delete the string with the nodes !!} procedure set_location(var destloc,sourceloc : tlocation); begin if assigned(destloc.reference.symbol) then stringdispose(destloc.reference.symbol); destloc:= sourceloc; if sourceloc.loc in [LOC_MEM,LOC_REFERENCE] then begin if assigned(sourceloc.reference.symbol) then destloc.reference.symbol:= stringdup(sourceloc.reference.symbol^); end else destloc.reference.symbol:=nil; end; procedure swap_location(var destloc,sourceloc : tlocation); var swapl : tlocation; begin swapl := destloc; destloc := sourceloc; sourceloc := swapl; end; end. { $Log$ Revision 1.1 1998-03-25 11:18:13 root Initial revision Revision 1.15 1998/03/24 21:48:36 florian * just a couple of fixes applied: - problem with fixed16 solved - internalerror 10005 problem fixed - patch for assembler reading - small optimizer fix - mem is now supported Revision 1.14 1998/03/10 16:27:46 pierre * better line info in stabs debug * symtabletype and lexlevel separated into two fields of tsymtable + ifdef MAKELIB for direct library output, not complete + ifdef CHAINPROCSYMS for overloaded seach across units, not fully working + ifdef TESTFUNCRET for setting func result in underfunction, not working Revision 1.13 1998/03/10 01:17:30 peter * all files have the same header * messages are fully implemented, EXTDEBUG uses Comment() + AG... files for the Assembler generation Revision 1.12 1998/03/02 01:49:37 peter * renamed target_DOS to target_GO32V1 + new verbose system, merged old errors and verbose units into one new verbose.pas, so errors.pas is obsolete Revision 1.11 1998/02/27 09:26:18 daniel * Changed symtable handling so no junk symtable is put on the symtablestack. Revision 1.10 1998/02/13 10:35:54 daniel * Made Motorola version compilable. * Fixed optimizer Revision 1.9 1998/02/12 11:50:51 daniel Yes! Finally! After three retries, my patch! Changes: Complete rewrite of psub.pas. Added support for DLL's. Compiler requires less memory. Platform units for each platform. Revision 1.8 1998/02/04 14:39:31 florian * small clean up Revision 1.7 1998/01/13 23:11:16 florian + class methods Revision 1.6 1998/01/11 04:16:36 carl + correct floating point support for m68k Revision 1.5 1998/01/07 00:17:11 michael Restored released version (plus fixes) as current Revision 1.3 1997/12/04 12:02:15 pierre + added a counter of max firstpass's for a ptree for debugging only in ifdef extdebug Revision 1.2 1997/11/29 15:43:08 florian * some minor changes Revision 1.1.1.1 1997/11/27 08:33:03 michael FPC Compiler CVS start Pre-CVS log: CEC Carl-Eric Codere FK Florian Klaempfl PM Pierre Muller + feature added - removed * bug fixed or changed History: 19th october 1996: + adapted to version 0.9.0 6th september 1997: + added support for MC68000 (CEC) 3rd october 1997: + added tc_bool_2_u8bit for in_ord_x (PM) 3rd november1997: + added symdifn for sets (PM) 13th november 1997: + added partial code for u32bit support (PM) }