nflw.pas 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729
  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,symnot,
  25. symppu,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. tloopnode = class(tbinarynode)
  45. t1,t2 : tnode;
  46. loopflags : tloopflags;
  47. constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual;
  48. destructor destroy;override;
  49. function getcopy : tnode;override;
  50. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  51. procedure ppuwrite(ppufile:tcompilerppufile);override;
  52. procedure buildderefimpl;override;
  53. procedure derefimpl;override;
  54. procedure insertintolist(l : tnodelist);override;
  55. procedure printnodetree(var t:text);override;
  56. function docompare(p: tnode): boolean; override;
  57. end;
  58. twhilerepeatnode = class(tloopnode)
  59. constructor create(l,r,_t1:Tnode;tab,cn:boolean);virtual;
  60. function det_resulttype:tnode;override;
  61. function pass_1 : tnode;override;
  62. {$ifdef state_tracking}
  63. function track_state_pass(exec_known:boolean):boolean;override;
  64. {$endif}
  65. end;
  66. twhilerepeatnodeclass = class of twhilerepeatnode;
  67. tifnode = class(tloopnode)
  68. constructor create(l,r,_t1 : tnode);virtual;
  69. function det_resulttype:tnode;override;
  70. function pass_1 : tnode;override;
  71. end;
  72. tifnodeclass = class of tifnode;
  73. tfornode = class(tloopnode)
  74. loopvar_notid:cardinal;
  75. constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;
  76. procedure loop_var_access(not_type:Tnotification_flag;symbol:Tsym);
  77. function det_resulttype:tnode;override;
  78. function pass_1 : tnode;override;
  79. end;
  80. tfornodeclass = class of tfornode;
  81. texitnode = class(tunarynode)
  82. constructor create(l:tnode);virtual;
  83. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  84. procedure ppuwrite(ppufile:tcompilerppufile);override;
  85. function det_resulttype:tnode;override;
  86. function pass_1 : tnode;override;
  87. end;
  88. texitnodeclass = class of texitnode;
  89. tbreaknode = class(tnode)
  90. constructor create;virtual;
  91. function det_resulttype:tnode;override;
  92. function pass_1 : tnode;override;
  93. end;
  94. tbreaknodeclass = class of tbreaknode;
  95. tcontinuenode = class(tnode)
  96. constructor create;virtual;
  97. function det_resulttype:tnode;override;
  98. function pass_1 : tnode;override;
  99. end;
  100. tcontinuenodeclass = class of tcontinuenode;
  101. tgotonode = class(tnode)
  102. labsym : tlabelsym;
  103. labsymderef : tderef;
  104. exceptionblock : integer;
  105. { internlab : tinterngotolabel;}
  106. constructor create(p : tlabelsym);virtual;
  107. { constructor createintern(g:tinterngotolabel);}
  108. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  109. procedure ppuwrite(ppufile:tcompilerppufile);override;
  110. procedure buildderefimpl;override;
  111. procedure derefimpl;override;
  112. function getcopy : tnode;override;
  113. function det_resulttype:tnode;override;
  114. function pass_1 : tnode;override;
  115. function docompare(p: tnode): boolean; override;
  116. end;
  117. tgotonodeclass = class of tgotonode;
  118. tlabelnode = class(tunarynode)
  119. labelnr : tasmlabel;
  120. labsym : tlabelsym;
  121. labsymderef : tderef;
  122. exceptionblock : integer;
  123. constructor createcase(p : tasmlabel;l:tnode);virtual;
  124. constructor create(p : tlabelsym;l:tnode);virtual;
  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. tlabelnodeclass = class of tlabelnode;
  135. traisenode = class(tbinarynode)
  136. frametree : tnode;
  137. constructor create(l,taddr,tframe:tnode);virtual;
  138. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  139. procedure ppuwrite(ppufile:tcompilerppufile);override;
  140. procedure buildderefimpl;override;
  141. procedure derefimpl;override;
  142. function getcopy : tnode;override;
  143. procedure insertintolist(l : tnodelist);override;
  144. function det_resulttype:tnode;override;
  145. function pass_1 : tnode;override;
  146. function docompare(p: tnode): boolean; override;
  147. end;
  148. traisenodeclass = class of traisenode;
  149. ttryexceptnode = class(tloopnode)
  150. constructor create(l,r,_t1 : tnode);virtual;
  151. function det_resulttype:tnode;override;
  152. function pass_1 : tnode;override;
  153. end;
  154. ttryexceptnodeclass = class of ttryexceptnode;
  155. ttryfinallynode = class(tloopnode)
  156. implicitframe : boolean;
  157. constructor create(l,r:tnode);virtual;
  158. constructor create_implicit(l,r,_t1:tnode);virtual;
  159. function det_resulttype:tnode;override;
  160. function pass_1 : tnode;override;
  161. end;
  162. ttryfinallynodeclass = class of ttryfinallynode;
  163. tonnode = class(tbinarynode)
  164. exceptsymtable : tsymtable;
  165. excepttype : tobjectdef;
  166. constructor create(l,r:tnode);virtual;
  167. destructor destroy;override;
  168. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  169. function det_resulttype:tnode;override;
  170. function pass_1 : tnode;override;
  171. function getcopy : tnode;override;
  172. function docompare(p: tnode): boolean; override;
  173. end;
  174. tonnodeclass = class of tonnode;
  175. { for compatibilty }
  176. function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode;
  177. var
  178. cwhilerepeatnode : twhilerepeatnodeclass;
  179. cifnode : tifnodeclass;
  180. cfornode : tfornodeclass;
  181. cexitnode : texitnodeclass;
  182. cbreaknode : tbreaknodeclass;
  183. ccontinuenode : tcontinuenodeclass;
  184. cgotonode : tgotonodeclass;
  185. clabelnode : tlabelnodeclass;
  186. craisenode : traisenodeclass;
  187. ctryexceptnode : ttryexceptnodeclass;
  188. ctryfinallynode : ttryfinallynodeclass;
  189. connode : tonnodeclass;
  190. implementation
  191. uses
  192. globtype,systems,
  193. cutils,verbose,globals,
  194. symconst,paramgr,defcmp,defutil,htypechk,pass_1,
  195. ncal,nadd,ncon,nmem,nld,ncnv,nbas,cgobj,
  196. {$ifdef state_tracking}
  197. nstate,
  198. {$endif}
  199. cgbase,procinfo
  200. ;
  201. function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode;
  202. var
  203. p : tnode;
  204. begin
  205. case t of
  206. ifn:
  207. p:=cifnode.create(l,r,n1);
  208. whilerepeatn:
  209. if back then
  210. {Repeat until.}
  211. p:=cwhilerepeatnode.create(l,r,n1,false,true)
  212. else
  213. {While do.}
  214. p:=cwhilerepeatnode.create(l,r,n1,true,false);
  215. forn:
  216. p:=cfornode.create(l,r,n1,nil,back);
  217. end;
  218. resulttypepass(p);
  219. genloopnode:=p;
  220. end;
  221. {****************************************************************************
  222. TLOOPNODE
  223. *****************************************************************************}
  224. constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode);
  225. begin
  226. inherited create(tt,l,r);
  227. t1:=_t1;
  228. t2:=_t2;
  229. set_file_line(l);
  230. end;
  231. destructor tloopnode.destroy;
  232. begin
  233. t1.free;
  234. t2.free;
  235. inherited destroy;
  236. end;
  237. constructor tloopnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  238. begin
  239. inherited ppuload(t,ppufile);
  240. t1:=ppuloadnode(ppufile);
  241. t2:=ppuloadnode(ppufile);
  242. end;
  243. procedure tloopnode.ppuwrite(ppufile:tcompilerppufile);
  244. begin
  245. inherited ppuwrite(ppufile);
  246. ppuwritenode(ppufile,t1);
  247. ppuwritenode(ppufile,t2);
  248. end;
  249. procedure tloopnode.buildderefimpl;
  250. begin
  251. inherited buildderefimpl;
  252. if assigned(t1) then
  253. t1.buildderefimpl;
  254. if assigned(t2) then
  255. t2.buildderefimpl;
  256. end;
  257. procedure tloopnode.derefimpl;
  258. begin
  259. inherited derefimpl;
  260. if assigned(t1) then
  261. t1.derefimpl;
  262. if assigned(t2) then
  263. t2.derefimpl;
  264. end;
  265. function tloopnode.getcopy : tnode;
  266. var
  267. p : tloopnode;
  268. begin
  269. p:=tloopnode(inherited getcopy);
  270. if assigned(t1) then
  271. p.t1:=t1.getcopy
  272. else
  273. p.t1:=nil;
  274. if assigned(t2) then
  275. p.t2:=t2.getcopy
  276. else
  277. p.t2:=nil;
  278. getcopy:=p;
  279. end;
  280. procedure tloopnode.insertintolist(l : tnodelist);
  281. begin
  282. end;
  283. procedure tloopnode.printnodetree(var t:text);
  284. begin
  285. write(t,printnodeindention,'(');
  286. printnodeindent;
  287. printnodeinfo(t);
  288. printnode(t,left);
  289. printnode(t,right);
  290. printnode(t,t1);
  291. printnode(t,t2);
  292. printnodeunindent;
  293. writeln(t,printnodeindention,')');
  294. end;
  295. function tloopnode.docompare(p: tnode): boolean;
  296. begin
  297. docompare :=
  298. inherited docompare(p) and
  299. (loopflags*loopflagsequal=tloopnode(p).loopflags*loopflagsequal) and
  300. t1.isequal(tloopnode(p).t1) and
  301. t2.isequal(tloopnode(p).t2);
  302. end;
  303. {****************************************************************************
  304. TWHILEREPEATNODE
  305. *****************************************************************************}
  306. constructor Twhilerepeatnode.create(l,r,_t1:Tnode;tab,cn:boolean);
  307. begin
  308. inherited create(whilerepeatn,l,r,_t1,nil);
  309. if tab then
  310. include(loopflags, lnf_testatbegin);
  311. if cn then
  312. include(loopflags,lnf_checknegate);
  313. end;
  314. function twhilerepeatnode.det_resulttype:tnode;
  315. var
  316. t:Tunarynode;
  317. begin
  318. result:=nil;
  319. resulttype:=voidtype;
  320. resulttypepass(left);
  321. {A not node can be removed.}
  322. if left.nodetype=notn then
  323. begin
  324. t:=Tunarynode(left);
  325. left:=Tunarynode(left).left;
  326. t.left:=nil;
  327. t.destroy;
  328. {$ifdef Delphi}
  329. { How can this be handled in Delphi ? }
  330. RunError(255);
  331. {$else}
  332. {Symdif operator, in case you are wondering:}
  333. loopflags:=loopflags >< [lnf_checknegate];
  334. {$endif}
  335. end;
  336. { loop instruction }
  337. if assigned(right) then
  338. resulttypepass(right);
  339. set_varstate(left,vs_used,true);
  340. if codegenerror then
  341. exit;
  342. if not is_boolean(left.resulttype.def) then
  343. begin
  344. CGMessage(type_e_mismatch);
  345. exit;
  346. end;
  347. end;
  348. function twhilerepeatnode.pass_1 : tnode;
  349. var
  350. old_t_times : longint;
  351. begin
  352. result:=nil;
  353. expectloc:=LOC_VOID;
  354. old_t_times:=cg.t_times;
  355. { calc register weight }
  356. if not(cs_littlesize in aktglobalswitches ) then
  357. cg.t_times:=cg.t_times*8;
  358. firstpass(left);
  359. if codegenerror then
  360. exit;
  361. registers32:=left.registers32;
  362. registersfpu:=left.registersfpu;
  363. {$ifdef SUPPORT_MMX}
  364. registersmmx:=left.registersmmx;
  365. {$endif SUPPORT_MMX}
  366. { loop instruction }
  367. if assigned(right) then
  368. begin
  369. firstpass(right);
  370. if codegenerror then
  371. exit;
  372. if registers32<right.registers32 then
  373. registers32:=right.registers32;
  374. if registersfpu<right.registersfpu then
  375. registersfpu:=right.registersfpu;
  376. {$ifdef SUPPORT_MMX}
  377. if registersmmx<right.registersmmx then
  378. registersmmx:=right.registersmmx;
  379. {$endif SUPPORT_MMX}
  380. end;
  381. cg.t_times:=old_t_times;
  382. end;
  383. {$ifdef state_tracking}
  384. function Twhilerepeatnode.track_state_pass(exec_known:boolean):boolean;
  385. var condition:Tnode;
  386. code:Tnode;
  387. done:boolean;
  388. value:boolean;
  389. change:boolean;
  390. firsttest:boolean;
  391. factval:Tnode;
  392. begin
  393. track_state_pass:=false;
  394. done:=false;
  395. firsttest:=true;
  396. {For repeat until statements, first do a pass through the code.}
  397. if not(lnf_testatbegin in flags) then
  398. begin
  399. code:=right.getcopy;
  400. if code.track_state_pass(exec_known) then
  401. track_state_pass:=true;
  402. code.destroy;
  403. end;
  404. repeat
  405. condition:=left.getcopy;
  406. code:=right.getcopy;
  407. change:=condition.track_state_pass(exec_known);
  408. factval:=aktstate.find_fact(left);
  409. if factval<>nil then
  410. begin
  411. condition.destroy;
  412. condition:=factval.getcopy;
  413. change:=true;
  414. end;
  415. if change then
  416. begin
  417. track_state_pass:=true;
  418. {Force new resulttype pass.}
  419. condition.resulttype.def:=nil;
  420. do_resulttypepass(condition);
  421. end;
  422. if is_constboolnode(condition) then
  423. begin
  424. {Try to turn a while loop into a repeat loop.}
  425. if firsttest then
  426. exclude(flags,testatbegin);
  427. value:=(Tordconstnode(condition).value<>0) xor checknegate;
  428. if value then
  429. begin
  430. if code.track_state_pass(exec_known) then
  431. track_state_pass:=true;
  432. end
  433. else
  434. done:=true;
  435. end
  436. else
  437. begin
  438. {Remove any modified variables from the state.}
  439. code.track_state_pass(false);
  440. done:=true;
  441. end;
  442. code.destroy;
  443. condition.destroy;
  444. firsttest:=false;
  445. until done;
  446. {The loop condition is also known, for example:
  447. while i<10 do
  448. begin
  449. ...
  450. end;
  451. When the loop is done, we do know that i<10 = false.
  452. }
  453. condition:=left.getcopy;
  454. if condition.track_state_pass(exec_known) then
  455. begin
  456. track_state_pass:=true;
  457. {Force new resulttype pass.}
  458. condition.resulttype.def:=nil;
  459. do_resulttypepass(condition);
  460. end;
  461. if not is_constboolnode(condition) then
  462. aktstate.store_fact(condition,
  463. cordconstnode.create(byte(checknegate),booltype,true))
  464. else
  465. condition.destroy;
  466. end;
  467. {$endif}
  468. {*****************************************************************************
  469. TIFNODE
  470. *****************************************************************************}
  471. constructor tifnode.create(l,r,_t1 : tnode);
  472. begin
  473. inherited create(ifn,l,r,_t1,nil);
  474. end;
  475. function tifnode.det_resulttype:tnode;
  476. begin
  477. result:=nil;
  478. resulttype:=voidtype;
  479. resulttypepass(left);
  480. { if path }
  481. if assigned(right) then
  482. resulttypepass(right);
  483. { else path }
  484. if assigned(t1) then
  485. resulttypepass(t1);
  486. set_varstate(left,vs_used,true);
  487. if codegenerror then
  488. exit;
  489. if not is_boolean(left.resulttype.def) then
  490. Message1(type_e_boolean_expr_expected,left.resulttype.def.typename);
  491. end;
  492. function tifnode.pass_1 : tnode;
  493. var
  494. old_t_times : longint;
  495. hp : tnode;
  496. begin
  497. result:=nil;
  498. expectloc:=LOC_VOID;
  499. old_t_times:=cg.t_times;
  500. firstpass(left);
  501. registers32:=left.registers32;
  502. registersfpu:=left.registersfpu;
  503. {$ifdef SUPPORT_MMX}
  504. registersmmx:=left.registersmmx;
  505. {$endif SUPPORT_MMX}
  506. { determines registers weigths }
  507. if not(cs_littlesize in aktglobalswitches) then
  508. cg.t_times:=cg.t_times div 2;
  509. if cg.t_times=0 then
  510. cg.t_times:=1;
  511. { if path }
  512. if assigned(right) then
  513. begin
  514. firstpass(right);
  515. if registers32<right.registers32 then
  516. registers32:=right.registers32;
  517. if registersfpu<right.registersfpu then
  518. registersfpu:=right.registersfpu;
  519. {$ifdef SUPPORT_MMX}
  520. if registersmmx<right.registersmmx then
  521. registersmmx:=right.registersmmx;
  522. {$endif SUPPORT_MMX}
  523. end;
  524. { else path }
  525. if assigned(t1) then
  526. begin
  527. firstpass(t1);
  528. if registers32<t1.registers32 then
  529. registers32:=t1.registers32;
  530. if registersfpu<t1.registersfpu then
  531. registersfpu:=t1.registersfpu;
  532. {$ifdef SUPPORT_MMX}
  533. if registersmmx<t1.registersmmx then
  534. registersmmx:=t1.registersmmx;
  535. {$endif SUPPORT_MMX}
  536. end;
  537. { leave if we've got an error in one of the paths }
  538. if codegenerror then
  539. exit;
  540. if left.nodetype=ordconstn then
  541. begin
  542. { optimize }
  543. if tordconstnode(left).value=1 then
  544. begin
  545. hp:=right;
  546. right:=nil;
  547. { we cannot set p to nil !!! }
  548. if assigned(hp) then
  549. result:=hp
  550. else
  551. result:=cnothingnode.create;
  552. end
  553. else
  554. begin
  555. hp:=t1;
  556. t1:=nil;
  557. { we cannot set p to nil !!! }
  558. if assigned(hp) then
  559. result:=hp
  560. else
  561. result:=cnothingnode.create;
  562. end;
  563. end;
  564. cg.t_times:=old_t_times;
  565. end;
  566. {*****************************************************************************
  567. TFORNODE
  568. *****************************************************************************}
  569. constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
  570. begin
  571. inherited create(forn,l,r,_t1,_t2);
  572. if back then
  573. include(loopflags,lnf_backward);
  574. include(loopflags,lnf_testatbegin);
  575. end;
  576. procedure Tfornode.loop_var_access(not_type:Tnotification_flag;
  577. symbol:Tsym);
  578. begin
  579. {If there is a read access, the value of the loop counter is important;
  580. at the end of the loop the loop variable should contain the value it
  581. had in the last iteration.}
  582. if not_type=vn_onwrite then
  583. begin
  584. writeln('Loopvar does not matter on exit');
  585. end
  586. else
  587. begin
  588. exclude(loopflags,lnf_dont_mind_loopvar_on_exit);
  589. writeln('Loopvar does matter on exit');
  590. end;
  591. Tvarsym(symbol).unregister_notification(loopvar_notid);
  592. end;
  593. function tfornode.det_resulttype:tnode;
  594. var
  595. hp : tnode;
  596. begin
  597. result:=nil;
  598. resulttype:=voidtype;
  599. if left.nodetype<>assignn then
  600. begin
  601. CGMessage(cg_e_illegal_expression);
  602. exit;
  603. end;
  604. {Can we spare the first comparision?}
  605. if (right.nodetype=ordconstn) and (Tassignmentnode(left).right.nodetype=ordconstn) then
  606. if (
  607. (lnf_backward in loopflags) and
  608. (Tordconstnode(Tassignmentnode(left).right).value>=Tordconstnode(right).value)
  609. )
  610. or not(
  611. (lnf_backward in loopflags) and
  612. (Tordconstnode(Tassignmentnode(left).right).value<=Tordconstnode(right).value)
  613. ) then
  614. exclude(loopflags,lnf_testatbegin);
  615. { save counter var }
  616. t2:=tassignmentnode(left).left.getcopy;
  617. resulttypepass(left);
  618. set_varstate(left,vs_used,true);
  619. if assigned(t1) then
  620. begin
  621. resulttypepass(t1);
  622. if codegenerror then
  623. exit;
  624. end;
  625. { process count var }
  626. resulttypepass(t2);
  627. set_varstate(t2,vs_used,false);
  628. if codegenerror then
  629. exit;
  630. { Check count var, record fields are also allowed in tp7 }
  631. hp:=t2;
  632. while (hp.nodetype=subscriptn) or
  633. ((hp.nodetype=vecn) and
  634. is_constintnode(tvecnode(hp).right)) or
  635. ((hp.nodetype=typeconvn) and
  636. (ttypeconvnode(hp).convtype=tc_equal)) do
  637. hp:=tunarynode(hp).left;
  638. { we need a simple loadn, but the load must be in a global symtable or
  639. in the same level as the para of the current proc }
  640. if (
  641. (hp.nodetype=loadn) and
  642. (
  643. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  644. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  645. ) and
  646. not(
  647. (tloadnode(hp).symtableentry.typ=varsym) and
  648. ((tvarsym(tloadnode(hp).symtableentry).varspez in [vs_var,vs_out]) or
  649. (vo_is_thread_var in tvarsym(tloadnode(hp).symtableentry).varoptions))
  650. )
  651. ) then
  652. begin
  653. if (hp.nodetype=loadn) and
  654. (tloadnode(hp).symtableentry.typ=varsym) then
  655. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_used;
  656. if not(is_ordinal(t2.resulttype.def))
  657. {$ifndef cpu64bit}
  658. or is_64bitint(t2.resulttype.def)
  659. {$endif cpu64bit}
  660. then
  661. CGMessagePos(hp.fileinfo,type_e_ordinal_expr_expected);
  662. end
  663. else
  664. CGMessagePos(hp.fileinfo,cg_e_illegal_count_var);
  665. resulttypepass(right);
  666. set_varstate(right,vs_used,true);
  667. inserttypeconv(right,t2.resulttype);
  668. end;
  669. function tfornode.pass_1 : tnode;
  670. var
  671. old_t_times : longint;
  672. {$ifdef loopvar_dont_mind}
  673. hp : Tnode;
  674. {$endif loopvar_dont_mind}
  675. begin
  676. result:=nil;
  677. expectloc:=LOC_VOID;
  678. { Calc register weight }
  679. old_t_times:=cg.t_times;
  680. if not(cs_littlesize in aktglobalswitches) then
  681. cg.t_times:=cg.t_times*8;
  682. firstpass(left);
  683. if assigned(t1) then
  684. begin
  685. firstpass(t1);
  686. if codegenerror then
  687. exit;
  688. end;
  689. registers32:=t1.registers32;
  690. registersfpu:=t1.registersfpu;
  691. {$ifdef SUPPORT_MMX}
  692. registersmmx:=left.registersmmx;
  693. {$endif SUPPORT_MMX}
  694. if left.registers32>registers32 then
  695. registers32:=left.registers32;
  696. if left.registersfpu>registersfpu then
  697. registersfpu:=left.registersfpu;
  698. {$ifdef SUPPORT_MMX}
  699. if left.registersmmx>registersmmx then
  700. registersmmx:=left.registersmmx;
  701. {$endif SUPPORT_MMX}
  702. { process count var }
  703. firstpass(t2);
  704. if codegenerror then
  705. exit;
  706. if t2.registers32>registers32 then
  707. registers32:=t2.registers32;
  708. if t2.registersfpu>registersfpu then
  709. registersfpu:=t2.registersfpu;
  710. {$ifdef SUPPORT_MMX}
  711. if t2.registersmmx>registersmmx then
  712. registersmmx:=t2.registersmmx;
  713. {$endif SUPPORT_MMX}
  714. firstpass(right);
  715. {$ifdef loopvar_dont_mind}
  716. { Check count var, record fields are also allowed in tp7 }
  717. include(loopflags,lnf_dont_mind_loopvar_on_exit);
  718. hp:=t2;
  719. while (hp.nodetype=subscriptn) or
  720. ((hp.nodetype=vecn) and
  721. is_constintnode(tvecnode(hp).right)) do
  722. hp:=tunarynode(hp).left;
  723. if (hp.nodetype=loadn) and (Tloadnode(hp).symtableentry.typ=varsym) then
  724. loopvar_notid:=Tvarsym(Tloadnode(hp).symtableentry).
  725. register_notification([vn_onread,vn_onwrite],@loop_var_access);
  726. {$endif}
  727. if right.registers32>registers32 then
  728. registers32:=right.registers32;
  729. if right.registersfpu>registersfpu then
  730. registersfpu:=right.registersfpu;
  731. {$ifdef SUPPORT_MMX}
  732. if right.registersmmx>registersmmx then
  733. registersmmx:=right.registersmmx;
  734. {$endif SUPPORT_MMX}
  735. { we need at least one register for comparisons PM }
  736. if registers32=0 then
  737. inc(registers32);
  738. cg.t_times:=old_t_times;
  739. end;
  740. {*****************************************************************************
  741. TEXITNODE
  742. *****************************************************************************}
  743. constructor texitnode.create(l:tnode);
  744. begin
  745. inherited create(exitn,l);
  746. end;
  747. constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  748. begin
  749. inherited ppuload(t,ppufile);
  750. end;
  751. procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
  752. begin
  753. inherited ppuwrite(ppufile);
  754. end;
  755. function texitnode.det_resulttype:tnode;
  756. begin
  757. result:=nil;
  758. if assigned(left) then
  759. begin
  760. { add assignment to funcretsym }
  761. inserttypeconv(left,current_procinfo.procdef.rettype);
  762. left:=cassignmentnode.create(
  763. cloadnode.create(current_procinfo.procdef.funcretsym,current_procinfo.procdef.funcretsym.owner),
  764. left);
  765. resulttypepass(left);
  766. set_varstate(left,vs_used,true);
  767. end;
  768. resulttype:=voidtype;
  769. end;
  770. function texitnode.pass_1 : tnode;
  771. begin
  772. result:=nil;
  773. expectloc:=LOC_VOID;
  774. if assigned(left) then
  775. begin
  776. firstpass(left);
  777. if codegenerror then
  778. exit;
  779. registers32:=left.registers32;
  780. registersfpu:=left.registersfpu;
  781. {$ifdef SUPPORT_MMX}
  782. registersmmx:=left.registersmmx;
  783. {$endif SUPPORT_MMX}
  784. end;
  785. end;
  786. {*****************************************************************************
  787. TBREAKNODE
  788. *****************************************************************************}
  789. constructor tbreaknode.create;
  790. begin
  791. inherited create(breakn);
  792. end;
  793. function tbreaknode.det_resulttype:tnode;
  794. begin
  795. result:=nil;
  796. resulttype:=voidtype;
  797. end;
  798. function tbreaknode.pass_1 : tnode;
  799. begin
  800. result:=nil;
  801. expectloc:=LOC_VOID;
  802. end;
  803. {*****************************************************************************
  804. TCONTINUENODE
  805. *****************************************************************************}
  806. constructor tcontinuenode.create;
  807. begin
  808. inherited create(continuen);
  809. end;
  810. function tcontinuenode.det_resulttype:tnode;
  811. begin
  812. result:=nil;
  813. resulttype:=voidtype;
  814. end;
  815. function tcontinuenode.pass_1 : tnode;
  816. begin
  817. result:=nil;
  818. expectloc:=LOC_VOID;
  819. end;
  820. {*****************************************************************************
  821. TGOTONODE
  822. *****************************************************************************}
  823. constructor tgotonode.create(p : tlabelsym);
  824. begin
  825. inherited create(goton);
  826. exceptionblock:=aktexceptblock;
  827. labsym:=p;
  828. end;
  829. constructor tgotonode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  830. begin
  831. inherited ppuload(t,ppufile);
  832. ppufile.getderef(labsymderef);
  833. exceptionblock:=ppufile.getbyte;
  834. end;
  835. procedure tgotonode.ppuwrite(ppufile:tcompilerppufile);
  836. begin
  837. inherited ppuwrite(ppufile);
  838. ppufile.putderef(labsymderef);
  839. ppufile.putbyte(exceptionblock);
  840. end;
  841. procedure tgotonode.buildderefimpl;
  842. begin
  843. inherited buildderefimpl;
  844. labsymderef.build(labsym);
  845. end;
  846. procedure tgotonode.derefimpl;
  847. begin
  848. inherited derefimpl;
  849. labsym:=tlabelsym(labsymderef.resolve);
  850. end;
  851. function tgotonode.det_resulttype:tnode;
  852. begin
  853. result:=nil;
  854. resulttype:=voidtype;
  855. end;
  856. function tgotonode.pass_1 : tnode;
  857. begin
  858. result:=nil;
  859. expectloc:=LOC_VOID;
  860. { check if }
  861. if assigned(labsym) and
  862. assigned(labsym.code) and
  863. (exceptionblock<>tlabelnode(labsym.code).exceptionblock) then
  864. begin
  865. writeln('goto exceptblock: ',exceptionblock);
  866. writeln('label exceptblock: ',tlabelnode(labsym.code).exceptionblock);
  867. CGMessage(cg_e_goto_inout_of_exception_block);
  868. end;
  869. end;
  870. function tgotonode.getcopy : tnode;
  871. var
  872. p : tgotonode;
  873. begin
  874. p:=tgotonode(inherited getcopy);
  875. p.labsym:=labsym;
  876. p.exceptionblock:=exceptionblock;
  877. result:=p;
  878. end;
  879. function tgotonode.docompare(p: tnode): boolean;
  880. begin
  881. docompare := false;
  882. end;
  883. {*****************************************************************************
  884. TLABELNODE
  885. *****************************************************************************}
  886. constructor tlabelnode.createcase(p : tasmlabel;l:tnode);
  887. begin
  888. inherited create(labeln,l);
  889. { it shouldn't be possible to jump to case labels using goto }
  890. exceptionblock:=-1;
  891. labsym:=nil;
  892. labelnr:=p;
  893. end;
  894. constructor tlabelnode.create(p : tlabelsym;l:tnode);
  895. begin
  896. inherited create(labeln,l);
  897. exceptionblock:=aktexceptblock;
  898. labsym:=p;
  899. labelnr:=p.lab;
  900. { save the current labelnode in the labelsym }
  901. p.code:=self;
  902. end;
  903. constructor tlabelnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  904. begin
  905. inherited ppuload(t,ppufile);
  906. ppufile.getderef(labsymderef);
  907. labelnr:=tasmlabel(ppufile.getasmsymbol);
  908. exceptionblock:=ppufile.getbyte;
  909. end;
  910. procedure tlabelnode.ppuwrite(ppufile:tcompilerppufile);
  911. begin
  912. inherited ppuwrite(ppufile);
  913. ppufile.putderef(labsymderef);
  914. ppufile.putasmsymbol(labelnr);
  915. ppufile.putbyte(exceptionblock);
  916. end;
  917. procedure tlabelnode.buildderefimpl;
  918. begin
  919. inherited buildderefimpl;
  920. labsymderef.build(labsym);
  921. end;
  922. procedure tlabelnode.derefimpl;
  923. begin
  924. inherited derefimpl;
  925. labsym:=tlabelsym(labsymderef.resolve);
  926. objectlibrary.derefasmsymbol(tasmsymbol(labelnr));
  927. end;
  928. function tlabelnode.det_resulttype:tnode;
  929. begin
  930. result:=nil;
  931. { left could still be unassigned }
  932. if assigned(left) then
  933. resulttypepass(left);
  934. resulttype:=voidtype;
  935. end;
  936. function tlabelnode.pass_1 : tnode;
  937. begin
  938. result:=nil;
  939. expectloc:=LOC_VOID;
  940. if assigned(left) then
  941. begin
  942. firstpass(left);
  943. registers32:=left.registers32;
  944. registersfpu:=left.registersfpu;
  945. {$ifdef SUPPORT_MMX}
  946. registersmmx:=left.registersmmx;
  947. {$endif SUPPORT_MMX}
  948. end;
  949. end;
  950. function tlabelnode.getcopy : tnode;
  951. var
  952. p : tlabelnode;
  953. begin
  954. p:=tlabelnode(inherited getcopy);
  955. p.labelnr:=labelnr;
  956. p.exceptionblock:=exceptionblock;
  957. p.labsym:=labsym;
  958. result:=p;
  959. end;
  960. function tlabelnode.docompare(p: tnode): boolean;
  961. begin
  962. docompare := false;
  963. end;
  964. {*****************************************************************************
  965. TRAISENODE
  966. *****************************************************************************}
  967. constructor traisenode.create(l,taddr,tframe:tnode);
  968. begin
  969. inherited create(raisen,l,taddr);
  970. frametree:=tframe;
  971. end;
  972. constructor traisenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  973. begin
  974. inherited ppuload(t,ppufile);
  975. frametree:=ppuloadnode(ppufile);
  976. end;
  977. procedure traisenode.ppuwrite(ppufile:tcompilerppufile);
  978. begin
  979. inherited ppuwrite(ppufile);
  980. ppuwritenode(ppufile,frametree);
  981. end;
  982. procedure traisenode.buildderefimpl;
  983. begin
  984. inherited buildderefimpl;
  985. if assigned(frametree) then
  986. frametree.buildderefimpl;
  987. end;
  988. procedure traisenode.derefimpl;
  989. begin
  990. inherited derefimpl;
  991. if assigned(frametree) then
  992. frametree.derefimpl;
  993. end;
  994. function traisenode.getcopy : tnode;
  995. var
  996. n : traisenode;
  997. begin
  998. n:=traisenode(inherited getcopy);
  999. if assigned(frametree) then
  1000. n.frametree:=frametree.getcopy
  1001. else
  1002. n.frametree:=nil;
  1003. getcopy:=n;
  1004. end;
  1005. procedure traisenode.insertintolist(l : tnodelist);
  1006. begin
  1007. end;
  1008. function traisenode.det_resulttype:tnode;
  1009. begin
  1010. result:=nil;
  1011. resulttype:=voidtype;
  1012. if assigned(left) then
  1013. begin
  1014. { first para must be a _class_ }
  1015. resulttypepass(left);
  1016. set_varstate(left,vs_used,true);
  1017. if codegenerror then
  1018. exit;
  1019. if not(is_class(left.resulttype.def)) then
  1020. CGMessage(type_e_mismatch);
  1021. { insert needed typeconvs for addr,frame }
  1022. if assigned(right) then
  1023. begin
  1024. { addr }
  1025. resulttypepass(right);
  1026. inserttypeconv(right,voidpointertype);
  1027. { frame }
  1028. if assigned(frametree) then
  1029. begin
  1030. resulttypepass(frametree);
  1031. inserttypeconv(frametree,voidpointertype);
  1032. end;
  1033. end;
  1034. end;
  1035. end;
  1036. function traisenode.pass_1 : tnode;
  1037. begin
  1038. result:=nil;
  1039. include(current_procinfo.flags,pi_do_call);
  1040. expectloc:=LOC_VOID;
  1041. if assigned(left) then
  1042. begin
  1043. { first para must be a _class_ }
  1044. firstpass(left);
  1045. { insert needed typeconvs for addr,frame }
  1046. if assigned(right) then
  1047. begin
  1048. { addr }
  1049. firstpass(right);
  1050. { frame }
  1051. if assigned(frametree) then
  1052. firstpass(frametree);
  1053. end;
  1054. left_right_max;
  1055. end;
  1056. end;
  1057. function traisenode.docompare(p: tnode): boolean;
  1058. begin
  1059. docompare := false;
  1060. end;
  1061. {*****************************************************************************
  1062. TTRYEXCEPTNODE
  1063. *****************************************************************************}
  1064. constructor ttryexceptnode.create(l,r,_t1 : tnode);
  1065. begin
  1066. inherited create(tryexceptn,l,r,_t1,nil);
  1067. end;
  1068. function ttryexceptnode.det_resulttype:tnode;
  1069. begin
  1070. result:=nil;
  1071. resulttypepass(left);
  1072. { on statements }
  1073. if assigned(right) then
  1074. resulttypepass(right);
  1075. { else block }
  1076. if assigned(t1) then
  1077. resulttypepass(t1);
  1078. resulttype:=voidtype;
  1079. end;
  1080. function ttryexceptnode.pass_1 : tnode;
  1081. begin
  1082. result:=nil;
  1083. expectloc:=LOC_VOID;
  1084. firstpass(left);
  1085. { on statements }
  1086. if assigned(right) then
  1087. begin
  1088. firstpass(right);
  1089. registers32:=max(registers32,right.registers32);
  1090. registersfpu:=max(registersfpu,right.registersfpu);
  1091. {$ifdef SUPPORT_MMX}
  1092. registersmmx:=max(registersmmx,right.registersmmx);
  1093. {$endif SUPPORT_MMX}
  1094. end;
  1095. { else block }
  1096. if assigned(t1) then
  1097. begin
  1098. firstpass(t1);
  1099. registers32:=max(registers32,t1.registers32);
  1100. registersfpu:=max(registersfpu,t1.registersfpu);
  1101. {$ifdef SUPPORT_MMX}
  1102. registersmmx:=max(registersmmx,t1.registersmmx);
  1103. {$endif SUPPORT_MMX}
  1104. end;
  1105. end;
  1106. {*****************************************************************************
  1107. TTRYFINALLYNODE
  1108. *****************************************************************************}
  1109. constructor ttryfinallynode.create(l,r:tnode);
  1110. begin
  1111. inherited create(tryfinallyn,l,r,nil,nil);
  1112. implicitframe:=false;
  1113. end;
  1114. constructor ttryfinallynode.create_implicit(l,r,_t1:tnode);
  1115. begin
  1116. inherited create(tryfinallyn,l,r,_t1,nil);
  1117. implicitframe:=true;
  1118. end;
  1119. function ttryfinallynode.det_resulttype:tnode;
  1120. begin
  1121. result:=nil;
  1122. resulttype:=voidtype;
  1123. resulttypepass(left);
  1124. set_varstate(left,vs_used,true);
  1125. resulttypepass(right);
  1126. set_varstate(right,vs_used,true);
  1127. { special finally block only executed when there was an exception }
  1128. if assigned(t1) then
  1129. begin
  1130. resulttypepass(t1);
  1131. set_varstate(t1,vs_used,true);
  1132. end;
  1133. end;
  1134. function ttryfinallynode.pass_1 : tnode;
  1135. begin
  1136. result:=nil;
  1137. expectloc:=LOC_VOID;
  1138. firstpass(left);
  1139. firstpass(right);
  1140. left_right_max;
  1141. if assigned(t1) then
  1142. begin
  1143. firstpass(t1);
  1144. registers32:=max(registers32,t1.registers32);
  1145. registersfpu:=max(registersfpu,t1.registersfpu);
  1146. {$ifdef SUPPORT_MMX}
  1147. registersmmx:=max(registersmmx,t1.registersmmx);
  1148. {$endif SUPPORT_MMX}
  1149. end;
  1150. end;
  1151. {*****************************************************************************
  1152. TONNODE
  1153. *****************************************************************************}
  1154. constructor tonnode.create(l,r:tnode);
  1155. begin
  1156. inherited create(onn,l,r);
  1157. exceptsymtable:=nil;
  1158. excepttype:=nil;
  1159. end;
  1160. destructor tonnode.destroy;
  1161. begin
  1162. { copied nodes don't need to release the symtable }
  1163. if assigned(exceptsymtable) then
  1164. exceptsymtable.free;
  1165. inherited destroy;
  1166. end;
  1167. constructor tonnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  1168. begin
  1169. inherited ppuload(t,ppufile);
  1170. exceptsymtable:=nil;
  1171. excepttype:=nil;
  1172. end;
  1173. function tonnode.getcopy : tnode;
  1174. var
  1175. n : tonnode;
  1176. begin
  1177. n:=tonnode(inherited getcopy);
  1178. n.exceptsymtable:=exceptsymtable.getcopy;
  1179. n.excepttype:=excepttype;
  1180. result:=n;
  1181. end;
  1182. function tonnode.det_resulttype:tnode;
  1183. begin
  1184. result:=nil;
  1185. resulttype:=voidtype;
  1186. if not(is_class(excepttype)) then
  1187. CGMessage(type_e_mismatch);
  1188. if assigned(left) then
  1189. resulttypepass(left);
  1190. if assigned(right) then
  1191. resulttypepass(right);
  1192. end;
  1193. function tonnode.pass_1 : tnode;
  1194. begin
  1195. result:=nil;
  1196. expectloc:=LOC_VOID;
  1197. registers32:=0;
  1198. registersfpu:=0;
  1199. {$ifdef SUPPORT_MMX}
  1200. registersmmx:=0;
  1201. {$endif SUPPORT_MMX}
  1202. if assigned(left) then
  1203. begin
  1204. firstpass(left);
  1205. registers32:=left.registers32;
  1206. registersfpu:=left.registersfpu;
  1207. {$ifdef SUPPORT_MMX}
  1208. registersmmx:=left.registersmmx;
  1209. {$endif SUPPORT_MMX}
  1210. end;
  1211. if assigned(right) then
  1212. begin
  1213. firstpass(right);
  1214. registers32:=max(registers32,right.registers32);
  1215. registersfpu:=max(registersfpu,right.registersfpu);
  1216. {$ifdef SUPPORT_MMX}
  1217. registersmmx:=max(registersmmx,right.registersmmx);
  1218. {$endif SUPPORT_MMX}
  1219. end;
  1220. end;
  1221. function tonnode.docompare(p: tnode): boolean;
  1222. begin
  1223. docompare := false;
  1224. end;
  1225. begin
  1226. cwhilerepeatnode:=twhilerepeatnode;
  1227. cifnode:=tifnode;
  1228. cfornode:=tfornode;
  1229. cexitnode:=texitnode;
  1230. cgotonode:=tgotonode;
  1231. clabelnode:=tlabelnode;
  1232. craisenode:=traisenode;
  1233. ctryexceptnode:=ttryexceptnode;
  1234. ctryfinallynode:=ttryfinallynode;
  1235. connode:=tonnode;
  1236. end.
  1237. {
  1238. $Log$
  1239. Revision 1.89 2003-12-01 18:44:15 peter
  1240. * fixed some crashes
  1241. * fixed varargs and register calling probs
  1242. Revision 1.88 2003/11/23 17:39:16 peter
  1243. * don't release exceptsymtable for copied nodes
  1244. Revision 1.87 2003/11/12 15:48:27 peter
  1245. * fix set_varstate in for loops
  1246. * fix set_varstate from case statements
  1247. Revision 1.86 2003/10/28 15:36:01 peter
  1248. * absolute to object field supported, fixes tb0458
  1249. Revision 1.85 2003/10/23 14:44:07 peter
  1250. * splitted buildderef and buildderefimpl to fix interface crc
  1251. calculation
  1252. Revision 1.84 2003/10/22 20:40:00 peter
  1253. * write derefdata in a separate ppu entry
  1254. Revision 1.83 2003/10/09 21:31:37 daniel
  1255. * Register allocator splitted, ans abstract now
  1256. Revision 1.82 2003/10/08 19:19:45 peter
  1257. * set_varstate cleanup
  1258. Revision 1.81 2003/10/05 11:53:57 florian
  1259. * writing of loop nodes fixed
  1260. Revision 1.80 2003/10/01 20:34:48 peter
  1261. * procinfo unit contains tprocinfo
  1262. * cginfo renamed to cgbase
  1263. * moved cgmessage to verbose
  1264. * fixed ppc and sparc compiles
  1265. Revision 1.79 2003/07/06 15:31:20 daniel
  1266. * Fixed register allocator. *Lots* of fixes.
  1267. Revision 1.78 2003/06/13 21:19:30 peter
  1268. * current_procdef removed, use current_procinfo.procdef instead
  1269. Revision 1.77 2003/06/07 20:26:32 peter
  1270. * re-resolving added instead of reloading from ppu
  1271. * tderef object added to store deref info for resolving
  1272. Revision 1.76 2003/06/07 18:57:04 jonas
  1273. + added freeintparaloc
  1274. * ppc get/freeintparaloc now check whether the parameter regs are
  1275. properly allocated/deallocated (and get an extra list para)
  1276. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  1277. * fixed lot of missing pi_do_call's
  1278. Revision 1.75 2003/05/26 21:17:17 peter
  1279. * procinlinenode removed
  1280. * aktexit2label removed, fast exit removed
  1281. + tcallnode.inlined_pass_2 added
  1282. Revision 1.74 2003/05/13 19:14:41 peter
  1283. * failn removed
  1284. * inherited result code check moven to pexpr
  1285. Revision 1.73 2003/05/11 21:37:03 peter
  1286. * moved implicit exception frame from ncgutil to psub
  1287. * constructor/destructor helpers moved from cobj/ncgutil to psub
  1288. Revision 1.72 2003/05/01 07:59:42 florian
  1289. * introduced defaultordconsttype to decribe the default size of ordinal constants
  1290. on 64 bit CPUs it's equal to cs64bitdef while on 32 bit CPUs it's equal to s32bitdef
  1291. + added defines CPU32 and CPU64 for 32 bit and 64 bit CPUs
  1292. * int64s/qwords are allowed as for loop counter on 64 bit CPUs
  1293. Revision 1.71 2003/04/27 11:21:33 peter
  1294. * aktprocdef renamed to current_procinfo.procdef
  1295. * procinfo renamed to current_procinfo
  1296. * procinfo will now be stored in current_module so it can be
  1297. cleaned up properly
  1298. * gen_main_procsym changed to create_main_proc and release_main_proc
  1299. to also generate a tprocinfo structure
  1300. * fixed unit implicit initfinal
  1301. Revision 1.70 2003/04/27 07:29:50 peter
  1302. * current_procinfo.procdef cleanup, current_procdef is now always nil when parsing
  1303. a new procdef declaration
  1304. * aktprocsym removed
  1305. * lexlevel removed, use symtable.symtablelevel instead
  1306. * implicit init/final code uses the normal genentry/genexit
  1307. * funcret state checking updated for new funcret handling
  1308. Revision 1.69 2003/04/26 00:28:41 peter
  1309. * removed load_funcret
  1310. Revision 1.68 2003/04/25 20:59:33 peter
  1311. * removed funcretn,funcretsym, function result is now in varsym
  1312. and aliases for result and function name are added using absolutesym
  1313. * vs_hidden parameter for funcret passed in parameter
  1314. * vs_hidden fixes
  1315. * writenode changed to printnode and released from extdebug
  1316. * -vp option added to generate a tree.log with the nodetree
  1317. * nicer printnode for statements, callnode
  1318. Revision 1.67 2003/04/25 08:25:26 daniel
  1319. * Ifdefs around a lot of calls to cleartempgen
  1320. * Fixed registers that are allocated but not freed in several nodes
  1321. * Tweak to register allocator to cause less spills
  1322. * 8-bit registers now interfere with esi,edi and ebp
  1323. Compiler can now compile rtl successfully when using new register
  1324. allocator
  1325. Revision 1.66 2003/04/22 23:50:23 peter
  1326. * firstpass uses expectloc
  1327. * checks if there are differences between the expectloc and
  1328. location.loc from secondpass in EXTDEBUG
  1329. Revision 1.65 2003/03/20 15:54:46 peter
  1330. * don't allow var and out parameters as for loop counter
  1331. Revision 1.64 2003/01/09 21:52:37 peter
  1332. * merged some verbosity options.
  1333. * V_LineInfo is a verbosity flag to include line info
  1334. Revision 1.63 2003/01/04 08:08:47 daniel
  1335. * Readded missing variable
  1336. Revision 1.62 2003/01/03 17:16:57 peter
  1337. * fixed warning about unset funcret
  1338. Revision 1.61 2003/01/03 12:15:56 daniel
  1339. * Removed ifdefs around notifications
  1340. ifdefs around for loop optimizations remain
  1341. Revision 1.60 2002/12/31 09:55:58 daniel
  1342. + Notification implementation complete
  1343. + Add for loop code optimization using notifications
  1344. results in 1.5-1.9% speed improvement in nestloop benchmark
  1345. Optimization incomplete, compiler does not cycle yet with
  1346. notifications enabled.
  1347. Revision 1.59 2002/12/30 22:44:53 daniel
  1348. * Some work on notifications
  1349. Revision 1.58 2002/12/27 15:25:40 peter
  1350. * do not allow threadvar as loop counter
  1351. Revision 1.57 2002/11/28 11:17:02 florian
  1352. * loop node flags from node flags splitted
  1353. Revision 1.56 2002/11/25 17:43:18 peter
  1354. * splitted defbase in defutil,symutil,defcmp
  1355. * merged isconvertable and is_equal into compare_defs(_ext)
  1356. * made operator search faster by walking the list only once
  1357. Revision 1.55 2002/11/18 17:31:56 peter
  1358. * pass proccalloption to ret_in_xxx and push_xxx functions
  1359. Revision 1.54 2002/10/20 15:31:49 peter
  1360. * set funcret state for exit(0)
  1361. Revision 1.53 2002/10/05 12:43:25 carl
  1362. * fixes for Delphi 6 compilation
  1363. (warning : Some features do not work under Delphi)
  1364. Revision 1.52 2002/09/07 15:25:03 peter
  1365. * old logs removed and tabs fixed
  1366. Revision 1.51 2002/09/07 12:16:04 carl
  1367. * second part bug report 1996 fix, testrange in cordconstnode
  1368. only called if option is set (also make parsing a tiny faster)
  1369. Revision 1.50 2002/09/01 18:47:00 peter
  1370. * assignn check in exitnode changed to use a separate boolean as the
  1371. assignn can be changed to a calln
  1372. Revision 1.49 2002/09/01 08:01:16 daniel
  1373. * Removed sets from Tcallnode.det_resulttype
  1374. + Added read/write notifications of variables. These will be usefull
  1375. for providing information for several optimizations. For example
  1376. the value of the loop variable of a for loop does matter is the
  1377. variable is read after the for loop, but if it's no longer used
  1378. or written, it doesn't matter and this can be used to optimize
  1379. the loop code generation.
  1380. Revision 1.48 2002/08/22 15:15:20 daniel
  1381. * Fixed the detection wether the first check of a for loop can be skipped
  1382. Revision 1.47 2002/08/19 19:36:43 peter
  1383. * More fixes for cross unit inlining, all tnodes are now implemented
  1384. * Moved pocall_internconst to po_internconst because it is not a
  1385. calling type at all and it conflicted when inlining of these small
  1386. functions was requested
  1387. Revision 1.46 2002/08/17 22:09:46 florian
  1388. * result type handling in tcgcal.pass_2 overhauled
  1389. * better tnode.dowrite
  1390. * some ppc stuff fixed
  1391. Revision 1.45 2002/08/17 09:23:37 florian
  1392. * first part of current_procinfo rewrite
  1393. Revision 1.44 2002/07/21 06:58:49 daniel
  1394. * Changed booleans into flags
  1395. Revision 1.43 2002/07/20 11:57:54 florian
  1396. * types.pas renamed to defbase.pas because D6 contains a types
  1397. unit so this would conflicts if D6 programms are compiled
  1398. + Willamette/SSE2 instructions to assembler added
  1399. Revision 1.42 2002/07/20 11:18:18 daniel
  1400. * Small mistake fixed; the skip test was done before we know the for node
  1401. is correct.
  1402. Revision 1.40 2002/07/20 08:19:31 daniel
  1403. * State tracker automatically changes while loops into repeat loops
  1404. Revision 1.39 2002/07/19 12:55:27 daniel
  1405. * Further developed state tracking in whilerepeatn
  1406. Revision 1.38 2002/07/19 11:41:35 daniel
  1407. * State tracker work
  1408. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1409. allows the state tracker to change while nodes automatically into
  1410. repeat nodes.
  1411. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1412. 'not(a>b)' is optimized into 'a<=b'.
  1413. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1414. by removing the notn and later switchting the true and falselabels. The
  1415. same is done with 'repeat until not a'.
  1416. Revision 1.37 2002/07/16 13:57:02 florian
  1417. * raise takes now a void pointer as at and frame address
  1418. instead of a longint
  1419. Revision 1.36 2002/07/15 18:03:15 florian
  1420. * readded removed changes
  1421. Revision 1.35 2002/07/14 18:00:44 daniel
  1422. + Added the beginning of a state tracker. This will track the values of
  1423. variables through procedures and optimize things away.
  1424. Revision 1.34 2002/07/11 14:41:28 florian
  1425. * start of the new generic parameter handling
  1426. Revision 1.33 2002/07/01 18:46:23 peter
  1427. * internal linker
  1428. * reorganized aasm layer
  1429. Revision 1.32 2002/05/18 13:34:10 peter
  1430. * readded missing revisions
  1431. Revision 1.31 2002/05/16 19:46:38 carl
  1432. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1433. + try to fix temp allocation (still in ifdef)
  1434. + generic constructor calls
  1435. + start of tassembler / tmodulebase class cleanup
  1436. }