nflw.pas 37 KB

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