2
0

nflw.pas 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Type checking and register allocation for nodes that influence
  4. the flow
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit nflw;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cclasses,
  23. node,cpubase,
  24. symnot,
  25. symtype,symbase,symdef,symsym,
  26. optunrol;
  27. type
  28. { flags used by loop nodes }
  29. tloopflag = (
  30. { set if it is a for ... downto ... do loop }
  31. lnf_backward,
  32. { Do we need to parse childs to set var state? }
  33. lnf_varstate,
  34. { Do a test at the begin of the loop?}
  35. lnf_testatbegin,
  36. { Negate the loop test? }
  37. lnf_checknegate,
  38. { Should the value of the loop variable on exit be correct. }
  39. lnf_dont_mind_loopvar_on_exit);
  40. tloopflags = set of tloopflag;
  41. const
  42. { loop flags which must match to consider loop nodes equal regarding the flags }
  43. loopflagsequal = [lnf_backward];
  44. type
  45. tlabelnode = class;
  46. tloopnode = class(tbinarynode)
  47. t1,t2 : tnode;
  48. loopflags : tloopflags;
  49. constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual;
  50. destructor destroy;override;
  51. function dogetcopy : tnode;override;
  52. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  53. procedure ppuwrite(ppufile:tcompilerppufile);override;
  54. procedure buildderefimpl;override;
  55. procedure derefimpl;override;
  56. procedure insertintolist(l : tnodelist);override;
  57. procedure printnodetree(var t:text);override;
  58. function docompare(p: tnode): boolean; override;
  59. end;
  60. twhilerepeatnode = class(tloopnode)
  61. constructor create(l,r:Tnode;tab,cn:boolean);virtual;reintroduce;
  62. function pass_typecheck:tnode;override;
  63. function pass_1 : tnode;override;
  64. {$ifdef state_tracking}
  65. function track_state_pass(exec_known:boolean):boolean;override;
  66. {$endif}
  67. end;
  68. twhilerepeatnodeclass = class of twhilerepeatnode;
  69. tifnode = class(tloopnode)
  70. constructor create(l,r,_t1 : tnode);virtual;reintroduce;
  71. function pass_typecheck:tnode;override;
  72. function pass_1 : tnode;override;
  73. function simplify : tnode;override;
  74. private
  75. function internalsimplify(warn: boolean) : tnode;
  76. end;
  77. tifnodeclass = class of tifnode;
  78. tfornode = class(tloopnode)
  79. { if count isn divisable by unrolls then
  80. the for loop must jump to this label to get the correct
  81. number of executions }
  82. entrylabel : tnode;
  83. loopvar_notid:cardinal;
  84. constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;reintroduce;
  85. procedure loop_var_access(not_type:Tnotification_flag;symbol:Tsym);
  86. function pass_typecheck:tnode;override;
  87. function pass_1 : tnode;override;
  88. end;
  89. tfornodeclass = class of tfornode;
  90. texitnode = class(tunarynode)
  91. constructor create(l:tnode);virtual;
  92. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  93. procedure ppuwrite(ppufile:tcompilerppufile);override;
  94. function pass_typecheck:tnode;override;
  95. function pass_1 : tnode;override;
  96. end;
  97. texitnodeclass = class of texitnode;
  98. tbreaknode = class(tnode)
  99. constructor create;virtual;
  100. function pass_typecheck:tnode;override;
  101. function pass_1 : tnode;override;
  102. end;
  103. tbreaknodeclass = class of tbreaknode;
  104. tcontinuenode = class(tnode)
  105. constructor create;virtual;
  106. function pass_typecheck:tnode;override;
  107. function pass_1 : tnode;override;
  108. end;
  109. tcontinuenodeclass = class of tcontinuenode;
  110. tgotonode = class(tnode)
  111. labelsym : tlabelsym;
  112. labelnode : tlabelnode;
  113. exceptionblock : integer;
  114. constructor create(p : tlabelsym);virtual;
  115. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  116. procedure ppuwrite(ppufile:tcompilerppufile);override;
  117. procedure buildderefimpl;override;
  118. procedure derefimpl;override;
  119. function dogetcopy : tnode;override;
  120. function pass_typecheck:tnode;override;
  121. function pass_1 : tnode;override;
  122. function docompare(p: tnode): boolean; override;
  123. end;
  124. tgotonodeclass = class of tgotonode;
  125. tlabelnode = class(tunarynode)
  126. exceptionblock : integer;
  127. { when copying trees, this points to the newly created copy of a label }
  128. copiedto : tlabelnode;
  129. labsym : tlabelsym;
  130. constructor create(l:tnode;alabsym:tlabelsym);virtual;
  131. destructor destroy;override;
  132. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  133. procedure ppuwrite(ppufile:tcompilerppufile);override;
  134. procedure buildderefimpl;override;
  135. procedure derefimpl;override;
  136. function dogetcopy : tnode;override;
  137. function pass_typecheck:tnode;override;
  138. function pass_1 : tnode;override;
  139. function docompare(p: tnode): boolean; override;
  140. end;
  141. tlabelnodeclass = class of tlabelnode;
  142. traisenode = class(ttertiarynode)
  143. constructor create(l,taddr,tframe:tnode);virtual;
  144. function pass_typecheck:tnode;override;
  145. function pass_1 : tnode;override;
  146. end;
  147. traisenodeclass = class of traisenode;
  148. ttryexceptnode = class(tloopnode)
  149. constructor create(l,r,_t1 : tnode);virtual;reintroduce;
  150. function pass_typecheck:tnode;override;
  151. function pass_1 : tnode;override;
  152. end;
  153. ttryexceptnodeclass = class of ttryexceptnode;
  154. ttryfinallynode = class(tloopnode)
  155. implicitframe : boolean;
  156. constructor create(l,r:tnode);virtual;reintroduce;
  157. constructor create_implicit(l,r,_t1:tnode);virtual;
  158. function pass_typecheck:tnode;override;
  159. function pass_1 : tnode;override;
  160. end;
  161. ttryfinallynodeclass = class of ttryfinallynode;
  162. tonnode = class(tbinarynode)
  163. excepTSymtable : TSymtable;
  164. excepttype : tobjectdef;
  165. constructor create(l,r:tnode);virtual;
  166. destructor destroy;override;
  167. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  168. function pass_typecheck:tnode;override;
  169. function pass_1 : tnode;override;
  170. function dogetcopy : tnode;override;
  171. function docompare(p: tnode): boolean; override;
  172. end;
  173. tonnodeclass = class of tonnode;
  174. var
  175. cwhilerepeatnode : twhilerepeatnodeclass;
  176. cifnode : tifnodeclass;
  177. cfornode : tfornodeclass;
  178. cexitnode : texitnodeclass;
  179. cbreaknode : tbreaknodeclass;
  180. ccontinuenode : tcontinuenodeclass;
  181. cgotonode : tgotonodeclass;
  182. clabelnode : tlabelnodeclass;
  183. craisenode : traisenodeclass;
  184. ctryexceptnode : ttryexceptnodeclass;
  185. ctryfinallynode : ttryfinallynodeclass;
  186. connode : tonnodeclass;
  187. implementation
  188. uses
  189. globtype,systems,constexp,
  190. cutils,verbose,globals,
  191. symconst,paramgr,defcmp,defutil,htypechk,pass_1,
  192. ncal,nadd,ncon,nmem,nld,ncnv,nbas,cgobj,nutils,
  193. {$ifdef prefetchnext}
  194. ninl,
  195. {$endif prefetchnext}
  196. {$ifdef state_tracking}
  197. nstate,
  198. {$endif}
  199. cgbase,procinfo
  200. ;
  201. {****************************************************************************
  202. TLOOPNODE
  203. *****************************************************************************}
  204. constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode);
  205. begin
  206. inherited create(tt,l,r);
  207. t1:=_t1;
  208. t2:=_t2;
  209. fileinfo:=l.fileinfo;
  210. end;
  211. destructor tloopnode.destroy;
  212. begin
  213. t1.free;
  214. t2.free;
  215. inherited destroy;
  216. end;
  217. constructor tloopnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  218. begin
  219. inherited ppuload(t,ppufile);
  220. t1:=ppuloadnode(ppufile);
  221. t2:=ppuloadnode(ppufile);
  222. end;
  223. procedure tloopnode.ppuwrite(ppufile:tcompilerppufile);
  224. begin
  225. inherited ppuwrite(ppufile);
  226. ppuwritenode(ppufile,t1);
  227. ppuwritenode(ppufile,t2);
  228. end;
  229. procedure tloopnode.buildderefimpl;
  230. begin
  231. inherited buildderefimpl;
  232. if assigned(t1) then
  233. t1.buildderefimpl;
  234. if assigned(t2) then
  235. t2.buildderefimpl;
  236. end;
  237. procedure tloopnode.derefimpl;
  238. begin
  239. inherited derefimpl;
  240. if assigned(t1) then
  241. t1.derefimpl;
  242. if assigned(t2) then
  243. t2.derefimpl;
  244. end;
  245. function tloopnode.dogetcopy : tnode;
  246. var
  247. p : tloopnode;
  248. begin
  249. p:=tloopnode(inherited dogetcopy);
  250. if assigned(t1) then
  251. p.t1:=t1.dogetcopy
  252. else
  253. p.t1:=nil;
  254. if assigned(t2) then
  255. p.t2:=t2.dogetcopy
  256. else
  257. p.t2:=nil;
  258. p.loopflags:=loopflags;
  259. dogetcopy:=p;
  260. end;
  261. procedure tloopnode.insertintolist(l : tnodelist);
  262. begin
  263. end;
  264. procedure tloopnode.printnodetree(var t:text);
  265. begin
  266. write(t,printnodeindention,'(');
  267. printnodeindent;
  268. printnodeinfo(t);
  269. writeln(t);
  270. printnode(t,left);
  271. printnode(t,right);
  272. printnode(t,t1);
  273. printnode(t,t2);
  274. printnodeunindent;
  275. writeln(t,printnodeindention,')');
  276. end;
  277. function tloopnode.docompare(p: tnode): boolean;
  278. begin
  279. docompare :=
  280. inherited docompare(p) and
  281. (loopflags*loopflagsequal=tloopnode(p).loopflags*loopflagsequal) and
  282. t1.isequal(tloopnode(p).t1) and
  283. t2.isequal(tloopnode(p).t2);
  284. end;
  285. {****************************************************************************
  286. TWHILEREPEATNODE
  287. *****************************************************************************}
  288. constructor Twhilerepeatnode.create(l,r:Tnode;tab,cn:boolean);
  289. begin
  290. inherited create(whilerepeatn,l,r,nil,nil);
  291. if tab then
  292. include(loopflags, lnf_testatbegin);
  293. if cn then
  294. include(loopflags,lnf_checknegate);
  295. end;
  296. function twhilerepeatnode.pass_typecheck:tnode;
  297. var
  298. t:Tunarynode;
  299. begin
  300. result:=nil;
  301. resultdef:=voidtype;
  302. typecheckpass(left);
  303. { tp procvar support }
  304. maybe_call_procvar(left,true);
  305. {A not node can be removed.}
  306. if left.nodetype=notn then
  307. begin
  308. t:=Tunarynode(left);
  309. left:=Tunarynode(left).left;
  310. t.left:=nil;
  311. t.destroy;
  312. {Symdif operator, in case you are wondering:}
  313. loopflags:=loopflags >< [lnf_checknegate];
  314. end;
  315. { loop instruction }
  316. if assigned(right) then
  317. typecheckpass(right);
  318. set_varstate(left,vs_read,[vsf_must_be_valid]);
  319. if codegenerror then
  320. exit;
  321. if not is_boolean(left.resultdef) then
  322. begin
  323. if left.resultdef.typ=variantdef then
  324. inserttypeconv(left,booltype)
  325. else
  326. CGMessage1(type_e_boolean_expr_expected,left.resultdef.typename);
  327. end;
  328. { Give warnings for code that will never be executed for
  329. while false do }
  330. if (lnf_testatbegin in loopflags) and
  331. (left.nodetype=ordconstn) and
  332. (tordconstnode(left).value.uvalue=0) and
  333. assigned(right) then
  334. CGMessagePos(right.fileinfo,cg_w_unreachable_code);
  335. end;
  336. {$ifdef prefetchnext}
  337. type
  338. passignmentquery = ^tassignmentquery;
  339. tassignmentquery = record
  340. towhat: tnode;
  341. source: tassignmentnode;
  342. statementcount: cardinal;
  343. end;
  344. function checkassignment(var n: tnode; arg: pointer): foreachnoderesult;
  345. var
  346. query: passignmentquery absolute arg;
  347. temp, prederef: tnode;
  348. begin
  349. result := fen_norecurse_false;
  350. if (n.nodetype in [assignn,inlinen,forn,calln,whilerepeatn,casen,ifn]) then
  351. inc(query^.statementcount);
  352. { make sure there's something else in the loop besides going to the }
  353. { next item }
  354. if (query^.statementcount > 1) and
  355. (n.nodetype = assignn) then
  356. begin
  357. { skip type conversions of assignment target }
  358. temp := tassignmentnode(n).left;
  359. while (temp.nodetype = typeconvn) do
  360. temp := ttypeconvnode(temp).left;
  361. { assignment to x of the while assigned(x) check? }
  362. if not(temp.isequal(query^.towhat)) then
  363. exit;
  364. { right hand side of assignment dereferenced field of }
  365. { x? (no derefn in case of class) }
  366. temp := tassignmentnode(n).right;
  367. while (temp.nodetype = typeconvn) do
  368. temp := ttypeconvnode(temp).left;
  369. if (temp.nodetype <> subscriptn) then
  370. exit;
  371. prederef := tsubscriptnode(temp).left;
  372. temp := prederef;
  373. while (temp.nodetype = typeconvn) do
  374. temp := ttypeconvnode(temp).left;
  375. { see tests/test/prefetch1.pp }
  376. if (temp.nodetype = derefn) then
  377. temp := tderefnode(temp).left
  378. else
  379. temp := prederef;
  380. if temp.isequal(query^.towhat) then
  381. begin
  382. query^.source := tassignmentnode(n);
  383. result := fen_norecurse_true;
  384. end
  385. end
  386. { don't check nodes which can't contain an assignment or whose }
  387. { final assignment can vary a lot }
  388. else if not(n.nodetype in [calln,inlinen,casen,whilerepeatn,forn]) then
  389. result := fen_false;
  390. end;
  391. function findassignment(where: tnode; towhat: tnode): tassignmentnode;
  392. var
  393. query: tassignmentquery;
  394. begin
  395. query.towhat := towhat;
  396. query.source := nil;
  397. query.statementcount := 0;
  398. if foreachnodestatic(where,@checkassignment,@query) then
  399. result := query.source
  400. else
  401. result := nil;
  402. end;
  403. {$endif prefetchnext}
  404. function twhilerepeatnode.pass_1 : tnode;
  405. var
  406. {$ifdef prefetchnext}
  407. runnernode, prefetchcode: tnode;
  408. assignmentnode: tassignmentnode;
  409. prefetchstatements: tstatementnode;
  410. {$endif prefetchnext}
  411. old_t_times : longint;
  412. begin
  413. result:=nil;
  414. expectloc:=LOC_VOID;
  415. old_t_times:=cg.t_times;
  416. { calc register weight }
  417. if not(cs_opt_size in current_settings.optimizerswitches) then
  418. cg.t_times:=cg.t_times*8;
  419. firstpass(left);
  420. if codegenerror then
  421. exit;
  422. { loop instruction }
  423. if assigned(right) then
  424. begin
  425. firstpass(right);
  426. if codegenerror then
  427. exit;
  428. end;
  429. cg.t_times:=old_t_times;
  430. {$ifdef prefetchnext}
  431. { do at the end so all complex typeconversions are already }
  432. { converted to calln's }
  433. if (cs_opt_level1 in current_settings.optimizerswitches) and
  434. (lnf_testatbegin in loopflags) then
  435. begin
  436. { get first component of the while check }
  437. runnernode := left;
  438. while (runnernode.nodetype in [andn,orn,notn,xorn,typeconvn]) do
  439. runnernode := tunarynode(runnernode).left;
  440. { is it an assigned(x) check? }
  441. if ((runnernode.nodetype = inlinen) and
  442. (tinlinenode(runnernode).inlinenumber = in_assigned_x)) or
  443. ((runnernode.nodetype = unequaln) and
  444. (taddnode(runnernode).right.nodetype = niln)) then
  445. begin
  446. runnernode := tunarynode(runnernode).left;
  447. { in case of in_assigned_x, there's a callparan in between }
  448. if (runnernode.nodetype = callparan) then
  449. runnernode := tcallparanode(runnernode).left;
  450. while (runnernode.nodetype = typeconvn) do
  451. runnernode := ttypeconvnode(runnernode).left;
  452. { is there an "x := x(^).somefield"? }
  453. assignmentnode := findassignment(right,runnernode);
  454. if assigned(assignmentnode) then
  455. begin
  456. prefetchcode := internalstatements(prefetchstatements);
  457. addstatement(prefetchstatements,geninlinenode(in_prefetch_var,false,
  458. cderefnode.create(ctypeconvnode.create(assignmentnode.right.getcopy,voidpointertype))));
  459. addstatement(prefetchstatements,right);
  460. right := prefetchcode;
  461. typecheckpass(right);
  462. end;
  463. end;
  464. end;
  465. {$endif prefetchnext}
  466. end;
  467. {$ifdef state_tracking}
  468. function Twhilerepeatnode.track_state_pass(exec_known:boolean):boolean;
  469. var condition:Tnode;
  470. code:Tnode;
  471. done:boolean;
  472. value:boolean;
  473. change:boolean;
  474. firsttest:boolean;
  475. factval:Tnode;
  476. begin
  477. track_state_pass:=false;
  478. done:=false;
  479. firsttest:=true;
  480. {For repeat until statements, first do a pass through the code.}
  481. if not(lnf_testatbegin in flags) then
  482. begin
  483. code:=right.getcopy;
  484. if code.track_state_pass(exec_known) then
  485. track_state_pass:=true;
  486. code.destroy;
  487. end;
  488. repeat
  489. condition:=left.getcopy;
  490. code:=right.getcopy;
  491. change:=condition.track_state_pass(exec_known);
  492. factval:=aktstate.find_fact(left);
  493. if factval<>nil then
  494. begin
  495. condition.destroy;
  496. condition:=factval.getcopy;
  497. change:=true;
  498. end;
  499. if change then
  500. begin
  501. track_state_pass:=true;
  502. {Force new resultdef pass.}
  503. condition.resultdef:=nil;
  504. do_typecheckpass(condition);
  505. end;
  506. if is_constboolnode(condition) then
  507. begin
  508. {Try to turn a while loop into a repeat loop.}
  509. if firsttest then
  510. exclude(flags,testatbegin);
  511. value:=(Tordconstnode(condition).value<>0) xor checknegate;
  512. if value then
  513. begin
  514. if code.track_state_pass(exec_known) then
  515. track_state_pass:=true;
  516. end
  517. else
  518. done:=true;
  519. end
  520. else
  521. begin
  522. {Remove any modified variables from the state.}
  523. code.track_state_pass(false);
  524. done:=true;
  525. end;
  526. code.destroy;
  527. condition.destroy;
  528. firsttest:=false;
  529. until done;
  530. {The loop condition is also known, for example:
  531. while i<10 do
  532. begin
  533. ...
  534. end;
  535. When the loop is done, we do know that i<10 = false.
  536. }
  537. condition:=left.getcopy;
  538. if condition.track_state_pass(exec_known) then
  539. begin
  540. track_state_pass:=true;
  541. {Force new resultdef pass.}
  542. condition.resultdef:=nil;
  543. do_typecheckpass(condition);
  544. end;
  545. if not is_constboolnode(condition) then
  546. aktstate.store_fact(condition,
  547. cordconstnode.create(byte(checknegate),booltype,true))
  548. else
  549. condition.destroy;
  550. end;
  551. {$endif}
  552. {*****************************************************************************
  553. TIFNODE
  554. *****************************************************************************}
  555. constructor tifnode.create(l,r,_t1 : tnode);
  556. begin
  557. inherited create(ifn,l,r,_t1,nil);
  558. end;
  559. function tifnode.internalsimplify(warn: boolean) : tnode;
  560. begin
  561. result:=nil;
  562. { optimize constant expressions }
  563. if (left.nodetype=ordconstn) then
  564. begin
  565. if tordconstnode(left).value.uvalue=1 then
  566. begin
  567. if assigned(right) then
  568. result:=right
  569. else
  570. result:=cnothingnode.create;
  571. right:=nil;
  572. if warn and assigned(t1) then
  573. CGMessagePos(t1.fileinfo,cg_w_unreachable_code);
  574. end
  575. else
  576. begin
  577. if assigned(t1) then
  578. result:=t1
  579. else
  580. result:=cnothingnode.create;
  581. t1:=nil;
  582. if warn and assigned(right) then
  583. CGMessagePos(right.fileinfo,cg_w_unreachable_code);
  584. end;
  585. end;
  586. end;
  587. function tifnode.simplify : tnode;
  588. begin
  589. result:=internalsimplify(false);
  590. end;
  591. function tifnode.pass_typecheck:tnode;
  592. begin
  593. result:=nil;
  594. resultdef:=voidtype;
  595. typecheckpass(left);
  596. { tp procvar support }
  597. maybe_call_procvar(left,true);
  598. { if path }
  599. if assigned(right) then
  600. typecheckpass(right);
  601. { else path }
  602. if assigned(t1) then
  603. typecheckpass(t1);
  604. set_varstate(left,vs_read,[vsf_must_be_valid]);
  605. if codegenerror then
  606. exit;
  607. if not is_boolean(left.resultdef) then
  608. begin
  609. if left.resultdef.typ=variantdef then
  610. inserttypeconv(left,booltype)
  611. else
  612. Message1(type_e_boolean_expr_expected,left.resultdef.typename);
  613. end;
  614. result:=internalsimplify(true);
  615. end;
  616. function tifnode.pass_1 : tnode;
  617. var
  618. old_t_times : longint;
  619. begin
  620. result:=nil;
  621. expectloc:=LOC_VOID;
  622. old_t_times:=cg.t_times;
  623. firstpass(left);
  624. { determines registers weigths }
  625. if not(cs_opt_size in current_settings.optimizerswitches) then
  626. cg.t_times:=cg.t_times div 2;
  627. if cg.t_times=0 then
  628. cg.t_times:=1;
  629. { if path }
  630. if assigned(right) then
  631. firstpass(right);
  632. { else path }
  633. if assigned(t1) then
  634. firstpass(t1);
  635. { leave if we've got an error in one of the paths }
  636. if codegenerror then
  637. exit;
  638. cg.t_times:=old_t_times;
  639. end;
  640. {*****************************************************************************
  641. TFORNODE
  642. *****************************************************************************}
  643. constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
  644. begin
  645. inherited create(forn,l,r,_t1,_t2);
  646. if back then
  647. include(loopflags,lnf_backward);
  648. include(loopflags,lnf_testatbegin);
  649. end;
  650. procedure Tfornode.loop_var_access(not_type:Tnotification_flag;
  651. symbol:Tsym);
  652. begin
  653. {If there is a read access, the value of the loop counter is important;
  654. at the end of the loop the loop variable should contain the value it
  655. had in the last iteration.}
  656. if not_type=vn_onwrite then
  657. begin
  658. writeln('Loopvar does not matter on exit');
  659. end
  660. else
  661. begin
  662. exclude(loopflags,lnf_dont_mind_loopvar_on_exit);
  663. writeln('Loopvar does matter on exit');
  664. end;
  665. Tabstractvarsym(symbol).unregister_notification(loopvar_notid);
  666. end;
  667. function tfornode.pass_typecheck:tnode;
  668. var
  669. unrollres : tnode;
  670. begin
  671. result:=nil;
  672. resultdef:=voidtype;
  673. { loop unrolling }
  674. if cs_opt_loopunroll in current_settings.optimizerswitches then
  675. begin
  676. unrollres:=unroll_loop(self);
  677. if assigned(unrollres) then
  678. begin
  679. typecheckpass(unrollres);
  680. result:=unrollres;
  681. exit;
  682. end;
  683. end;
  684. { process the loopvar, from and to, varstates are already set }
  685. typecheckpass(left);
  686. typecheckpass(right);
  687. typecheckpass(t1);
  688. {Can we spare the first comparision?}
  689. if (t1.nodetype=ordconstn) and
  690. (right.nodetype=ordconstn) and
  691. (
  692. (
  693. (lnf_backward in loopflags) and
  694. (Tordconstnode(right).value>=Tordconstnode(t1).value)
  695. ) or
  696. (
  697. not(lnf_backward in loopflags) and
  698. (Tordconstnode(right).value<=Tordconstnode(t1).value)
  699. )
  700. ) then
  701. exclude(loopflags,lnf_testatbegin);
  702. { Make sure that the loop var and the
  703. from and to values are compatible types }
  704. check_ranges(right.fileinfo,right,left.resultdef);
  705. inserttypeconv(right,left.resultdef);
  706. check_ranges(t1.fileinfo,t1,left.resultdef);
  707. inserttypeconv(t1,left.resultdef);
  708. if assigned(t2) then
  709. typecheckpass(t2);
  710. end;
  711. function tfornode.pass_1 : tnode;
  712. var
  713. old_t_times : longint;
  714. begin
  715. result:=nil;
  716. expectloc:=LOC_VOID;
  717. firstpass(left);
  718. firstpass(right);
  719. firstpass(t1);
  720. if assigned(t2) then
  721. begin
  722. { Calc register weight }
  723. old_t_times:=cg.t_times;
  724. if not(cs_opt_size in current_settings.optimizerswitches) then
  725. cg.t_times:=cg.t_times*8;
  726. firstpass(t2);
  727. if codegenerror then
  728. exit;
  729. cg.t_times:=old_t_times;
  730. end;
  731. end;
  732. {*****************************************************************************
  733. TEXITNODE
  734. *****************************************************************************}
  735. constructor texitnode.create(l:tnode);
  736. begin
  737. inherited create(exitn,l);
  738. end;
  739. constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  740. begin
  741. inherited ppuload(t,ppufile);
  742. end;
  743. procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
  744. begin
  745. inherited ppuwrite(ppufile);
  746. end;
  747. function texitnode.pass_typecheck:tnode;
  748. begin
  749. result:=nil;
  750. if assigned(left) then
  751. begin
  752. { add assignment to funcretsym }
  753. inserttypeconv(left,current_procinfo.procdef.returndef);
  754. left:=cassignmentnode.create(
  755. cloadnode.create(current_procinfo.procdef.funcretsym,current_procinfo.procdef.funcretsym.owner),
  756. left);
  757. typecheckpass(left);
  758. set_varstate(left,vs_read,[vsf_must_be_valid]);
  759. end;
  760. resultdef:=voidtype;
  761. end;
  762. function texitnode.pass_1 : tnode;
  763. begin
  764. result:=nil;
  765. expectloc:=LOC_VOID;
  766. if assigned(left) then
  767. begin
  768. firstpass(left);
  769. if codegenerror then
  770. exit;
  771. end;
  772. end;
  773. {*****************************************************************************
  774. TBREAKNODE
  775. *****************************************************************************}
  776. constructor tbreaknode.create;
  777. begin
  778. inherited create(breakn);
  779. end;
  780. function tbreaknode.pass_typecheck:tnode;
  781. begin
  782. result:=nil;
  783. resultdef:=voidtype;
  784. end;
  785. function tbreaknode.pass_1 : tnode;
  786. begin
  787. result:=nil;
  788. expectloc:=LOC_VOID;
  789. end;
  790. {*****************************************************************************
  791. TCONTINUENODE
  792. *****************************************************************************}
  793. constructor tcontinuenode.create;
  794. begin
  795. inherited create(continuen);
  796. end;
  797. function tcontinuenode.pass_typecheck:tnode;
  798. begin
  799. result:=nil;
  800. resultdef:=voidtype;
  801. end;
  802. function tcontinuenode.pass_1 : tnode;
  803. begin
  804. result:=nil;
  805. expectloc:=LOC_VOID;
  806. end;
  807. {*****************************************************************************
  808. TGOTONODE
  809. *****************************************************************************}
  810. constructor tgotonode.create(p : tlabelsym);
  811. begin
  812. inherited create(goton);
  813. exceptionblock:=aktexceptblock;
  814. labelnode:=nil;
  815. labelsym:=p;
  816. end;
  817. constructor tgotonode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  818. begin
  819. inherited ppuload(t,ppufile);
  820. labelnode:=tlabelnode(ppuloadnoderef(ppufile));
  821. exceptionblock:=ppufile.getbyte;
  822. end;
  823. procedure tgotonode.ppuwrite(ppufile:tcompilerppufile);
  824. begin
  825. inherited ppuwrite(ppufile);
  826. ppuwritenoderef(ppufile,labelnode);
  827. ppufile.putbyte(exceptionblock);
  828. end;
  829. procedure tgotonode.buildderefimpl;
  830. begin
  831. inherited buildderefimpl;
  832. //!!! deref(labelnode);
  833. end;
  834. procedure tgotonode.derefimpl;
  835. begin
  836. inherited derefimpl;
  837. //!!! deref(labelnode);
  838. end;
  839. function tgotonode.pass_typecheck:tnode;
  840. begin
  841. result:=nil;
  842. resultdef:=voidtype;
  843. end;
  844. function tgotonode.pass_1 : tnode;
  845. begin
  846. result:=nil;
  847. expectloc:=LOC_VOID;
  848. include(current_procinfo.flags,pi_has_goto);
  849. { The labelnode can already be set when
  850. this node was copied }
  851. if not assigned(labelnode) then
  852. begin
  853. if assigned(labelsym.code) then
  854. labelnode:=tlabelnode(labelsym.code)
  855. else
  856. CGMessage1(cg_e_goto_label_not_found,labelsym.realname);
  857. end;
  858. { check if we don't mess with exception blocks }
  859. if assigned(labelnode) and
  860. (exceptionblock<>labelnode.exceptionblock) then
  861. CGMessage(cg_e_goto_inout_of_exception_block);
  862. end;
  863. function tgotonode.dogetcopy : tnode;
  864. var
  865. p : tgotonode;
  866. begin
  867. p:=tgotonode(inherited dogetcopy);
  868. p.exceptionblock:=exceptionblock;
  869. { force a valid labelnode }
  870. if not(assigned(labelnode)) then
  871. begin
  872. if assigned(labelsym) and assigned(labelsym.code) then
  873. labelnode:=tlabelnode(labelsym.code)
  874. else
  875. internalerror(200610291);
  876. end;
  877. p.labelsym:=labelsym;
  878. p.labelnode:=tlabelnode(labelnode.dogetcopy);
  879. result:=p;
  880. end;
  881. function tgotonode.docompare(p: tnode): boolean;
  882. begin
  883. docompare := false;
  884. end;
  885. {*****************************************************************************
  886. TLABELNODE
  887. *****************************************************************************}
  888. constructor tlabelnode.create(l:tnode;alabsym:tlabelsym);
  889. begin
  890. inherited create(labeln,l);
  891. exceptionblock:=aktexceptblock;
  892. labsym:=alabsym;
  893. { Register labelnode in labelsym }
  894. labsym.code:=self;
  895. end;
  896. constructor tlabelnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  897. begin
  898. inherited ppuload(t,ppufile);
  899. exceptionblock:=ppufile.getbyte;
  900. end;
  901. destructor tlabelnode.destroy;
  902. begin
  903. { Remove reference in labelsym, this is to prevent
  904. goto's to this label }
  905. if assigned(labsym) and (labsym.code=pointer(self)) then
  906. labsym.code:=nil;
  907. inherited destroy;
  908. end;
  909. procedure tlabelnode.ppuwrite(ppufile:tcompilerppufile);
  910. begin
  911. inherited ppuwrite(ppufile);
  912. ppufile.putbyte(exceptionblock);
  913. end;
  914. procedure tlabelnode.buildderefimpl;
  915. begin
  916. inherited buildderefimpl;
  917. end;
  918. procedure tlabelnode.derefimpl;
  919. begin
  920. inherited derefimpl;
  921. end;
  922. function tlabelnode.pass_typecheck:tnode;
  923. begin
  924. result:=nil;
  925. { left could still be unassigned }
  926. if assigned(left) then
  927. typecheckpass(left);
  928. resultdef:=voidtype;
  929. end;
  930. function tlabelnode.pass_1 : tnode;
  931. begin
  932. result:=nil;
  933. expectloc:=LOC_VOID;
  934. if assigned(left) then
  935. firstpass(left);
  936. end;
  937. function tlabelnode.dogetcopy : tnode;
  938. begin
  939. if not(assigned(copiedto)) then
  940. copiedto:=tlabelnode(inherited dogetcopy);
  941. copiedto.exceptionblock:=exceptionblock;
  942. result:=copiedto;
  943. end;
  944. function tlabelnode.docompare(p: tnode): boolean;
  945. begin
  946. docompare := false;
  947. end;
  948. {*****************************************************************************
  949. TRAISENODE
  950. *****************************************************************************}
  951. constructor traisenode.create(l,taddr,tframe:tnode);
  952. begin
  953. inherited create(raisen,l,taddr,tframe);
  954. end;
  955. function traisenode.pass_typecheck:tnode;
  956. begin
  957. result:=nil;
  958. resultdef:=voidtype;
  959. if assigned(left) then
  960. begin
  961. { first para must be a _class_ }
  962. typecheckpass(left);
  963. set_varstate(left,vs_read,[vsf_must_be_valid]);
  964. if codegenerror then
  965. exit;
  966. if not(is_class(left.resultdef)) then
  967. CGMessage1(type_e_class_type_expected,left.resultdef.typename);
  968. { insert needed typeconvs for addr,frame }
  969. if assigned(right) then
  970. begin
  971. { addr }
  972. typecheckpass(right);
  973. inserttypeconv(right,voidpointertype);
  974. { frame }
  975. if assigned(third) then
  976. begin
  977. typecheckpass(third);
  978. inserttypeconv(third,voidpointertype);
  979. end;
  980. end;
  981. end;
  982. end;
  983. function traisenode.pass_1 : tnode;
  984. begin
  985. result:=nil;
  986. include(current_procinfo.flags,pi_do_call);
  987. expectloc:=LOC_VOID;
  988. if assigned(left) then
  989. begin
  990. { first para must be a _class_ }
  991. firstpass(left);
  992. { insert needed typeconvs for addr,frame }
  993. if assigned(right) then
  994. begin
  995. { addr }
  996. firstpass(right);
  997. { frame }
  998. if assigned(third) then
  999. firstpass(third);
  1000. end;
  1001. end;
  1002. end;
  1003. {*****************************************************************************
  1004. TTRYEXCEPTNODE
  1005. *****************************************************************************}
  1006. constructor ttryexceptnode.create(l,r,_t1 : tnode);
  1007. begin
  1008. inherited create(tryexceptn,l,r,_t1,nil);
  1009. end;
  1010. function ttryexceptnode.pass_typecheck:tnode;
  1011. begin
  1012. result:=nil;
  1013. typecheckpass(left);
  1014. { on statements }
  1015. if assigned(right) then
  1016. typecheckpass(right);
  1017. { else block }
  1018. if assigned(t1) then
  1019. typecheckpass(t1);
  1020. resultdef:=voidtype;
  1021. end;
  1022. function ttryexceptnode.pass_1 : tnode;
  1023. begin
  1024. result:=nil;
  1025. include(current_procinfo.flags,pi_do_call);
  1026. expectloc:=LOC_VOID;
  1027. firstpass(left);
  1028. { on statements }
  1029. if assigned(right) then
  1030. firstpass(right);
  1031. { else block }
  1032. if assigned(t1) then
  1033. firstpass(t1);
  1034. end;
  1035. {*****************************************************************************
  1036. TTRYFINALLYNODE
  1037. *****************************************************************************}
  1038. constructor ttryfinallynode.create(l,r:tnode);
  1039. begin
  1040. inherited create(tryfinallyn,l,r,nil,nil);
  1041. implicitframe:=false;
  1042. end;
  1043. constructor ttryfinallynode.create_implicit(l,r,_t1:tnode);
  1044. begin
  1045. inherited create(tryfinallyn,l,r,_t1,nil);
  1046. implicitframe:=true;
  1047. end;
  1048. function ttryfinallynode.pass_typecheck:tnode;
  1049. begin
  1050. result:=nil;
  1051. include(current_procinfo.flags,pi_do_call);
  1052. resultdef:=voidtype;
  1053. typecheckpass(left);
  1054. // "try block" is "used"? (JM)
  1055. set_varstate(left,vs_readwritten,[vsf_must_be_valid]);
  1056. typecheckpass(right);
  1057. // "except block" is "used"? (JM)
  1058. set_varstate(right,vs_readwritten,[vsf_must_be_valid]);
  1059. { special finally block only executed when there was an exception }
  1060. if assigned(t1) then
  1061. begin
  1062. typecheckpass(t1);
  1063. // "finally block" is "used"? (JM)
  1064. set_varstate(t1,vs_readwritten,[vsf_must_be_valid]);
  1065. end;
  1066. end;
  1067. function ttryfinallynode.pass_1 : tnode;
  1068. begin
  1069. result:=nil;
  1070. expectloc:=LOC_VOID;
  1071. firstpass(left);
  1072. firstpass(right);
  1073. if assigned(t1) then
  1074. firstpass(t1);
  1075. end;
  1076. {*****************************************************************************
  1077. TONNODE
  1078. *****************************************************************************}
  1079. constructor tonnode.create(l,r:tnode);
  1080. begin
  1081. inherited create(onn,l,r);
  1082. excepTSymtable:=nil;
  1083. excepttype:=nil;
  1084. end;
  1085. destructor tonnode.destroy;
  1086. begin
  1087. { copied nodes don't need to release the symtable }
  1088. if assigned(excepTSymtable) then
  1089. excepTSymtable.free;
  1090. inherited destroy;
  1091. end;
  1092. constructor tonnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  1093. begin
  1094. inherited ppuload(t,ppufile);
  1095. excepTSymtable:=nil;
  1096. excepttype:=nil;
  1097. end;
  1098. function tonnode.dogetcopy : tnode;
  1099. var
  1100. n : tonnode;
  1101. begin
  1102. n:=tonnode(inherited dogetcopy);
  1103. if assigned(exceptsymtable) then
  1104. n.exceptsymtable:=exceptsymtable.getcopy
  1105. else
  1106. n.exceptsymtable:=nil;
  1107. n.excepttype:=excepttype;
  1108. result:=n;
  1109. end;
  1110. function tonnode.pass_typecheck:tnode;
  1111. begin
  1112. result:=nil;
  1113. resultdef:=voidtype;
  1114. if not(is_class(excepttype)) then
  1115. CGMessage1(type_e_class_type_expected,excepttype.typename);
  1116. if assigned(left) then
  1117. typecheckpass(left);
  1118. if assigned(right) then
  1119. typecheckpass(right);
  1120. end;
  1121. function tonnode.pass_1 : tnode;
  1122. begin
  1123. result:=nil;
  1124. include(current_procinfo.flags,pi_do_call);
  1125. expectloc:=LOC_VOID;
  1126. if assigned(left) then
  1127. firstpass(left);
  1128. if assigned(right) then
  1129. firstpass(right);
  1130. end;
  1131. function tonnode.docompare(p: tnode): boolean;
  1132. begin
  1133. docompare := false;
  1134. end;
  1135. begin
  1136. cwhilerepeatnode:=twhilerepeatnode;
  1137. cifnode:=tifnode;
  1138. cfornode:=tfornode;
  1139. cexitnode:=texitnode;
  1140. cgotonode:=tgotonode;
  1141. clabelnode:=tlabelnode;
  1142. craisenode:=traisenode;
  1143. ctryexceptnode:=ttryexceptnode;
  1144. ctryfinallynode:=ttryfinallynode;
  1145. connode:=tonnode;
  1146. end.