123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- {
- $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
- }
|