{ $Id$ 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 node,aasmbase,aasmtai,aasmcpu,cpubase, symbase,symdef,symsym; type tloopnode = class(tbinarynode) t1,t2 : tnode; constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual; destructor destroy;override; function getcopy : tnode;override; procedure insertintolist(l : tnodelist);override; {$ifdef extdebug} procedure dowrite;override; {$endif extdebug} function docompare(p: tnode): boolean; override; end; twhilerepeatnode = class(tloopnode) testatbegin,checknegate:boolean; constructor create(l,r,_t1:Tnode;tab,cn:boolean);virtual; function det_resulttype: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; function det_resulttype:tnode;override; function pass_1 : tnode;override; end; tifnodeclass = class of tifnode; tfornode = class(tloopnode) testatbegin:boolean; constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual; function det_resulttype:tnode;override; function pass_1 : tnode;override; end; tfornodeclass = class of tfornode; texitnode = class(tunarynode) constructor create(l:tnode);virtual; function det_resulttype:tnode;override; function pass_1 : tnode;override; end; texitnodeclass = class of texitnode; tbreaknode = class(tnode) constructor create;virtual; function det_resulttype:tnode;override; function pass_1 : tnode;override; end; tbreaknodeclass = class of tbreaknode; tcontinuenode = class(tnode) constructor create;virtual; function det_resulttype:tnode;override; function pass_1 : tnode;override; end; tcontinuenodeclass = class of tcontinuenode; tgotonode = class(tnode) labelnr : tasmlabel; labsym : tlabelsym; exceptionblock : integer; constructor create(p : tlabelsym);virtual; function getcopy : tnode;override; function det_resulttype:tnode;override; function pass_1 : tnode;override; function docompare(p: tnode): boolean; override; end; tgotonodeclass = class of tgotonode; tlabelnode = class(tunarynode) labelnr : tasmlabel; labsym : tlabelsym; exceptionblock : integer; constructor createcase(p : tasmlabel;l:tnode);virtual; constructor create(p : tlabelsym;l:tnode);virtual; function getcopy : tnode;override; function det_resulttype:tnode;override; function pass_1 : tnode;override; function docompare(p: tnode): boolean; override; end; tlabelnodeclass = class of tlabelnode; traisenode = class(tbinarynode) frametree : tnode; constructor create(l,taddr,tframe:tnode);virtual; function getcopy : tnode;override; procedure insertintolist(l : tnodelist);override; function det_resulttype:tnode;override; function pass_1 : tnode;override; function docompare(p: tnode): boolean; override; end; traisenodeclass = class of traisenode; ttryexceptnode = class(tloopnode) constructor create(l,r,_t1 : tnode);virtual; function det_resulttype:tnode;override; function pass_1 : tnode;override; end; ttryexceptnodeclass = class of ttryexceptnode; ttryfinallynode = class(tbinarynode) constructor create(l,r:tnode);virtual; function det_resulttype: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; function det_resulttype:tnode;override; function pass_1 : tnode;override; function getcopy : tnode;override; function docompare(p: tnode): boolean; override; end; tonnodeclass = class of tonnode; tfailnode = class(tnode) constructor create;virtual; function det_resulttype:tnode;override; function pass_1: tnode;override; function docompare(p: tnode): boolean; override; end; tfailnodeclass = class of tfailnode; { for compatibilty } function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode; 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; cfailnode : tfailnodeclass; implementation uses globtype,systems, cutils,verbose,globals, symconst,symtable,paramgr,defbase,htypechk,pass_1, ncon,nmem,nld,ncnv,nbas,rgobj, {$ifdef state_tracking} nstate, {$endif} cgbase ; function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode; var p : tnode; begin case t of ifn: p:=cifnode.create(l,r,n1); whilerepeatn: if back then {Repeat until.} p:=cwhilerepeatnode.create(l,r,n1,false,true) else {While do.} p:=cwhilerepeatnode.create(l,r,n1,true,false); forn: p:=cfornode.create(l,r,n1,nil,back); end; genloopnode:=p; end; {**************************************************************************** TLOOPNODE *****************************************************************************} constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode); begin inherited create(tt,l,r); t1:=_t1; t2:=_t2; set_file_line(l); end; destructor tloopnode.destroy; begin t1.free; t2.free; inherited destroy; end; function tloopnode.getcopy : tnode; var p : tloopnode; begin p:=tloopnode(inherited getcopy); if assigned(t1) then p.t1:=t1.getcopy else p.t1:=nil; if assigned(t2) then p.t2:=t2.getcopy else p.t2:=nil; getcopy:=p; end; procedure tloopnode.insertintolist(l : tnodelist); begin end; {$ifdef extdebug} procedure tloopnode.dowrite; begin inherited dowrite; writenodeindention:=writenodeindention+' '; writenode(t1); writenode(t2); delete(writenodeindention,1,4); end; {$endif extdebug} function tloopnode.docompare(p: tnode): boolean; begin docompare := inherited docompare(p) and t1.isequal(tloopnode(p).t1) and t2.isequal(tloopnode(p).t2); end; {**************************************************************************** TWHILEREPEATNODE *****************************************************************************} constructor Twhilerepeatnode.create(l,r,_t1:Tnode;tab,cn:boolean); begin inherited create(whilerepeatn,l,r,_t1,nil); testatbegin:=tab; checknegate:=cn; end; function twhilerepeatnode.det_resulttype:tnode; var t:Tunarynode; begin result:=nil; resulttype:=voidtype; resulttypepass(left); {A not node can be removed.} if left.nodetype=notn then begin t:=Tunarynode(left); left:=Tunarynode(left).left; t.left:=nil; t.destroy; checknegate:=not checknegate; end; { loop instruction } if assigned(right) then resulttypepass(right); set_varstate(left,true); if codegenerror then exit; if not is_boolean(left.resulttype.def) then begin CGMessage(type_e_mismatch); exit; end; end; function twhilerepeatnode.pass_1 : tnode; var old_t_times : longint; begin result:=nil; old_t_times:=rg.t_times; { calc register weight } if not(cs_littlesize in aktglobalswitches ) then rg.t_times:=rg.t_times*8; rg.cleartempgen; firstpass(left); if codegenerror then exit; registers32:=left.registers32; registersfpu:=left.registersfpu; {$ifdef SUPPORT_MMX} registersmmx:=left.registersmmx; {$endif SUPPORT_MMX} { loop instruction } if assigned(right) then begin rg.cleartempgen; firstpass(right); if codegenerror then exit; if registers32nil then begin condition.destroy; condition:=factval.getcopy; change:=true; end; if change then begin track_state_pass:=true; {Force new resulttype pass.} condition.resulttype.def:=nil; do_resulttypepass(condition); end; if is_constboolnode(condition) then begin {Try to turn a while loop into a repeat loop.} if firsttest then begin testatbegin:=false; writeln('while->repeat'); end; 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 resulttype pass.} condition.resulttype.def:=nil; do_resulttypepass(condition); end; if not is_constboolnode(condition) then aktstate.store_fact(condition, cordconstnode.create(byte(checknegate),booltype)) else condition.destroy; end; {$endif} {***************************************************************************** TIFNODE *****************************************************************************} constructor tifnode.create(l,r,_t1 : tnode); begin inherited create(ifn,l,r,_t1,nil); end; function tifnode.det_resulttype:tnode; begin result:=nil; resulttype:=voidtype; resulttypepass(left); { if path } if assigned(right) then resulttypepass(right); { else path } if assigned(t1) then resulttypepass(t1); set_varstate(left,true); if codegenerror then exit; if not is_boolean(left.resulttype.def) then Message1(type_e_boolean_expr_expected,left.resulttype.def.typename); end; function tifnode.pass_1 : tnode; var old_t_times : longint; hp : tnode; begin result:=nil; old_t_times:=rg.t_times; rg.cleartempgen; firstpass(left); registers32:=left.registers32; registersfpu:=left.registersfpu; {$ifdef SUPPORT_MMX} registersmmx:=left.registersmmx; {$endif SUPPORT_MMX} { determines registers weigths } if not(cs_littlesize in aktglobalswitches) then rg.t_times:=rg.t_times div 2; if rg.t_times=0 then rg.t_times:=1; { if path } if assigned(right) then begin rg.cleartempgen; firstpass(right); if registers32assignn then begin CGMessage(cg_e_illegal_expression); exit; end; {Can we spare the first comparision?} if right.nodetype=ordconstn then if Tassignmentnode(left).right.nodetype=ordconstn then testatbegin:=not(((nf_backward in flags) and (Tordconstnode(Tassignmentnode(left).right).value>=Tordconstnode(right).value)) or (not(nf_backward in flags) and (Tordconstnode(Tassignmentnode(left).right).value<=Tordconstnode(right).value))); { save counter var } t2:=tassignmentnode(left).left.getcopy; resulttypepass(left); set_varstate(left,false); if assigned(t1) then begin resulttypepass(t1); if codegenerror then exit; end; { process count var } resulttypepass(t2); set_varstate(t2,true); if codegenerror then exit; { Check count var, record fields are also allowed in tp7 } hp:=t2; while (hp.nodetype=subscriptn) or ((hp.nodetype=vecn) and is_constintnode(tvecnode(hp).right)) do hp:=tunarynode(hp).left; { we need a simple loadn, but the load must be in a global symtable or in the same lexlevel } if (hp.nodetype=funcretn) or ((hp.nodetype=loadn) and ((tloadnode(hp).symtable.symtablelevel<=1) or (tloadnode(hp).symtable.symtablelevel=lexlevel))) then begin if (hp.nodetype=loadn) and (tloadnode(hp).symtableentry.typ=varsym) then tvarsym(tloadnode(hp).symtableentry).varstate:=vs_used; if (not(is_ordinal(t2.resulttype.def)) or is_64bitint(t2.resulttype.def)) then CGMessagePos(hp.fileinfo,type_e_ordinal_expr_expected); end else CGMessagePos(hp.fileinfo,cg_e_illegal_count_var); resulttypepass(right); set_varstate(right,true); inserttypeconv(right,t2.resulttype); end; function tfornode.pass_1 : tnode; var old_t_times : longint; begin result:=nil; { Calc register weight } old_t_times:=rg.t_times; if not(cs_littlesize in aktglobalswitches) then rg.t_times:=rg.t_times*8; rg.cleartempgen; firstpass(left); rg.cleartempgen; if assigned(t1) then begin firstpass(t1); if codegenerror then exit; end; registers32:=t1.registers32; registersfpu:=t1.registersfpu; {$ifdef SUPPORT_MMX} registersmmx:=left.registersmmx; {$endif SUPPORT_MMX} if left.registers32>registers32 then registers32:=left.registers32; if left.registersfpu>registersfpu then registersfpu:=left.registersfpu; {$ifdef SUPPORT_MMX} if left.registersmmx>registersmmx then registersmmx:=left.registersmmx; {$endif SUPPORT_MMX} { process count var } rg.cleartempgen; firstpass(t2); if codegenerror then exit; if t2.registers32>registers32 then registers32:=t2.registers32; if t2.registersfpu>registersfpu then registersfpu:=t2.registersfpu; {$ifdef SUPPORT_MMX} if t2.registersmmx>registersmmx then registersmmx:=t2.registersmmx; {$endif SUPPORT_MMX} rg.cleartempgen; firstpass(right); if right.registers32>registers32 then registers32:=right.registers32; if right.registersfpu>registersfpu then registersfpu:=right.registersfpu; {$ifdef SUPPORT_MMX} if right.registersmmx>registersmmx then registersmmx:=right.registersmmx; {$endif SUPPORT_MMX} { we need at least one register for comparisons PM } if registers32=0 then inc(registers32); rg.t_times:=old_t_times; end; {***************************************************************************** TEXITNODE *****************************************************************************} constructor texitnode.create(l:tnode); begin inherited create(exitn,l); end; function texitnode.det_resulttype:tnode; var pt : tnode; begin result:=nil; { Check the 2 types } if not inlining_procedure then begin if assigned(left) then begin inserttypeconv(left,aktprocdef.rettype); if paramanager.ret_in_param(aktprocdef.rettype.def) or (procinfo^.no_fast_exit) or ((procinfo^.flags and pi_uses_exceptions)<>0) then begin pt:=cfuncretnode.create(aktprocdef.funcretsym); left:=cassignmentnode.create(pt,left); end; end; end; if assigned(left) then begin resulttypepass(left); set_varstate(left,true); end; resulttype:=voidtype; end; function texitnode.pass_1 : tnode; begin result:=nil; if assigned(left) then begin firstpass(left); if codegenerror then exit; registers32:=left.registers32; 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.det_resulttype:tnode; begin result:=nil; resulttype:=voidtype; end; function tbreaknode.pass_1 : tnode; begin result:=nil; end; {***************************************************************************** TCONTINUENODE *****************************************************************************} constructor tcontinuenode.create; begin inherited create(continuen); end; function tcontinuenode.det_resulttype:tnode; begin result:=nil; resulttype:=voidtype; end; function tcontinuenode.pass_1 : tnode; begin result:=nil; end; {***************************************************************************** TGOTONODE *****************************************************************************} constructor tgotonode.create(p : tlabelsym); begin inherited create(goton); exceptionblock:=aktexceptblock; labsym:=p; labelnr:=p.lab; end; function tgotonode.det_resulttype:tnode; begin result:=nil; resulttype:=voidtype; end; function tgotonode.pass_1 : tnode; begin result:=nil; { check if } if assigned(labsym) and assigned(labsym.code) and (exceptionblock<>tlabelnode(labsym.code).exceptionblock) then begin writeln('goto exceptblock: ',exceptionblock); writeln('label exceptblock: ',tlabelnode(labsym.code).exceptionblock); CGMessage(cg_e_goto_inout_of_exception_block); end; end; function tgotonode.getcopy : tnode; var p : tgotonode; begin p:=tgotonode(inherited getcopy); p.labelnr:=labelnr; p.labsym:=labsym; p.exceptionblock:=exceptionblock; result:=p; end; function tgotonode.docompare(p: tnode): boolean; begin docompare := false; end; {***************************************************************************** TLABELNODE *****************************************************************************} constructor tlabelnode.createcase(p : tasmlabel;l:tnode); begin inherited create(labeln,l); { it shouldn't be possible to jump to case labels using goto } exceptionblock:=-1; labsym:=nil; labelnr:=p; end; constructor tlabelnode.create(p : tlabelsym;l:tnode); begin inherited create(labeln,l); exceptionblock:=aktexceptblock; labsym:=p; labelnr:=p.lab; { save the current labelnode in the labelsym } p.code:=self; end; function tlabelnode.det_resulttype:tnode; begin result:=nil; { left could still be unassigned } if assigned(left) then resulttypepass(left); resulttype:=voidtype; end; function tlabelnode.pass_1 : tnode; begin result:=nil; if assigned(left) then begin rg.cleartempgen; firstpass(left); registers32:=left.registers32; registersfpu:=left.registersfpu; {$ifdef SUPPORT_MMX} registersmmx:=left.registersmmx; {$endif SUPPORT_MMX} end; end; function tlabelnode.getcopy : tnode; var p : tlabelnode; begin p:=tlabelnode(inherited getcopy); p.labelnr:=labelnr; p.exceptionblock:=exceptionblock; p.labsym:=labsym; result:=p; 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); frametree:=tframe; end; function traisenode.getcopy : tnode; var n : traisenode; begin n:=traisenode(inherited getcopy); if assigned(frametree) then n.frametree:=frametree.getcopy else n.frametree:=nil; getcopy:=n; end; procedure traisenode.insertintolist(l : tnodelist); begin end; function traisenode.det_resulttype:tnode; begin result:=nil; resulttype:=voidtype; if assigned(left) then begin { first para must be a _class_ } resulttypepass(left); set_varstate(left,true); if codegenerror then exit; if not(is_class(left.resulttype.def)) then CGMessage(type_e_mismatch); { insert needed typeconvs for addr,frame } if assigned(right) then begin { addr } resulttypepass(right); inserttypeconv(right,voidpointertype); { frame } if assigned(frametree) then begin resulttypepass(frametree); inserttypeconv(frametree,voidpointertype); end; end; end; end; function traisenode.pass_1 : tnode; begin result:=nil; 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; function traisenode.docompare(p: tnode): boolean; begin docompare := false; end; {***************************************************************************** TTRYEXCEPTNODE *****************************************************************************} constructor ttryexceptnode.create(l,r,_t1 : tnode); begin inherited create(tryexceptn,l,r,_t1,nil); end; function ttryexceptnode.det_resulttype:tnode; begin result:=nil; resulttypepass(left); { on statements } if assigned(right) then resulttypepass(right); { else block } if assigned(t1) then resulttypepass(t1); resulttype:=voidtype; end; function ttryexceptnode.pass_1 : tnode; begin result:=nil; rg.cleartempgen; firstpass(left); { on statements } if assigned(right) then begin rg.cleartempgen; firstpass(right); registers32:=max(registers32,right.registers32); 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); registers32:=max(registers32,t1.registers32); 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); end; function ttryfinallynode.det_resulttype:tnode; begin result:=nil; resulttype:=voidtype; resulttypepass(left); set_varstate(left,true); resulttypepass(right); set_varstate(right,true); end; function ttryfinallynode.pass_1 : tnode; begin result:=nil; rg.cleartempgen; firstpass(left); rg.cleartempgen; firstpass(right); left_right_max; end; {***************************************************************************** TONNODE *****************************************************************************} constructor tonnode.create(l,r:tnode); begin inherited create(onn,l,r); exceptsymtable:=nil; excepttype:=nil; end; destructor tonnode.destroy; begin if assigned(exceptsymtable) then exceptsymtable.free; inherited destroy; end; function tonnode.getcopy : tnode; var n : tonnode; begin n:=tonnode(inherited getcopy); n.exceptsymtable:=exceptsymtable; n.excepttype:=excepttype; result:=n; end; function tonnode.det_resulttype:tnode; begin result:=nil; resulttype:=voidtype; if not(is_class(excepttype)) then CGMessage(type_e_mismatch); if assigned(left) then resulttypepass(left); if assigned(right) then resulttypepass(right); end; function tonnode.pass_1 : tnode; begin result:=nil; rg.cleartempgen; registers32:=0; registersfpu:=0; {$ifdef SUPPORT_MMX} registersmmx:=0; {$endif SUPPORT_MMX} if assigned(left) then begin firstpass(left); registers32:=left.registers32; registersfpu:=left.registersfpu; {$ifdef SUPPORT_MMX} registersmmx:=left.registersmmx; {$endif SUPPORT_MMX} end; rg.cleartempgen; if assigned(right) then begin firstpass(right); registers32:=max(registers32,right.registers32); 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; {***************************************************************************** TFAILNODE *****************************************************************************} constructor tfailnode.create; begin inherited create(failn); end; function tfailnode.det_resulttype:tnode; begin result:=nil; resulttype:=voidtype; end; function tfailnode.pass_1 : tnode; begin result:=nil; end; function tfailnode.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; cfailnode:=tfailnode; end. { $Log$ Revision 1.43 2002-07-20 11:57:54 florian * types.pas renamed to defbase.pas because D6 contains a types unit so this would conflicts if D6 programms are compiled + Willamette/SSE2 instructions to assembler added Revision 1.42 2002/07/20 11:18:18 daniel * Small mistake fixed; the skip test was done before we know the for node is correct. Revision 1.40 2002/07/20 08:19:31 daniel * State tracker automatically changes while loops into repeat loops Revision 1.39 2002/07/19 12:55:27 daniel * Further developed state tracking in whilerepeatn Revision 1.38 2002/07/19 11:41:35 daniel * State tracker work * The whilen and repeatn are now completely unified into whilerepeatn. This allows the state tracker to change while nodes automatically into repeat nodes. * Resulttypepass improvements to the notn. 'not not a' is optimized away and 'not(a>b)' is optimized into 'a<=b'. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized by removing the notn and later switchting the true and falselabels. The same is done with 'repeat until not a'. Revision 1.37 2002/07/16 13:57:02 florian * raise takes now a void pointer as at and frame address instead of a longint Revision 1.36 2002/07/15 18:03:15 florian * readded removed changes Revision 1.35 2002/07/14 18:00:44 daniel + Added the beginning of a state tracker. This will track the values of variables through procedures and optimize things away. Revision 1.34 2002/07/11 14:41:28 florian * start of the new generic parameter handling Revision 1.33 2002/07/01 18:46:23 peter * internal linker * reorganized aasm layer Revision 1.32 2002/05/18 13:34:10 peter * readded missing revisions Revision 1.31 2002/05/16 19:46:38 carl + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand + try to fix temp allocation (still in ifdef) + generic constructor calls + start of tassembler / tmodulebase class cleanup Revision 1.29 2002/05/12 16:53:07 peter * moved entry and exitcode to ncgutil and cgobj * foreach gets extra argument for passing local data to the iterator function * -CR checks also class typecasts at runtime by changing them into as * fixed compiler to cycle with the -CR option * fixed stabs with elf writer, finally the global variables can be watched * removed a lot of routines from cga unit and replaced them by calls to cgobj * u32bit-s32bit updates for and,or,xor nodes. When one element is u32bit then the other is typecasted also to u32bit without giving a rangecheck warning/error. * fixed pascal calling method with reversing also the high tree in the parast, detected by tcalcst3 test Revision 1.28 2002/03/31 20:26:34 jonas + a_loadfpu_* and a_loadmm_* methods in tcg * register allocation is now handled by a class and is mostly processor independent (+rgobj.pas and i386/rgcpu.pas) * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas) * some small improvements and fixes to the optimizer * some register allocation fixes * some fpuvaroffset fixes in the unary minus node * push/popusedregisters is now called rg.save/restoreusedregisters and (for i386) uses temps instead of push/pop's when using -Op3 (that code is also better optimizable) * fixed and optimized register saving/restoring for new/dispose nodes * LOC_FPU locations now also require their "register" field to be set to R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only) - list field removed of the tnode class because it's not used currently and can cause hard-to-find bugs }