{ $Id$ Copyright (c) 1996-98 by Florian Klaempfl This unit implements the first pass of the code generator 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} {$F+} {$endif tp} unit pass_1; interface uses tree; procedure firstpass(var p : ptree); function do_firstpass(var p : ptree) : boolean; implementation uses globtype,systems, cobjects,verbose,globals, aasm,symtable,types, hcodegen,htypechk, tcadd,tccal,tccnv,tccon,tcflw, tcinl,tcld,tcmat,tcmem,tcset {$ifdef i386} ,i386base,i386asm ,tgeni386 {$endif} {$ifdef m68k} ,m68k,tgen68k {$endif} ; {***************************************************************************** FirstPass *****************************************************************************} type firstpassproc = procedure(var p : ptree); procedure firstnothing(var p : ptree); begin p^.resulttype:=voiddef; end; procedure firsterror(var p : ptree); begin p^.error:=true; codegenerror:=true; p^.resulttype:=generrordef; end; procedure firststatement(var p : ptree); begin { left is the next statement in the list } p^.resulttype:=voiddef; { no temps over several statements } cleartempgen; { right is the statement itself calln assignn or a complex one } firstpass(p^.right); if (not (cs_extsyntax in aktmoduleswitches)) and assigned(p^.right^.resulttype) and (p^.right^.resulttype<>pdef(voiddef)) then CGMessage(cg_e_illegal_expression); if codegenerror then exit; p^.registers32:=p^.right^.registers32; p^.registersfpu:=p^.right^.registersfpu; {$ifdef SUPPORT_MMX} p^.registersmmx:=p^.right^.registersmmx; {$endif SUPPORT_MMX} { left is the next in the list } firstpass(p^.left); if codegenerror then exit; if p^.right^.registers32>p^.registers32 then p^.registers32:=p^.right^.registers32; if p^.right^.registersfpu>p^.registersfpu then p^.registersfpu:=p^.right^.registersfpu; {$ifdef SUPPORT_MMX} if p^.right^.registersmmx>p^.registersmmx then p^.registersmmx:=p^.right^.registersmmx; {$endif} end; procedure firstblock(var p : ptree); var hp : ptree; count : longint; begin count:=0; hp:=p^.left; while assigned(hp) do begin if cs_regalloc in aktglobalswitches then begin { Codeumstellungen } { Funktionsresultate an exit anh„ngen } { this is wrong for string or other complex result types !!! } if ret_in_acc(procinfo.retdef) and assigned(hp^.left) and (hp^.left^.right^.treetype=exitn) and (hp^.right^.treetype=assignn) and (hp^.right^.left^.treetype=funcretn) then begin if assigned(hp^.left^.right^.left) then CGMessage(cg_n_inefficient_code) else begin hp^.left^.right^.left:=getcopy(hp^.right^.right); disposetree(hp^.right); hp^.right:=nil; end; end { warning if unreachable code occurs and elimate this } else if (hp^.right^.treetype in [exitn,breakn,continuen,goton]) and assigned(hp^.left) and (hp^.left^.treetype<>labeln) then begin { use correct line number } aktfilepos:=hp^.left^.fileinfo; disposetree(hp^.left); hp^.left:=nil; CGMessage(cg_w_unreachable_code); { old lines } aktfilepos:=hp^.right^.fileinfo; end; end; if assigned(hp^.right) then begin cleartempgen; firstpass(hp^.right); if (not (cs_extsyntax in aktmoduleswitches)) and assigned(hp^.right^.resulttype) and (hp^.right^.resulttype<>pdef(voiddef)) then CGMessage(cg_e_illegal_expression); if codegenerror then exit; hp^.registers32:=hp^.right^.registers32; hp^.registersfpu:=hp^.right^.registersfpu; {$ifdef SUPPORT_MMX} hp^.registersmmx:=hp^.right^.registersmmx; {$endif SUPPORT_MMX} end else hp^.registers32:=0; if hp^.registers32>p^.registers32 then p^.registers32:=hp^.registers32; if hp^.registersfpu>p^.registersfpu then p^.registersfpu:=hp^.registersfpu; {$ifdef SUPPORT_MMX} if hp^.registersmmx>p^.registersmmx then p^.registersmmx:=hp^.registersmmx; {$endif} inc(count); hp:=hp^.left; end; end; procedure firstasm(var p : ptree); begin procinfo.flags:=procinfo.flags or pi_uses_asm; end; procedure firstpass(var p : ptree); const procedures : array[ttreetyp] of firstpassproc = (firstadd, {addn} firstadd, {muln} firstadd, {subn} firstmoddiv, {divn} firstadd, {symdifn} firstmoddiv, {modn} firstassignment, {assignn} firstload, {loadn} firstrange, {range} firstadd, {ltn} firstadd, {lten} firstadd, {gtn} firstadd, {gten} firstadd, {equaln} firstadd, {unequaln} firstin, {inn} firstadd, {orn} firstadd, {xorn} firstshlshr, {shrn} firstshlshr, {shln} firstadd, {slashn} firstadd, {andn} firstsubscript, {subscriptn} firstderef, {derefn} firstaddr, {addrn} firstdoubleaddr, {doubleaddrn} firstordconst, {ordconstn} firsttypeconv, {typeconvn} firstcalln, {calln} firstnothing, {callparan} firstrealconst, {realconstn} firstfixconst, {fixconstn} firstumminus, {umminusn} firstasm, {asmn} firstvec, {vecn} firststringconst, {stringconstn} firstfuncret, {funcretn} firstself, {selfn} firstnot, {notn} firstinline, {inlinen} firstniln, {niln} firsterror, {errorn} firsttype, {typen} firsthnew, {hnewn} firsthdispose, {hdisposen} firstnew, {newn} firstsimplenewdispose, {simpledisposen} firstsetelement, {setelementn} firstsetconst, {setconstn} firstblock, {blockn} firststatement, {statementn} firstnothing, {loopn} firstif, {ifn} firstnothing, {breakn} firstnothing, {continuen} first_while_repeat, {repeatn} first_while_repeat, {whilen} firstfor, {forn} firstexit, {exitn} firstwith, {withn} firstcase, {casen} firstlabel, {labeln} firstgoto, {goton} firstsimplenewdispose, {simplenewn} firsttryexcept, {tryexceptn} firstraise, {raisen} firstnothing, {switchesn} firsttryfinally, {tryfinallyn} firston, {onn} firstis, {isn} firstas, {asn} firsterror, {caretn} firstnothing, {failn} firstadd, {starstarn} firstprocinline, {procinlinen} firstarrayconstruct, {arrayconstructn} firstarrayconstructrange, {arrayconstructrangen} firstnothing, {nothingn} firstloadvmt {loadvmtn} ); var oldcodegenerror : boolean; oldlocalswitches : tlocalswitches; oldpos : tfileposinfo; {$ifdef extdebug} str1,str2 : string; oldp : ptree; not_first : boolean; {$endif extdebug} begin {$ifdef extdebug} inc(total_of_firstpass); if (p^.firstpasscount>0) and only_one_pass then exit; {$endif extdebug} oldcodegenerror:=codegenerror; oldpos:=aktfilepos; oldlocalswitches:=aktlocalswitches; {$ifdef extdebug} if p^.firstpasscount>0 then begin move(p^,str1[1],sizeof(ttree)); {$ifndef TP} {$ifopt H+} SetLength(str1,sizeof(ttree)); {$else} str1[0]:=char(sizeof(ttree)); {$endif} {$else} str1[0]:=char(sizeof(ttree)); {$endif} new(oldp); oldp^:=p^; not_first:=true; inc(firstpass_several); end else not_first:=false; {$endif extdebug} if not p^.error then begin codegenerror:=false; aktfilepos:=p^.fileinfo; aktlocalswitches:=p^.localswitches; procedures[p^.treetype](p); aktlocalswitches:=oldlocalswitches; aktfilepos:=oldpos; p^.error:=codegenerror; codegenerror:=codegenerror or oldcodegenerror; end else codegenerror:=true; {$ifdef extdebug} if not_first then begin { dirty trick to compare two ttree's (PM) } move(p^,str2[1],sizeof(ttree)); {$ifndef TP} {$ifopt H+} SetLength(str2,sizeof(ttree)); {$else} str2[0]:=char(sizeof(ttree)); {$endif} {$else} str2[0]:=char(sizeof(ttree)); {$endif} if str1<>str2 then begin comment(v_debug,'tree changed after first counting pass ' +tostr(longint(p^.treetype))); compare_trees(oldp,p); end; dispose(oldp); end; if count_ref then inc(p^.firstpasscount); {$endif extdebug} end; function do_firstpass(var p : ptree) : boolean; begin codegenerror:=false; firstpass(p); do_firstpass:=codegenerror; end; end. { $Log$ Revision 1.102 1999-05-27 19:44:42 peter * removed oldasm * plabel -> pasmlabel * -a switches to source writing automaticly * assembler readers OOPed * asmsymbol automaticly external * jumptables and other label fixes for asm readers Revision 1.101 1999/05/01 13:24:26 peter * merged nasm compiler * old asm moved to oldasm/ Revision 1.100 1999/02/22 02:44:07 peter * ag386bin doesn't use i386.pas anymore Revision 1.99 1998/12/11 00:03:27 peter + globtype,tokens,version unit splitted from globals Revision 1.98 1998/11/23 17:49:03 pierre * ansistring support in extdebug code Revision 1.97 1998/11/05 14:26:47 peter * fixed variant warning with was sometimes said with sets Revision 1.96 1998/10/06 20:49:07 peter * m68k compiler compiles again Revision 1.95 1998/09/24 15:13:44 peter * fixed type node which was always set to void :( Revision 1.94 1998/09/23 20:42:22 peter * splitted pass_1 }