nflw.pas 45 KB

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