nflw.pas 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Type checking and register allocation for nodes that influence
  5. the flow
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit nflw;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,aasmbase,aasmtai,aasmcpu,cpubase,
  24. symbase,symdef,symsym;
  25. type
  26. tloopnode = class(tbinarynode)
  27. t1,t2 : tnode;
  28. constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual;
  29. destructor destroy;override;
  30. function getcopy : tnode;override;
  31. procedure insertintolist(l : tnodelist);override;
  32. {$ifdef extdebug}
  33. procedure dowrite;override;
  34. {$endif extdebug}
  35. function docompare(p: tnode): boolean; override;
  36. end;
  37. twhilerepeatnode = class(tloopnode)
  38. testatbegin,checknegate:boolean;
  39. constructor create(l,r,_t1:Tnode;tab,cn:boolean);virtual;
  40. function det_resulttype:tnode;override;
  41. function pass_1 : tnode;override;
  42. {$ifdef state_tracking}
  43. function track_state_pass(exec_known:boolean):boolean;override;
  44. {$endif}
  45. end;
  46. twhilerepeatnodeclass = class of twhilerepeatnode;
  47. tifnode = class(tloopnode)
  48. constructor create(l,r,_t1 : tnode);virtual;
  49. function det_resulttype:tnode;override;
  50. function pass_1 : tnode;override;
  51. end;
  52. tifnodeclass = class of tifnode;
  53. tfornode = class(tloopnode)
  54. testatbegin:boolean;
  55. constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;
  56. function det_resulttype:tnode;override;
  57. function pass_1 : tnode;override;
  58. end;
  59. tfornodeclass = class of tfornode;
  60. texitnode = class(tunarynode)
  61. constructor create(l:tnode);virtual;
  62. function det_resulttype:tnode;override;
  63. function pass_1 : tnode;override;
  64. end;
  65. texitnodeclass = class of texitnode;
  66. tbreaknode = class(tnode)
  67. constructor create;virtual;
  68. function det_resulttype:tnode;override;
  69. function pass_1 : tnode;override;
  70. end;
  71. tbreaknodeclass = class of tbreaknode;
  72. tcontinuenode = class(tnode)
  73. constructor create;virtual;
  74. function det_resulttype:tnode;override;
  75. function pass_1 : tnode;override;
  76. end;
  77. tcontinuenodeclass = class of tcontinuenode;
  78. tgotonode = class(tnode)
  79. labelnr : tasmlabel;
  80. labsym : tlabelsym;
  81. exceptionblock : integer;
  82. constructor create(p : tlabelsym);virtual;
  83. function getcopy : tnode;override;
  84. function det_resulttype:tnode;override;
  85. function pass_1 : tnode;override;
  86. function docompare(p: tnode): boolean; override;
  87. end;
  88. tgotonodeclass = class of tgotonode;
  89. tlabelnode = class(tunarynode)
  90. labelnr : tasmlabel;
  91. labsym : tlabelsym;
  92. exceptionblock : integer;
  93. constructor createcase(p : tasmlabel;l:tnode);virtual;
  94. constructor create(p : tlabelsym;l:tnode);virtual;
  95. function getcopy : tnode;override;
  96. function det_resulttype:tnode;override;
  97. function pass_1 : tnode;override;
  98. function docompare(p: tnode): boolean; override;
  99. end;
  100. tlabelnodeclass = class of tlabelnode;
  101. traisenode = class(tbinarynode)
  102. frametree : tnode;
  103. constructor create(l,taddr,tframe:tnode);virtual;
  104. function getcopy : tnode;override;
  105. procedure insertintolist(l : tnodelist);override;
  106. function det_resulttype:tnode;override;
  107. function pass_1 : tnode;override;
  108. function docompare(p: tnode): boolean; override;
  109. end;
  110. traisenodeclass = class of traisenode;
  111. ttryexceptnode = class(tloopnode)
  112. constructor create(l,r,_t1 : tnode);virtual;
  113. function det_resulttype:tnode;override;
  114. function pass_1 : tnode;override;
  115. end;
  116. ttryexceptnodeclass = class of ttryexceptnode;
  117. ttryfinallynode = class(tbinarynode)
  118. constructor create(l,r:tnode);virtual;
  119. function det_resulttype:tnode;override;
  120. function pass_1 : tnode;override;
  121. end;
  122. ttryfinallynodeclass = class of ttryfinallynode;
  123. tonnode = class(tbinarynode)
  124. exceptsymtable : tsymtable;
  125. excepttype : tobjectdef;
  126. constructor create(l,r:tnode);virtual;
  127. destructor destroy;override;
  128. function det_resulttype:tnode;override;
  129. function pass_1 : tnode;override;
  130. function getcopy : tnode;override;
  131. function docompare(p: tnode): boolean; override;
  132. end;
  133. tonnodeclass = class of tonnode;
  134. tfailnode = class(tnode)
  135. constructor create;virtual;
  136. function det_resulttype:tnode;override;
  137. function pass_1: tnode;override;
  138. function docompare(p: tnode): boolean; override;
  139. end;
  140. tfailnodeclass = class of tfailnode;
  141. { for compatibilty }
  142. function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode;
  143. var
  144. cwhilerepeatnode : twhilerepeatnodeclass;
  145. cifnode : tifnodeclass;
  146. cfornode : tfornodeclass;
  147. cexitnode : texitnodeclass;
  148. cbreaknode : tbreaknodeclass;
  149. ccontinuenode : tcontinuenodeclass;
  150. cgotonode : tgotonodeclass;
  151. clabelnode : tlabelnodeclass;
  152. craisenode : traisenodeclass;
  153. ctryexceptnode : ttryexceptnodeclass;
  154. ctryfinallynode : ttryfinallynodeclass;
  155. connode : tonnodeclass;
  156. cfailnode : tfailnodeclass;
  157. implementation
  158. uses
  159. globtype,systems,
  160. cutils,verbose,globals,
  161. symconst,symtable,paramgr,defbase,htypechk,pass_1,
  162. ncon,nmem,nld,ncnv,nbas,rgobj,
  163. {$ifdef state_tracking}
  164. nstate,
  165. {$endif}
  166. cgbase
  167. ;
  168. function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode;
  169. var
  170. p : tnode;
  171. begin
  172. case t of
  173. ifn:
  174. p:=cifnode.create(l,r,n1);
  175. whilerepeatn:
  176. if back then
  177. {Repeat until.}
  178. p:=cwhilerepeatnode.create(l,r,n1,false,true)
  179. else
  180. {While do.}
  181. p:=cwhilerepeatnode.create(l,r,n1,true,false);
  182. forn:
  183. p:=cfornode.create(l,r,n1,nil,back);
  184. end;
  185. genloopnode:=p;
  186. end;
  187. {****************************************************************************
  188. TLOOPNODE
  189. *****************************************************************************}
  190. constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode);
  191. begin
  192. inherited create(tt,l,r);
  193. t1:=_t1;
  194. t2:=_t2;
  195. set_file_line(l);
  196. end;
  197. destructor tloopnode.destroy;
  198. begin
  199. t1.free;
  200. t2.free;
  201. inherited destroy;
  202. end;
  203. function tloopnode.getcopy : tnode;
  204. var
  205. p : tloopnode;
  206. begin
  207. p:=tloopnode(inherited getcopy);
  208. if assigned(t1) then
  209. p.t1:=t1.getcopy
  210. else
  211. p.t1:=nil;
  212. if assigned(t2) then
  213. p.t2:=t2.getcopy
  214. else
  215. p.t2:=nil;
  216. getcopy:=p;
  217. end;
  218. procedure tloopnode.insertintolist(l : tnodelist);
  219. begin
  220. end;
  221. {$ifdef extdebug}
  222. procedure tloopnode.dowrite;
  223. begin
  224. inherited dowrite;
  225. writenodeindention:=writenodeindention+' ';
  226. writenode(t1);
  227. writenode(t2);
  228. delete(writenodeindention,1,4);
  229. end;
  230. {$endif extdebug}
  231. function tloopnode.docompare(p: tnode): boolean;
  232. begin
  233. docompare :=
  234. inherited docompare(p) and
  235. t1.isequal(tloopnode(p).t1) and
  236. t2.isequal(tloopnode(p).t2);
  237. end;
  238. {****************************************************************************
  239. TWHILEREPEATNODE
  240. *****************************************************************************}
  241. constructor Twhilerepeatnode.create(l,r,_t1:Tnode;tab,cn:boolean);
  242. begin
  243. inherited create(whilerepeatn,l,r,_t1,nil);
  244. testatbegin:=tab;
  245. checknegate:=cn;
  246. end;
  247. function twhilerepeatnode.det_resulttype:tnode;
  248. var
  249. t:Tunarynode;
  250. begin
  251. result:=nil;
  252. resulttype:=voidtype;
  253. resulttypepass(left);
  254. {A not node can be removed.}
  255. if left.nodetype=notn then
  256. begin
  257. t:=Tunarynode(left);
  258. left:=Tunarynode(left).left;
  259. t.left:=nil;
  260. t.destroy;
  261. checknegate:=not checknegate;
  262. end;
  263. { loop instruction }
  264. if assigned(right) then
  265. resulttypepass(right);
  266. set_varstate(left,true);
  267. if codegenerror then
  268. exit;
  269. if not is_boolean(left.resulttype.def) then
  270. begin
  271. CGMessage(type_e_mismatch);
  272. exit;
  273. end;
  274. end;
  275. function twhilerepeatnode.pass_1 : tnode;
  276. var
  277. old_t_times : longint;
  278. begin
  279. result:=nil;
  280. old_t_times:=rg.t_times;
  281. { calc register weight }
  282. if not(cs_littlesize in aktglobalswitches ) then
  283. rg.t_times:=rg.t_times*8;
  284. rg.cleartempgen;
  285. firstpass(left);
  286. if codegenerror then
  287. exit;
  288. registers32:=left.registers32;
  289. registersfpu:=left.registersfpu;
  290. {$ifdef SUPPORT_MMX}
  291. registersmmx:=left.registersmmx;
  292. {$endif SUPPORT_MMX}
  293. { loop instruction }
  294. if assigned(right) then
  295. begin
  296. rg.cleartempgen;
  297. firstpass(right);
  298. if codegenerror then
  299. exit;
  300. if registers32<right.registers32 then
  301. registers32:=right.registers32;
  302. if registersfpu<right.registersfpu then
  303. registersfpu:=right.registersfpu;
  304. {$ifdef SUPPORT_MMX}
  305. if registersmmx<right.registersmmx then
  306. registersmmx:=right.registersmmx;
  307. {$endif SUPPORT_MMX}
  308. end;
  309. rg.t_times:=old_t_times;
  310. end;
  311. {$ifdef state_tracking}
  312. function Twhilerepeatnode.track_state_pass(exec_known:boolean):boolean;
  313. var condition:Tnode;
  314. code:Tnode;
  315. done:boolean;
  316. value:boolean;
  317. change:boolean;
  318. firsttest:boolean;
  319. factval:Tnode;
  320. begin
  321. track_state_pass:=false;
  322. done:=false;
  323. firsttest:=true;
  324. {For repeat until statements, first do a pass through the code.}
  325. if not testatbegin then
  326. begin
  327. code:=right.getcopy;
  328. if code.track_state_pass(exec_known) then
  329. track_state_pass:=true;
  330. code.destroy;
  331. end;
  332. repeat
  333. condition:=left.getcopy;
  334. code:=right.getcopy;
  335. change:=condition.track_state_pass(exec_known);
  336. factval:=aktstate.find_fact(left);
  337. if factval<>nil then
  338. begin
  339. condition.destroy;
  340. condition:=factval.getcopy;
  341. change:=true;
  342. end;
  343. if change then
  344. begin
  345. track_state_pass:=true;
  346. {Force new resulttype pass.}
  347. condition.resulttype.def:=nil;
  348. do_resulttypepass(condition);
  349. end;
  350. if is_constboolnode(condition) then
  351. begin
  352. {Try to turn a while loop into a repeat loop.}
  353. if firsttest then
  354. begin
  355. testatbegin:=false;
  356. writeln('while->repeat');
  357. end;
  358. value:=(Tordconstnode(condition).value<>0) xor checknegate;
  359. if value then
  360. begin
  361. if code.track_state_pass(exec_known) then
  362. track_state_pass:=true;
  363. end
  364. else
  365. done:=true;
  366. end
  367. else
  368. begin
  369. {Remove any modified variables from the state.}
  370. code.track_state_pass(false);
  371. done:=true;
  372. end;
  373. code.destroy;
  374. condition.destroy;
  375. firsttest:=false;
  376. until done;
  377. {The loop condition is also known, for example:
  378. while i<10 do
  379. begin
  380. ...
  381. end;
  382. When the loop is done, we do know that i<10 = false.
  383. }
  384. condition:=left.getcopy;
  385. if condition.track_state_pass(exec_known) then
  386. begin
  387. track_state_pass:=true;
  388. {Force new resulttype pass.}
  389. condition.resulttype.def:=nil;
  390. do_resulttypepass(condition);
  391. end;
  392. if not is_constboolnode(condition) then
  393. aktstate.store_fact(condition,
  394. cordconstnode.create(byte(checknegate),booltype))
  395. else
  396. condition.destroy;
  397. end;
  398. {$endif}
  399. {*****************************************************************************
  400. TIFNODE
  401. *****************************************************************************}
  402. constructor tifnode.create(l,r,_t1 : tnode);
  403. begin
  404. inherited create(ifn,l,r,_t1,nil);
  405. end;
  406. function tifnode.det_resulttype:tnode;
  407. begin
  408. result:=nil;
  409. resulttype:=voidtype;
  410. resulttypepass(left);
  411. { if path }
  412. if assigned(right) then
  413. resulttypepass(right);
  414. { else path }
  415. if assigned(t1) then
  416. resulttypepass(t1);
  417. set_varstate(left,true);
  418. if codegenerror then
  419. exit;
  420. if not is_boolean(left.resulttype.def) then
  421. Message1(type_e_boolean_expr_expected,left.resulttype.def.typename);
  422. end;
  423. function tifnode.pass_1 : tnode;
  424. var
  425. old_t_times : longint;
  426. hp : tnode;
  427. begin
  428. result:=nil;
  429. old_t_times:=rg.t_times;
  430. rg.cleartempgen;
  431. firstpass(left);
  432. registers32:=left.registers32;
  433. registersfpu:=left.registersfpu;
  434. {$ifdef SUPPORT_MMX}
  435. registersmmx:=left.registersmmx;
  436. {$endif SUPPORT_MMX}
  437. { determines registers weigths }
  438. if not(cs_littlesize in aktglobalswitches) then
  439. rg.t_times:=rg.t_times div 2;
  440. if rg.t_times=0 then
  441. rg.t_times:=1;
  442. { if path }
  443. if assigned(right) then
  444. begin
  445. rg.cleartempgen;
  446. firstpass(right);
  447. if registers32<right.registers32 then
  448. registers32:=right.registers32;
  449. if registersfpu<right.registersfpu then
  450. registersfpu:=right.registersfpu;
  451. {$ifdef SUPPORT_MMX}
  452. if registersmmx<right.registersmmx then
  453. registersmmx:=right.registersmmx;
  454. {$endif SUPPORT_MMX}
  455. end;
  456. { else path }
  457. if assigned(t1) then
  458. begin
  459. rg.cleartempgen;
  460. firstpass(t1);
  461. if registers32<t1.registers32 then
  462. registers32:=t1.registers32;
  463. if registersfpu<t1.registersfpu then
  464. registersfpu:=t1.registersfpu;
  465. {$ifdef SUPPORT_MMX}
  466. if registersmmx<t1.registersmmx then
  467. registersmmx:=t1.registersmmx;
  468. {$endif SUPPORT_MMX}
  469. end;
  470. { leave if we've got an error in one of the paths }
  471. if codegenerror then
  472. exit;
  473. if left.nodetype=ordconstn then
  474. begin
  475. { optimize }
  476. if tordconstnode(left).value=1 then
  477. begin
  478. hp:=right;
  479. right:=nil;
  480. { we cannot set p to nil !!! }
  481. if assigned(hp) then
  482. result:=hp
  483. else
  484. result:=cnothingnode.create;
  485. end
  486. else
  487. begin
  488. hp:=t1;
  489. t1:=nil;
  490. { we cannot set p to nil !!! }
  491. if assigned(hp) then
  492. result:=hp
  493. else
  494. result:=cnothingnode.create;
  495. end;
  496. end;
  497. rg.t_times:=old_t_times;
  498. end;
  499. {*****************************************************************************
  500. TFORNODE
  501. *****************************************************************************}
  502. constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
  503. begin
  504. inherited create(forn,l,r,_t1,_t2);
  505. if back then
  506. include(flags,nf_backward);
  507. testatbegin:=true;
  508. end;
  509. function tfornode.det_resulttype:tnode;
  510. var
  511. hp : tnode;
  512. begin
  513. result:=nil;
  514. resulttype:=voidtype;
  515. if left.nodetype<>assignn then
  516. begin
  517. CGMessage(cg_e_illegal_expression);
  518. exit;
  519. end;
  520. {Can we spare the first comparision?}
  521. if right.nodetype=ordconstn then
  522. if Tassignmentnode(left).right.nodetype=ordconstn then
  523. testatbegin:=not(((nf_backward in flags) and
  524. (Tordconstnode(Tassignmentnode(left).right).value>=Tordconstnode(right).value))
  525. or (not(nf_backward in flags) and
  526. (Tordconstnode(Tassignmentnode(left).right).value<=Tordconstnode(right).value)));
  527. { save counter var }
  528. t2:=tassignmentnode(left).left.getcopy;
  529. resulttypepass(left);
  530. set_varstate(left,false);
  531. if assigned(t1) then
  532. begin
  533. resulttypepass(t1);
  534. if codegenerror then
  535. exit;
  536. end;
  537. { process count var }
  538. resulttypepass(t2);
  539. set_varstate(t2,true);
  540. if codegenerror then
  541. exit;
  542. { Check count var, record fields are also allowed in tp7 }
  543. hp:=t2;
  544. while (hp.nodetype=subscriptn) or
  545. ((hp.nodetype=vecn) and
  546. is_constintnode(tvecnode(hp).right)) do
  547. hp:=tunarynode(hp).left;
  548. { we need a simple loadn, but the load must be in a global symtable or
  549. in the same lexlevel }
  550. if (hp.nodetype=funcretn) or
  551. ((hp.nodetype=loadn) and
  552. ((tloadnode(hp).symtable.symtablelevel<=1) or
  553. (tloadnode(hp).symtable.symtablelevel=lexlevel))) then
  554. begin
  555. if (hp.nodetype=loadn) and
  556. (tloadnode(hp).symtableentry.typ=varsym) then
  557. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_used;
  558. if (not(is_ordinal(t2.resulttype.def)) or is_64bitint(t2.resulttype.def)) then
  559. CGMessagePos(hp.fileinfo,type_e_ordinal_expr_expected);
  560. end
  561. else
  562. CGMessagePos(hp.fileinfo,cg_e_illegal_count_var);
  563. resulttypepass(right);
  564. set_varstate(right,true);
  565. inserttypeconv(right,t2.resulttype);
  566. end;
  567. function tfornode.pass_1 : tnode;
  568. var
  569. old_t_times : longint;
  570. begin
  571. result:=nil;
  572. { Calc register weight }
  573. old_t_times:=rg.t_times;
  574. if not(cs_littlesize in aktglobalswitches) then
  575. rg.t_times:=rg.t_times*8;
  576. rg.cleartempgen;
  577. firstpass(left);
  578. rg.cleartempgen;
  579. if assigned(t1) then
  580. begin
  581. firstpass(t1);
  582. if codegenerror then
  583. exit;
  584. end;
  585. registers32:=t1.registers32;
  586. registersfpu:=t1.registersfpu;
  587. {$ifdef SUPPORT_MMX}
  588. registersmmx:=left.registersmmx;
  589. {$endif SUPPORT_MMX}
  590. if left.registers32>registers32 then
  591. registers32:=left.registers32;
  592. if left.registersfpu>registersfpu then
  593. registersfpu:=left.registersfpu;
  594. {$ifdef SUPPORT_MMX}
  595. if left.registersmmx>registersmmx then
  596. registersmmx:=left.registersmmx;
  597. {$endif SUPPORT_MMX}
  598. { process count var }
  599. rg.cleartempgen;
  600. firstpass(t2);
  601. if codegenerror then
  602. exit;
  603. if t2.registers32>registers32 then
  604. registers32:=t2.registers32;
  605. if t2.registersfpu>registersfpu then
  606. registersfpu:=t2.registersfpu;
  607. {$ifdef SUPPORT_MMX}
  608. if t2.registersmmx>registersmmx then
  609. registersmmx:=t2.registersmmx;
  610. {$endif SUPPORT_MMX}
  611. rg.cleartempgen;
  612. firstpass(right);
  613. if right.registers32>registers32 then
  614. registers32:=right.registers32;
  615. if right.registersfpu>registersfpu then
  616. registersfpu:=right.registersfpu;
  617. {$ifdef SUPPORT_MMX}
  618. if right.registersmmx>registersmmx then
  619. registersmmx:=right.registersmmx;
  620. {$endif SUPPORT_MMX}
  621. { we need at least one register for comparisons PM }
  622. if registers32=0 then
  623. inc(registers32);
  624. rg.t_times:=old_t_times;
  625. end;
  626. {*****************************************************************************
  627. TEXITNODE
  628. *****************************************************************************}
  629. constructor texitnode.create(l:tnode);
  630. begin
  631. inherited create(exitn,l);
  632. end;
  633. function texitnode.det_resulttype:tnode;
  634. var
  635. pt : tnode;
  636. begin
  637. result:=nil;
  638. { Check the 2 types }
  639. if not inlining_procedure then
  640. begin
  641. if assigned(left) then
  642. begin
  643. inserttypeconv(left,aktprocdef.rettype);
  644. if paramanager.ret_in_param(aktprocdef.rettype.def) or
  645. (procinfo^.no_fast_exit) or
  646. ((procinfo^.flags and pi_uses_exceptions)<>0) then
  647. begin
  648. pt:=cfuncretnode.create(aktprocdef.funcretsym);
  649. left:=cassignmentnode.create(pt,left);
  650. end;
  651. end;
  652. end;
  653. if assigned(left) then
  654. begin
  655. resulttypepass(left);
  656. set_varstate(left,true);
  657. end;
  658. resulttype:=voidtype;
  659. end;
  660. function texitnode.pass_1 : tnode;
  661. begin
  662. result:=nil;
  663. if assigned(left) then
  664. begin
  665. firstpass(left);
  666. if codegenerror then
  667. exit;
  668. registers32:=left.registers32;
  669. registersfpu:=left.registersfpu;
  670. {$ifdef SUPPORT_MMX}
  671. registersmmx:=left.registersmmx;
  672. {$endif SUPPORT_MMX}
  673. end;
  674. end;
  675. {*****************************************************************************
  676. TBREAKNODE
  677. *****************************************************************************}
  678. constructor tbreaknode.create;
  679. begin
  680. inherited create(breakn);
  681. end;
  682. function tbreaknode.det_resulttype:tnode;
  683. begin
  684. result:=nil;
  685. resulttype:=voidtype;
  686. end;
  687. function tbreaknode.pass_1 : tnode;
  688. begin
  689. result:=nil;
  690. end;
  691. {*****************************************************************************
  692. TCONTINUENODE
  693. *****************************************************************************}
  694. constructor tcontinuenode.create;
  695. begin
  696. inherited create(continuen);
  697. end;
  698. function tcontinuenode.det_resulttype:tnode;
  699. begin
  700. result:=nil;
  701. resulttype:=voidtype;
  702. end;
  703. function tcontinuenode.pass_1 : tnode;
  704. begin
  705. result:=nil;
  706. end;
  707. {*****************************************************************************
  708. TGOTONODE
  709. *****************************************************************************}
  710. constructor tgotonode.create(p : tlabelsym);
  711. begin
  712. inherited create(goton);
  713. exceptionblock:=aktexceptblock;
  714. labsym:=p;
  715. labelnr:=p.lab;
  716. end;
  717. function tgotonode.det_resulttype:tnode;
  718. begin
  719. result:=nil;
  720. resulttype:=voidtype;
  721. end;
  722. function tgotonode.pass_1 : tnode;
  723. begin
  724. result:=nil;
  725. { check if }
  726. if assigned(labsym) and
  727. assigned(labsym.code) and
  728. (exceptionblock<>tlabelnode(labsym.code).exceptionblock) then
  729. begin
  730. writeln('goto exceptblock: ',exceptionblock);
  731. writeln('label exceptblock: ',tlabelnode(labsym.code).exceptionblock);
  732. CGMessage(cg_e_goto_inout_of_exception_block);
  733. end;
  734. end;
  735. function tgotonode.getcopy : tnode;
  736. var
  737. p : tgotonode;
  738. begin
  739. p:=tgotonode(inherited getcopy);
  740. p.labelnr:=labelnr;
  741. p.labsym:=labsym;
  742. p.exceptionblock:=exceptionblock;
  743. result:=p;
  744. end;
  745. function tgotonode.docompare(p: tnode): boolean;
  746. begin
  747. docompare := false;
  748. end;
  749. {*****************************************************************************
  750. TLABELNODE
  751. *****************************************************************************}
  752. constructor tlabelnode.createcase(p : tasmlabel;l:tnode);
  753. begin
  754. inherited create(labeln,l);
  755. { it shouldn't be possible to jump to case labels using goto }
  756. exceptionblock:=-1;
  757. labsym:=nil;
  758. labelnr:=p;
  759. end;
  760. constructor tlabelnode.create(p : tlabelsym;l:tnode);
  761. begin
  762. inherited create(labeln,l);
  763. exceptionblock:=aktexceptblock;
  764. labsym:=p;
  765. labelnr:=p.lab;
  766. { save the current labelnode in the labelsym }
  767. p.code:=self;
  768. end;
  769. function tlabelnode.det_resulttype:tnode;
  770. begin
  771. result:=nil;
  772. { left could still be unassigned }
  773. if assigned(left) then
  774. resulttypepass(left);
  775. resulttype:=voidtype;
  776. end;
  777. function tlabelnode.pass_1 : tnode;
  778. begin
  779. result:=nil;
  780. if assigned(left) then
  781. begin
  782. rg.cleartempgen;
  783. firstpass(left);
  784. registers32:=left.registers32;
  785. registersfpu:=left.registersfpu;
  786. {$ifdef SUPPORT_MMX}
  787. registersmmx:=left.registersmmx;
  788. {$endif SUPPORT_MMX}
  789. end;
  790. end;
  791. function tlabelnode.getcopy : tnode;
  792. var
  793. p : tlabelnode;
  794. begin
  795. p:=tlabelnode(inherited getcopy);
  796. p.labelnr:=labelnr;
  797. p.exceptionblock:=exceptionblock;
  798. p.labsym:=labsym;
  799. result:=p;
  800. end;
  801. function tlabelnode.docompare(p: tnode): boolean;
  802. begin
  803. docompare := false;
  804. end;
  805. {*****************************************************************************
  806. TRAISENODE
  807. *****************************************************************************}
  808. constructor traisenode.create(l,taddr,tframe:tnode);
  809. begin
  810. inherited create(raisen,l,taddr);
  811. frametree:=tframe;
  812. end;
  813. function traisenode.getcopy : tnode;
  814. var
  815. n : traisenode;
  816. begin
  817. n:=traisenode(inherited getcopy);
  818. if assigned(frametree) then
  819. n.frametree:=frametree.getcopy
  820. else
  821. n.frametree:=nil;
  822. getcopy:=n;
  823. end;
  824. procedure traisenode.insertintolist(l : tnodelist);
  825. begin
  826. end;
  827. function traisenode.det_resulttype:tnode;
  828. begin
  829. result:=nil;
  830. resulttype:=voidtype;
  831. if assigned(left) then
  832. begin
  833. { first para must be a _class_ }
  834. resulttypepass(left);
  835. set_varstate(left,true);
  836. if codegenerror then
  837. exit;
  838. if not(is_class(left.resulttype.def)) then
  839. CGMessage(type_e_mismatch);
  840. { insert needed typeconvs for addr,frame }
  841. if assigned(right) then
  842. begin
  843. { addr }
  844. resulttypepass(right);
  845. inserttypeconv(right,voidpointertype);
  846. { frame }
  847. if assigned(frametree) then
  848. begin
  849. resulttypepass(frametree);
  850. inserttypeconv(frametree,voidpointertype);
  851. end;
  852. end;
  853. end;
  854. end;
  855. function traisenode.pass_1 : tnode;
  856. begin
  857. result:=nil;
  858. if assigned(left) then
  859. begin
  860. { first para must be a _class_ }
  861. firstpass(left);
  862. { insert needed typeconvs for addr,frame }
  863. if assigned(right) then
  864. begin
  865. { addr }
  866. firstpass(right);
  867. { frame }
  868. if assigned(frametree) then
  869. firstpass(frametree);
  870. end;
  871. left_right_max;
  872. end;
  873. end;
  874. function traisenode.docompare(p: tnode): boolean;
  875. begin
  876. docompare := false;
  877. end;
  878. {*****************************************************************************
  879. TTRYEXCEPTNODE
  880. *****************************************************************************}
  881. constructor ttryexceptnode.create(l,r,_t1 : tnode);
  882. begin
  883. inherited create(tryexceptn,l,r,_t1,nil);
  884. end;
  885. function ttryexceptnode.det_resulttype:tnode;
  886. begin
  887. result:=nil;
  888. resulttypepass(left);
  889. { on statements }
  890. if assigned(right) then
  891. resulttypepass(right);
  892. { else block }
  893. if assigned(t1) then
  894. resulttypepass(t1);
  895. resulttype:=voidtype;
  896. end;
  897. function ttryexceptnode.pass_1 : tnode;
  898. begin
  899. result:=nil;
  900. rg.cleartempgen;
  901. firstpass(left);
  902. { on statements }
  903. if assigned(right) then
  904. begin
  905. rg.cleartempgen;
  906. firstpass(right);
  907. registers32:=max(registers32,right.registers32);
  908. registersfpu:=max(registersfpu,right.registersfpu);
  909. {$ifdef SUPPORT_MMX}
  910. registersmmx:=max(registersmmx,right.registersmmx);
  911. {$endif SUPPORT_MMX}
  912. end;
  913. { else block }
  914. if assigned(t1) then
  915. begin
  916. firstpass(t1);
  917. registers32:=max(registers32,t1.registers32);
  918. registersfpu:=max(registersfpu,t1.registersfpu);
  919. {$ifdef SUPPORT_MMX}
  920. registersmmx:=max(registersmmx,t1.registersmmx);
  921. {$endif SUPPORT_MMX}
  922. end;
  923. end;
  924. {*****************************************************************************
  925. TTRYFINALLYNODE
  926. *****************************************************************************}
  927. constructor ttryfinallynode.create(l,r:tnode);
  928. begin
  929. inherited create(tryfinallyn,l,r);
  930. end;
  931. function ttryfinallynode.det_resulttype:tnode;
  932. begin
  933. result:=nil;
  934. resulttype:=voidtype;
  935. resulttypepass(left);
  936. set_varstate(left,true);
  937. resulttypepass(right);
  938. set_varstate(right,true);
  939. end;
  940. function ttryfinallynode.pass_1 : tnode;
  941. begin
  942. result:=nil;
  943. rg.cleartempgen;
  944. firstpass(left);
  945. rg.cleartempgen;
  946. firstpass(right);
  947. left_right_max;
  948. end;
  949. {*****************************************************************************
  950. TONNODE
  951. *****************************************************************************}
  952. constructor tonnode.create(l,r:tnode);
  953. begin
  954. inherited create(onn,l,r);
  955. exceptsymtable:=nil;
  956. excepttype:=nil;
  957. end;
  958. destructor tonnode.destroy;
  959. begin
  960. if assigned(exceptsymtable) then
  961. exceptsymtable.free;
  962. inherited destroy;
  963. end;
  964. function tonnode.getcopy : tnode;
  965. var
  966. n : tonnode;
  967. begin
  968. n:=tonnode(inherited getcopy);
  969. n.exceptsymtable:=exceptsymtable;
  970. n.excepttype:=excepttype;
  971. result:=n;
  972. end;
  973. function tonnode.det_resulttype:tnode;
  974. begin
  975. result:=nil;
  976. resulttype:=voidtype;
  977. if not(is_class(excepttype)) then
  978. CGMessage(type_e_mismatch);
  979. if assigned(left) then
  980. resulttypepass(left);
  981. if assigned(right) then
  982. resulttypepass(right);
  983. end;
  984. function tonnode.pass_1 : tnode;
  985. begin
  986. result:=nil;
  987. rg.cleartempgen;
  988. registers32:=0;
  989. registersfpu:=0;
  990. {$ifdef SUPPORT_MMX}
  991. registersmmx:=0;
  992. {$endif SUPPORT_MMX}
  993. if assigned(left) then
  994. begin
  995. firstpass(left);
  996. registers32:=left.registers32;
  997. registersfpu:=left.registersfpu;
  998. {$ifdef SUPPORT_MMX}
  999. registersmmx:=left.registersmmx;
  1000. {$endif SUPPORT_MMX}
  1001. end;
  1002. rg.cleartempgen;
  1003. if assigned(right) then
  1004. begin
  1005. firstpass(right);
  1006. registers32:=max(registers32,right.registers32);
  1007. registersfpu:=max(registersfpu,right.registersfpu);
  1008. {$ifdef SUPPORT_MMX}
  1009. registersmmx:=max(registersmmx,right.registersmmx);
  1010. {$endif SUPPORT_MMX}
  1011. end;
  1012. end;
  1013. function tonnode.docompare(p: tnode): boolean;
  1014. begin
  1015. docompare := false;
  1016. end;
  1017. {*****************************************************************************
  1018. TFAILNODE
  1019. *****************************************************************************}
  1020. constructor tfailnode.create;
  1021. begin
  1022. inherited create(failn);
  1023. end;
  1024. function tfailnode.det_resulttype:tnode;
  1025. begin
  1026. result:=nil;
  1027. resulttype:=voidtype;
  1028. end;
  1029. function tfailnode.pass_1 : tnode;
  1030. begin
  1031. result:=nil;
  1032. end;
  1033. function tfailnode.docompare(p: tnode): boolean;
  1034. begin
  1035. docompare := false;
  1036. end;
  1037. begin
  1038. cwhilerepeatnode:=twhilerepeatnode;
  1039. cifnode:=tifnode;
  1040. cfornode:=tfornode;
  1041. cexitnode:=texitnode;
  1042. cgotonode:=tgotonode;
  1043. clabelnode:=tlabelnode;
  1044. craisenode:=traisenode;
  1045. ctryexceptnode:=ttryexceptnode;
  1046. ctryfinallynode:=ttryfinallynode;
  1047. connode:=tonnode;
  1048. cfailnode:=tfailnode;
  1049. end.
  1050. {
  1051. $Log$
  1052. Revision 1.43 2002-07-20 11:57:54 florian
  1053. * types.pas renamed to defbase.pas because D6 contains a types
  1054. unit so this would conflicts if D6 programms are compiled
  1055. + Willamette/SSE2 instructions to assembler added
  1056. Revision 1.42 2002/07/20 11:18:18 daniel
  1057. * Small mistake fixed; the skip test was done before we know the for node
  1058. is correct.
  1059. Revision 1.40 2002/07/20 08:19:31 daniel
  1060. * State tracker automatically changes while loops into repeat loops
  1061. Revision 1.39 2002/07/19 12:55:27 daniel
  1062. * Further developed state tracking in whilerepeatn
  1063. Revision 1.38 2002/07/19 11:41:35 daniel
  1064. * State tracker work
  1065. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1066. allows the state tracker to change while nodes automatically into
  1067. repeat nodes.
  1068. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1069. 'not(a>b)' is optimized into 'a<=b'.
  1070. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1071. by removing the notn and later switchting the true and falselabels. The
  1072. same is done with 'repeat until not a'.
  1073. Revision 1.37 2002/07/16 13:57:02 florian
  1074. * raise takes now a void pointer as at and frame address
  1075. instead of a longint
  1076. Revision 1.36 2002/07/15 18:03:15 florian
  1077. * readded removed changes
  1078. Revision 1.35 2002/07/14 18:00:44 daniel
  1079. + Added the beginning of a state tracker. This will track the values of
  1080. variables through procedures and optimize things away.
  1081. Revision 1.34 2002/07/11 14:41:28 florian
  1082. * start of the new generic parameter handling
  1083. Revision 1.33 2002/07/01 18:46:23 peter
  1084. * internal linker
  1085. * reorganized aasm layer
  1086. Revision 1.32 2002/05/18 13:34:10 peter
  1087. * readded missing revisions
  1088. Revision 1.31 2002/05/16 19:46:38 carl
  1089. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1090. + try to fix temp allocation (still in ifdef)
  1091. + generic constructor calls
  1092. + start of tassembler / tmodulebase class cleanup
  1093. Revision 1.29 2002/05/12 16:53:07 peter
  1094. * moved entry and exitcode to ncgutil and cgobj
  1095. * foreach gets extra argument for passing local data to the
  1096. iterator function
  1097. * -CR checks also class typecasts at runtime by changing them
  1098. into as
  1099. * fixed compiler to cycle with the -CR option
  1100. * fixed stabs with elf writer, finally the global variables can
  1101. be watched
  1102. * removed a lot of routines from cga unit and replaced them by
  1103. calls to cgobj
  1104. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1105. u32bit then the other is typecasted also to u32bit without giving
  1106. a rangecheck warning/error.
  1107. * fixed pascal calling method with reversing also the high tree in
  1108. the parast, detected by tcalcst3 test
  1109. Revision 1.28 2002/03/31 20:26:34 jonas
  1110. + a_loadfpu_* and a_loadmm_* methods in tcg
  1111. * register allocation is now handled by a class and is mostly processor
  1112. independent (+rgobj.pas and i386/rgcpu.pas)
  1113. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1114. * some small improvements and fixes to the optimizer
  1115. * some register allocation fixes
  1116. * some fpuvaroffset fixes in the unary minus node
  1117. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1118. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1119. also better optimizable)
  1120. * fixed and optimized register saving/restoring for new/dispose nodes
  1121. * LOC_FPU locations now also require their "register" field to be set to
  1122. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1123. - list field removed of the tnode class because it's not used currently
  1124. and can cause hard-to-find bugs
  1125. }