123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766 |
- {$ifndef cg11}
- {
- $Id$
- Copyright (c) 1998-2000 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.
- ****************************************************************************
- }
- unit pass_1;
- {$i defines.inc}
- interface
- uses
- tree;
- procedure firstpass(var p : ptree);
- function do_firstpass(var p : ptree) : boolean;
- implementation
- uses
- globtype,systems,
- cutils,cobjects,verbose,globals,
- aasm,symtable,types,
- htypechk,
- tcadd,tccal,tccnv,tccon,tcflw,
- tcinl,tcld,tcmat,tcmem,tcset,cpubase,cpuasm
- {$ifdef newcg}
- ,cgbase
- ,tgcpu
- {$else newcg}
- ,hcodegen
- {$ifdef i386}
- ,tgeni386
- {$endif}
- {$ifdef m68k}
- ,tgen68k
- {$endif}
- {$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 }
- {$ifdef newcg}
- tg.cleartempgen;
- {$else newcg}
- cleartempgen;
- {$endif newcg}
- { right is the statement itself calln assignn or a complex one }
- {must_be_valid:=true; obsolete PM }
- 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^.returntype.def) and
- assigned(hp^.left) and
- assigned(hp^.left^.right) 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:=hp^.right^.right;
- hp^.right^.right:=nil;
- 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
- { statement node (JM) }
- assigned(hp^.left) and
- { kind of statement! (JM) }
- assigned(hp^.left^.right) and
- (hp^.left^.right^.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
- {$ifdef newcg}
- tg.cleartempgen;
- {$else newcg}
- cleartempgen;
- {$endif newcg}
- codegenerror:=false;
- 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}
- firstunaryminus, {unaryminusn}
- firstasm, {asmn}
- firstvec, {vecn}
- firstpointerconst,{pointerconstn}
- 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));
- str1[0]:=char(sizeof(ttree));
- 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));
- str2[0]:=char(sizeof(ttree));
- 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
- aktexceptblock:=nil;
- codegenerror:=false;
- firstpass(p);
- do_firstpass:=codegenerror;
- end;
- end.
- {$else tnode}
- unit pass_1;
- {$i defines.inc}
- interface
- uses
- node;
- procedure firstpass(var p : tnode);
- function do_firstpass(var p : tnode) : boolean;
- type
- tnothingnode = class(tnode)
- constructor create;virtual;
- function pass_1 : tnode;override;
- end;
- terrornode = class(tnode)
- constructor create;virtual;
- function pass_1 : tnode;override;
- end;
- tasmnode = class(tnode)
- constructor create;virtual;
- function pass_1 : tnode;override;
- end;
- tstatementnode = class(tbinarynode)
- constructor create(l,r : tnode);virtual;
- function pass_1 : tnode;override;
- end;
- tblocknode = class(tbinarynode)
- constructor create(l,r : tnode);virtual;
- function pass_1 : tnode;override;
- end;
- var
- cnothingnode : class of tnothingnode;
- cerrornode : class of terrornode;
- casmnode : class of tasmnode;
- cstatementnode : class of tstatementnode;
- cblocknode : class of tblocknode;
- implementation
- uses
- globtype,systems,
- cutils,cobjects,verbose,globals,
- aasm,symtable,types,
- htypechk,
- cpubase,cpuasm,
- nflw
- {$ifdef newcg}
- ,cgbase
- ,tgcpu
- {$else newcg}
- ,hcodegen
- {$ifdef i386}
- ,tgeni386
- {$endif}
- {$ifdef m68k}
- ,tgen68k
- {$endif}
- {$endif}
- ;
- {*****************************************************************************
- TFIRSTNOTHING
- *****************************************************************************}
- constructor tnothingnode.create;
- begin
- inherited create(nothingn);
- end;
- function tnothingnode.pass_1 : tnode;
- begin
- pass_1:=nil;
- resulttype:=voiddef;
- end;
- {*****************************************************************************
- TFIRSTERROR
- *****************************************************************************}
- constructor terrornode.create;
- begin
- inherited create(errorn);
- end;
- function terrornode.pass_1 : tnode;
- begin
- pass_1:=nil;
- include(flags,nf_error);
- codegenerror:=true;
- resulttype:=generrordef;
- end;
- {*****************************************************************************
- TSTATEMENTNODE
- *****************************************************************************}
- constructor tstatementnode.create(l,r : tnode);
- begin
- inherited create(statementn,l,r);
- end;
- function tstatementnode.pass_1 : tnode;
- begin
- pass_1:=nil;
- { left is the next statement in the list }
- resulttype:=voiddef;
- { no temps over several statements }
- {$ifdef newcg}
- tg.cleartempgen;
- {$else newcg}
- cleartempgen;
- {$endif newcg}
- { right is the statement itself calln assignn or a complex one }
- {must_be_valid:=true; obsolete PM }
- firstpass(right);
- if (not (cs_extsyntax in aktmoduleswitches)) and
- assigned(right.resulttype) and
- (right.resulttype<>pdef(voiddef)) then
- CGMessage(cg_e_illegal_expression);
- if codegenerror then
- exit;
- registers32:=right.registers32;
- registersfpu:=right.registersfpu;
- {$ifdef SUPPORT_MMX}
- registersmmx:=right.registersmmx;
- {$endif SUPPORT_MMX}
- { left is the next in the list }
- firstpass(left);
- if codegenerror then
- exit;
- 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}
- end;
- {*****************************************************************************
- TBLOCKNODE
- *****************************************************************************}
- constructor tblocknode.create(l,r : tnode);
- begin
- inherited create(blockn,l,r);
- end;
- function tblocknode.pass_1 : tnode;
- var
- hp : tstatementnode;
- count : longint;
- begin
- pass_1:=nil;
- count:=0;
- hp:=tstatementnode(left);
- while assigned(hp) do
- begin
- if cs_regalloc in aktglobalswitches then
- begin
- { node transformations }
- { concat function result to exit }
- { this is wrong for string or other complex
- result types !!! }
- if ret_in_acc(procinfo^.returntype.def) and
- assigned(hp.left) and
- assigned(tstatementnode(hp.left).right) and
- (tstatementnode(hp.left).right.nodetype=exitn) and
- (hp.right.nodetype=assignn) and
- { !!!! this tbinarynode should be tassignmentnode }
- (tbinarynode(hp.right).left.nodetype=funcretn) then
- begin
- if assigned(texitnode(tstatementnode(hp.left).right).left) then
- CGMessage(cg_n_inefficient_code)
- else
- begin
- texitnode(tstatementnode(hp.left).right).left:=tstatementnode(hp.right).right;
- tstatementnode(hp.right).right:=nil;
- hp.right.free;
- hp.right:=nil;
- end;
- end
- { warning if unreachable code occurs and elimate this }
- else if (hp.right.nodetype in
- [exitn,breakn,continuen,goton]) and
- { statement node (JM) }
- assigned(hp.left) and
- { kind of statement! (JM) }
- assigned(tstatementnode(hp.left).right) and
- (tstatementnode(hp.left).right.nodetype<>labeln) then
- begin
- { use correct line number }
- aktfilepos:=hp.left.fileinfo;
- hp.left.free;
- hp.left:=nil;
- CGMessage(cg_w_unreachable_code);
- { old lines }
- aktfilepos:=hp.right.fileinfo;
- end;
- end;
- if assigned(hp.right) then
- begin
- {$ifdef newcg}
- tg.cleartempgen;
- {$else newcg}
- cleartempgen;
- {$endif newcg}
- codegenerror:=false;
- 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>registers32 then
- registers32:=hp.registers32;
- if hp.registersfpu>registersfpu then
- registersfpu:=hp.registersfpu;
- {$ifdef SUPPORT_MMX}
- if hp.registersmmx>registersmmx then
- registersmmx:=hp.registersmmx;
- {$endif}
- inc(count);
- hp:=tstatementnode(hp.left);
- end;
- end;
- {*****************************************************************************
- TASMNODE
- *****************************************************************************}
- constructor tasmnode.create;
- begin
- inherited create(asmn);
- end;
- function tasmnode.pass_1 : tnode;
- begin
- pass_1:=nil;
- procinfo^.flags:=procinfo^.flags or pi_uses_asm;
- end;
- {*****************************************************************************
- Global procedures
- *****************************************************************************}
- procedure firstpass(var p : tnode);
- var
- oldcodegenerror : boolean;
- oldlocalswitches : tlocalswitches;
- oldpos : tfileposinfo;
- hp : tnode;
- {$ifdef extdebug}
- str1,str2 : string;
- oldp : tnode;
- 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));
- str1[0]:=char(sizeof(ttree));
- new(oldp);
- oldp^:=p^;
- not_first:=true;
- inc(firstpass_several);
- end
- else
- not_first:=false;
- {$endif extdebug}
- if not(nf_error in p.flags) then
- begin
- codegenerror:=false;
- aktfilepos:=p.fileinfo;
- aktlocalswitches:=p.localswitches;
- hp:=p.pass_1;
- { should the node be replaced? }
- if assigned(hp) then
- begin
- p.free;
- p:=hp;
- end;
- aktlocalswitches:=oldlocalswitches;
- aktfilepos:=oldpos;
- if codegenerror then
- include(p.flags,nf_error);
- 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));
- str2[0]:=char(sizeof(ttree));
- 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 : tnode) : boolean;
- begin
- aktexceptblock:=nil;
- codegenerror:=false;
- firstpass(p);
- do_firstpass:=codegenerror;
- end;
- begin
- cnothingnode:=tnothingnode;
- cerrornode:=terrornode;
- casmnode:=tasmnode;
- cstatementnode:=tstatementnode;
- cblocknode:=tblocknode;
- end.
- {$endif cg11}
- {
- $Log$
- Revision 1.8 2000-10-01 19:48:25 peter
- * lot of compile updates for cg11
- Revision 1.7 2000/09/30 16:08:45 peter
- * more cg11 updates
- Revision 1.6 2000/09/28 19:49:52 florian
- *** empty log message ***
- Revision 1.5 2000/09/24 21:15:34 florian
- * some errors fix to get more stuff compilable
- Revision 1.4 2000/09/24 15:06:21 peter
- * use defines.inc
- Revision 1.3 2000/09/19 23:09:07 pierre
- * problems wih extdebug cond. solved
- Revision 1.2 2000/07/13 11:32:44 michael
- + removed logs
- }
|