nflw.pas 46 KB

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