nflw.pas 42 KB

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