nflw.pas 41 KB

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