nflw.pas 51 KB

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