nbas.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl
  4. This unit implements some basic nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit nbas;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. aasmbase,aasmtai,aasmcpu,symtype,node,cpubase;
  23. type
  24. tnothingnode = class(tnode)
  25. constructor create;virtual;
  26. function pass_1 : tnode;override;
  27. function det_resulttype:tnode;override;
  28. end;
  29. tnothingnodeclass = class of tnothingnode;
  30. terrornode = class(tnode)
  31. constructor create;virtual;
  32. function pass_1 : tnode;override;
  33. function det_resulttype:tnode;override;
  34. end;
  35. terrornodeclass = class of terrornode;
  36. tasmnode = class(tnode)
  37. p_asm : taasmoutput;
  38. constructor create(p : taasmoutput);virtual;
  39. destructor destroy;override;
  40. function getcopy : tnode;override;
  41. function pass_1 : tnode;override;
  42. function det_resulttype:tnode;override;
  43. function docompare(p: tnode): boolean; override;
  44. end;
  45. tasmnodeclass = class of tasmnode;
  46. tstatementnode = class(tbinarynode)
  47. constructor create(l,r : tnode);virtual;
  48. function pass_1 : tnode;override;
  49. function det_resulttype:tnode;override;
  50. {$ifdef extdebug}
  51. procedure dowrite;override;
  52. {$endif extdebug}
  53. end;
  54. tstatementnodeclass = class of tstatementnode;
  55. tblocknode = class(tunarynode)
  56. constructor create(l : tnode);virtual;
  57. function pass_1 : tnode;override;
  58. function det_resulttype:tnode;override;
  59. {$ifdef state_tracking}
  60. function track_state_pass(exec_known:boolean):boolean;override;
  61. {$endif state_tracking}
  62. end;
  63. tblocknodeclass = class of tblocknode;
  64. { to allow access to the location by temp references even after the temp has }
  65. { already been disposed and to make sure the coherency between temps and }
  66. { temp references is kept after a getcopy }
  67. ptempinfo = ^ttempinfo;
  68. ttempinfo = record
  69. { set to the copy of a tempcreate pnode (if it gets copied) so that the }
  70. { refs and deletenode can hook to this copy once they get copied too }
  71. hookoncopy : ptempinfo;
  72. ref : treference;
  73. restype : ttype;
  74. valid : boolean;
  75. end;
  76. { a node which will create a (non)persistent temp of a given type with a given }
  77. { size (the size is separate to allow creating "void" temps with a custom size) }
  78. ttempcreatenode = class(tnode)
  79. size: longint;
  80. tempinfo: ptempinfo;
  81. persistent: boolean;
  82. { * persistent temps are used in manually written code where the temp }
  83. { be usable among different statements and where you can manually say }
  84. { when the temp has to be freed (using a ttempdeletenode) }
  85. { * non-persistent temps are mostly used in typeconversion helpers, }
  86. { where the node that receives the temp becomes responsible for }
  87. { freeing it. In this last case, you should use only one reference }
  88. { to it and *not* generate a ttempdeletenode }
  89. constructor create(const _restype: ttype; _size: longint; _persistent: boolean); virtual;
  90. function getcopy: tnode; override;
  91. function pass_1 : tnode; override;
  92. function det_resulttype: tnode; override;
  93. function docompare(p: tnode): boolean; override;
  94. end;
  95. ttempcreatenodeclass = class of ttempcreatenode;
  96. { a node which is a reference to a certain temp }
  97. ttemprefnode = class(tnode)
  98. constructor create(const temp: ttempcreatenode); virtual;
  99. constructor create_offset(const temp: ttempcreatenode;aoffset:longint);
  100. function getcopy: tnode; override;
  101. function pass_1 : tnode; override;
  102. function det_resulttype : tnode; override;
  103. function docompare(p: tnode): boolean; override;
  104. protected
  105. tempinfo: ptempinfo;
  106. offset : longint;
  107. end;
  108. ttemprefnodeclass = class of ttemprefnode;
  109. { a node which removes a temp }
  110. ttempdeletenode = class(tnode)
  111. constructor create(const temp: ttempcreatenode);
  112. { this will convert the persistant temp to a normal temp
  113. for returning to the other nodes }
  114. constructor create_normal_temp(const temp: ttempcreatenode);
  115. function getcopy: tnode; override;
  116. function pass_1: tnode; override;
  117. function det_resulttype: tnode; override;
  118. function docompare(p: tnode): boolean; override;
  119. destructor destroy; override;
  120. protected
  121. tempinfo: ptempinfo;
  122. release_to_normal : boolean;
  123. end;
  124. ttempdeletenodeclass = class of ttempdeletenode;
  125. var
  126. cnothingnode : tnothingnodeclass;
  127. cerrornode : terrornodeclass;
  128. casmnode : tasmnodeclass;
  129. cstatementnode : tstatementnodeclass;
  130. cblocknode : tblocknodeclass;
  131. ctempcreatenode : ttempcreatenodeclass;
  132. ctemprefnode : ttemprefnodeclass;
  133. ctempdeletenode : ttempdeletenodeclass;
  134. { Create a blocknode and statement node for multiple statements
  135. generated internally by the parser }
  136. function internalstatements(var laststatement:tstatementnode):tblocknode;
  137. procedure addstatement(var laststatement:tstatementnode;n:tnode);
  138. implementation
  139. uses
  140. cutils,
  141. verbose,globals,globtype,systems,
  142. symconst,symdef,symsym,defbase,
  143. pass_1,
  144. nld,ncal,nflw,rgobj,cgbase
  145. ;
  146. {*****************************************************************************
  147. Helpers
  148. *****************************************************************************}
  149. function internalstatements(var laststatement:tstatementnode):tblocknode;
  150. begin
  151. { create dummy initial statement }
  152. laststatement := cstatementnode.create(nil,cnothingnode.create);
  153. internalstatements := cblocknode.create(laststatement);
  154. end;
  155. procedure addstatement(var laststatement:tstatementnode;n:tnode);
  156. begin
  157. if assigned(laststatement.left) then
  158. internalerror(200204201);
  159. laststatement.left:=cstatementnode.create(nil,n);
  160. laststatement:=tstatementnode(laststatement.left);
  161. end;
  162. {*****************************************************************************
  163. TFIRSTNOTHING
  164. *****************************************************************************}
  165. constructor tnothingnode.create;
  166. begin
  167. inherited create(nothingn);
  168. end;
  169. function tnothingnode.det_resulttype:tnode;
  170. begin
  171. result:=nil;
  172. resulttype:=voidtype;
  173. end;
  174. function tnothingnode.pass_1 : tnode;
  175. begin
  176. result:=nil;
  177. end;
  178. {*****************************************************************************
  179. TFIRSTERROR
  180. *****************************************************************************}
  181. constructor terrornode.create;
  182. begin
  183. inherited create(errorn);
  184. end;
  185. function terrornode.det_resulttype:tnode;
  186. begin
  187. result:=nil;
  188. include(flags,nf_error);
  189. codegenerror:=true;
  190. resulttype:=generrortype;
  191. end;
  192. function terrornode.pass_1 : tnode;
  193. begin
  194. result:=nil;
  195. codegenerror:=true;
  196. end;
  197. {*****************************************************************************
  198. TSTATEMENTNODE
  199. *****************************************************************************}
  200. constructor tstatementnode.create(l,r : tnode);
  201. begin
  202. inherited create(statementn,l,r);
  203. end;
  204. function tstatementnode.det_resulttype:tnode;
  205. begin
  206. result:=nil;
  207. resulttype:=voidtype;
  208. { right is the statement itself calln assignn or a complex one }
  209. resulttypepass(right);
  210. if (not (cs_extsyntax in aktmoduleswitches)) and
  211. assigned(right.resulttype.def) and
  212. not((right.nodetype=calln) and
  213. (tcallnode(right).procdefinition.proctypeoption=potype_constructor)) and
  214. not(is_void(right.resulttype.def)) then
  215. CGMessage(cg_e_illegal_expression);
  216. if codegenerror then
  217. exit;
  218. { left is the next in the list }
  219. resulttypepass(left);
  220. if codegenerror then
  221. exit;
  222. end;
  223. function tstatementnode.pass_1 : tnode;
  224. begin
  225. result:=nil;
  226. { no temps over several statements }
  227. rg.cleartempgen;
  228. { right is the statement itself calln assignn or a complex one }
  229. firstpass(right);
  230. if codegenerror then
  231. exit;
  232. location.loc:=right.location.loc;
  233. registers32:=right.registers32;
  234. registersfpu:=right.registersfpu;
  235. {$ifdef SUPPORT_MMX}
  236. registersmmx:=right.registersmmx;
  237. {$endif SUPPORT_MMX}
  238. { left is the next in the list }
  239. firstpass(left);
  240. if codegenerror then
  241. exit;
  242. if right.registers32>registers32 then
  243. registers32:=right.registers32;
  244. if right.registersfpu>registersfpu then
  245. registersfpu:=right.registersfpu;
  246. {$ifdef SUPPORT_MMX}
  247. if right.registersmmx>registersmmx then
  248. registersmmx:=right.registersmmx;
  249. {$endif}
  250. end;
  251. {$ifdef extdebug}
  252. procedure tstatementnode.dowrite;
  253. begin
  254. { can't use inherited dowrite, because that will use the
  255. binary which we don't want for statements }
  256. dowritenodetype;
  257. writeln(',');
  258. { write the statement }
  259. writenodeindention:=writenodeindention+' ';
  260. writenode(right);
  261. writeln(')');
  262. delete(writenodeindention,1,4);
  263. { go on with the next statement }
  264. writenode(left);
  265. end;
  266. {$endif}
  267. {*****************************************************************************
  268. TBLOCKNODE
  269. *****************************************************************************}
  270. constructor tblocknode.create(l : tnode);
  271. begin
  272. inherited create(blockn,l);
  273. end;
  274. function tblocknode.det_resulttype:tnode;
  275. var
  276. hp : tstatementnode;
  277. begin
  278. result:=nil;
  279. resulttype:=voidtype;
  280. hp:=tstatementnode(left);
  281. while assigned(hp) do
  282. begin
  283. if assigned(hp.right) then
  284. begin
  285. codegenerror:=false;
  286. resulttypepass(hp.right);
  287. if (not (cs_extsyntax in aktmoduleswitches)) and
  288. assigned(hp.right.resulttype.def) and
  289. not((hp.right.nodetype=calln) and
  290. (tcallnode(hp.right).procdefinition.proctypeoption=potype_constructor)) and
  291. not(is_void(hp.right.resulttype.def)) then
  292. CGMessage(cg_e_illegal_expression);
  293. { the resulttype of the block is the last type that is
  294. returned. Normally this is a voidtype. But when the
  295. compiler inserts a block of multiple statements then the
  296. last entry can return a value }
  297. resulttype:=hp.right.resulttype;
  298. end;
  299. hp:=tstatementnode(hp.left);
  300. end;
  301. end;
  302. function tblocknode.pass_1 : tnode;
  303. var
  304. hp : tstatementnode;
  305. count : longint;
  306. begin
  307. result:=nil;
  308. count:=0;
  309. hp:=tstatementnode(left);
  310. while assigned(hp) do
  311. begin
  312. if cs_regalloc in aktglobalswitches then
  313. begin
  314. { node transformations }
  315. { concat function result to exit }
  316. { this is wrong for string or other complex
  317. result types !!! }
  318. if {ret_in_acc(aktprocdef.rettype.def) and }
  319. (is_ordinal(aktprocdef.rettype.def) or
  320. is_smallset(aktprocdef.rettype.def)) and
  321. assigned(hp.left) and
  322. assigned(tstatementnode(hp.left).right) and
  323. (tstatementnode(hp.left).right.nodetype=exitn) and
  324. (hp.right.nodetype=assignn) and
  325. { !!!! this tbinarynode should be tassignmentnode }
  326. (tbinarynode(hp.right).left.nodetype=funcretn) then
  327. begin
  328. if assigned(texitnode(tstatementnode(hp.left).right).left) then
  329. CGMessage(cg_n_inefficient_code)
  330. else
  331. begin
  332. texitnode(tstatementnode(hp.left).right).left:=tassignmentnode(hp.right).right;
  333. tassignmentnode(hp.right).right:=nil;
  334. hp.right.free;
  335. hp.right:=nil;
  336. end;
  337. end
  338. { warning if unreachable code occurs and elimate this }
  339. else if (hp.right.nodetype in
  340. [exitn,breakn,continuen,goton]) and
  341. { statement node (JM) }
  342. assigned(hp.left) and
  343. { kind of statement! (JM) }
  344. assigned(tstatementnode(hp.left).right) and
  345. (tstatementnode(hp.left).right.nodetype<>labeln) then
  346. begin
  347. { use correct line number }
  348. aktfilepos:=hp.left.fileinfo;
  349. hp.left.free;
  350. hp.left:=nil;
  351. CGMessage(cg_w_unreachable_code);
  352. { old lines }
  353. aktfilepos:=hp.right.fileinfo;
  354. end;
  355. end;
  356. if assigned(hp.right) then
  357. begin
  358. rg.cleartempgen;
  359. codegenerror:=false;
  360. firstpass(hp.right);
  361. hp.registers32:=hp.right.registers32;
  362. hp.registersfpu:=hp.right.registersfpu;
  363. {$ifdef SUPPORT_MMX}
  364. hp.registersmmx:=hp.right.registersmmx;
  365. {$endif SUPPORT_MMX}
  366. end
  367. else
  368. hp.registers32:=0;
  369. if hp.registers32>registers32 then
  370. registers32:=hp.registers32;
  371. if hp.registersfpu>registersfpu then
  372. registersfpu:=hp.registersfpu;
  373. {$ifdef SUPPORT_MMX}
  374. if hp.registersmmx>registersmmx then
  375. registersmmx:=hp.registersmmx;
  376. {$endif}
  377. location.loc:=hp.location.loc;
  378. inc(count);
  379. hp:=tstatementnode(hp.left);
  380. end;
  381. end;
  382. {$ifdef state_tracking}
  383. function Tblocknode.track_state_pass(exec_known:boolean):boolean;
  384. var hp:Tstatementnode;
  385. begin
  386. track_state_pass:=false;
  387. hp:=Tstatementnode(left);
  388. while assigned(hp) do
  389. begin
  390. if hp.right.track_state_pass(exec_known) then
  391. track_state_pass:=true;
  392. hp:=Tstatementnode(hp.left);
  393. end;
  394. end;
  395. {$endif state_tracking}
  396. {*****************************************************************************
  397. TASMNODE
  398. *****************************************************************************}
  399. constructor tasmnode.create(p : taasmoutput);
  400. begin
  401. inherited create(asmn);
  402. p_asm:=p;
  403. end;
  404. destructor tasmnode.destroy;
  405. begin
  406. if assigned(p_asm) then
  407. p_asm.free;
  408. inherited destroy;
  409. end;
  410. function tasmnode.getcopy: tnode;
  411. var
  412. n: tasmnode;
  413. begin
  414. n := tasmnode(inherited getcopy);
  415. if assigned(p_asm) then
  416. begin
  417. n.p_asm:=taasmoutput.create;
  418. n.p_asm.concatlistcopy(p_asm);
  419. end
  420. else n.p_asm := nil;
  421. getcopy := n;
  422. end;
  423. function tasmnode.det_resulttype:tnode;
  424. begin
  425. result:=nil;
  426. resulttype:=voidtype;
  427. end;
  428. function tasmnode.pass_1 : tnode;
  429. begin
  430. result:=nil;
  431. procinfo^.flags:=procinfo^.flags or pi_uses_asm;
  432. end;
  433. function tasmnode.docompare(p: tnode): boolean;
  434. begin
  435. { comparing of asmlists is not implemented (JM) }
  436. docompare := false;
  437. end;
  438. {*****************************************************************************
  439. TEMPCREATENODE
  440. *****************************************************************************}
  441. constructor ttempcreatenode.create(const _restype: ttype; _size: longint; _persistent: boolean);
  442. begin
  443. inherited create(tempcreaten);
  444. size := _size;
  445. new(tempinfo);
  446. fillchar(tempinfo^,sizeof(tempinfo^),0);
  447. tempinfo^.restype := _restype;
  448. persistent := _persistent;
  449. end;
  450. function ttempcreatenode.getcopy: tnode;
  451. var
  452. n: ttempcreatenode;
  453. begin
  454. n := ttempcreatenode(inherited getcopy);
  455. n.size := size;
  456. new(n.tempinfo);
  457. fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
  458. n.tempinfo^.restype := tempinfo^.restype;
  459. { signal the temprefs that the temp they point to has been copied, }
  460. { so that if the refs get copied as well, they can hook themselves }
  461. { to the copy of the temp }
  462. tempinfo^.hookoncopy := n.tempinfo;
  463. result := n;
  464. end;
  465. function ttempcreatenode.pass_1 : tnode;
  466. begin
  467. result := nil;
  468. end;
  469. function ttempcreatenode.det_resulttype: tnode;
  470. begin
  471. result := nil;
  472. { a tempcreatenode doesn't have a resulttype, only temprefnodes do }
  473. resulttype := voidtype;
  474. end;
  475. function ttempcreatenode.docompare(p: tnode): boolean;
  476. begin
  477. result :=
  478. inherited docompare(p) and
  479. (ttempcreatenode(p).size = size) and
  480. is_equal(ttempcreatenode(p).tempinfo^.restype.def,tempinfo^.restype.def);
  481. end;
  482. {*****************************************************************************
  483. TEMPREFNODE
  484. *****************************************************************************}
  485. constructor ttemprefnode.create(const temp: ttempcreatenode);
  486. begin
  487. inherited create(temprefn);
  488. tempinfo := temp.tempinfo;
  489. offset:=0;
  490. end;
  491. constructor ttemprefnode.create_offset(const temp: ttempcreatenode;aoffset:longint);
  492. begin
  493. self.create(temp);
  494. offset := aoffset;
  495. end;
  496. function ttemprefnode.getcopy: tnode;
  497. var
  498. n: ttemprefnode;
  499. begin
  500. n := ttemprefnode(inherited getcopy);
  501. if assigned(tempinfo^.hookoncopy) then
  502. { if the temp has been copied, assume it becomes a new }
  503. { temp which has to be hooked by the copied reference }
  504. begin
  505. { hook the ref to the copied temp }
  506. n.tempinfo := tempinfo^.hookoncopy;
  507. end
  508. else
  509. { if the temp we refer to hasn't been copied, assume }
  510. { we're just a new reference to that temp }
  511. begin
  512. n.tempinfo := tempinfo;
  513. end;
  514. result := n;
  515. end;
  516. function ttemprefnode.pass_1 : tnode;
  517. begin
  518. location.loc:=LOC_REFERENCE;
  519. result := nil;
  520. end;
  521. function ttemprefnode.det_resulttype: tnode;
  522. begin
  523. { check if the temp is already resulttype passed }
  524. if not assigned(tempinfo^.restype.def) then
  525. internalerror(200108233);
  526. result := nil;
  527. resulttype := tempinfo^.restype;
  528. end;
  529. function ttemprefnode.docompare(p: tnode): boolean;
  530. begin
  531. result :=
  532. inherited docompare(p) and
  533. (ttemprefnode(p).tempinfo = tempinfo);
  534. end;
  535. {*****************************************************************************
  536. TEMPDELETENODE
  537. *****************************************************************************}
  538. constructor ttempdeletenode.create(const temp: ttempcreatenode);
  539. begin
  540. inherited create(temprefn);
  541. tempinfo := temp.tempinfo;
  542. release_to_normal := false;
  543. if not temp.persistent then
  544. internalerror(200204211);
  545. end;
  546. constructor ttempdeletenode.create_normal_temp(const temp: ttempcreatenode);
  547. begin
  548. inherited create(tempdeleten);
  549. tempinfo := temp.tempinfo;
  550. release_to_normal := true;
  551. end;
  552. function ttempdeletenode.getcopy: tnode;
  553. var
  554. n: ttempdeletenode;
  555. begin
  556. n := ttempdeletenode(inherited getcopy);
  557. if assigned(tempinfo^.hookoncopy) then
  558. { if the temp has been copied, assume it becomes a new }
  559. { temp which has to be hooked by the copied deletenode }
  560. begin
  561. { hook the tempdeletenode to the copied temp }
  562. n.tempinfo := tempinfo^.hookoncopy;
  563. end
  564. else
  565. { if the temp we refer to hasn't been copied, we have a }
  566. { problem since that means we now have two delete nodes }
  567. { for one temp }
  568. internalerror(200108234);
  569. result := n;
  570. end;
  571. function ttempdeletenode.pass_1 : tnode;
  572. begin
  573. result := nil;
  574. end;
  575. function ttempdeletenode.det_resulttype: tnode;
  576. begin
  577. result := nil;
  578. resulttype := voidtype;
  579. end;
  580. function ttempdeletenode.docompare(p: tnode): boolean;
  581. begin
  582. result :=
  583. inherited docompare(p) and
  584. (ttemprefnode(p).tempinfo = tempinfo);
  585. end;
  586. destructor ttempdeletenode.destroy;
  587. begin
  588. dispose(tempinfo);
  589. end;
  590. begin
  591. cnothingnode:=tnothingnode;
  592. cerrornode:=terrornode;
  593. casmnode:=tasmnode;
  594. cstatementnode:=tstatementnode;
  595. cblocknode:=tblocknode;
  596. ctempcreatenode:=ttempcreatenode;
  597. ctemprefnode:=ttemprefnode;
  598. ctempdeletenode:=ttempdeletenode;
  599. end.
  600. {
  601. $Log$
  602. Revision 1.31 2002-08-15 19:10:35 peter
  603. * first things tai,tnode storing in ppu
  604. Revision 1.30 2002/07/20 11:57:53 florian
  605. * types.pas renamed to defbase.pas because D6 contains a types
  606. unit so this would conflicts if D6 programms are compiled
  607. + Willamette/SSE2 instructions to assembler added
  608. Revision 1.29 2002/07/19 11:41:35 daniel
  609. * State tracker work
  610. * The whilen and repeatn are now completely unified into whilerepeatn. This
  611. allows the state tracker to change while nodes automatically into
  612. repeat nodes.
  613. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  614. 'not(a>b)' is optimized into 'a<=b'.
  615. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  616. by removing the notn and later switchting the true and falselabels. The
  617. same is done with 'repeat until not a'.
  618. Revision 1.28 2002/07/14 18:00:43 daniel
  619. + Added the beginning of a state tracker. This will track the values of
  620. variables through procedures and optimize things away.
  621. Revision 1.27 2002/07/01 18:46:22 peter
  622. * internal linker
  623. * reorganized aasm layer
  624. Revision 1.26 2002/06/24 12:43:00 jonas
  625. * fixed errors found with new -CR code from Peter when cycling with -O2p3r
  626. Revision 1.25 2002/05/18 13:34:09 peter
  627. * readded missing revisions
  628. Revision 1.24 2002/05/16 19:46:37 carl
  629. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  630. + try to fix temp allocation (still in ifdef)
  631. + generic constructor calls
  632. + start of tassembler / tmodulebase class cleanup
  633. Revision 1.22 2002/04/23 19:16:34 peter
  634. * add pinline unit that inserts compiler supported functions using
  635. one or more statements
  636. * moved finalize and setlength from ninl to pinline
  637. Revision 1.21 2002/04/21 19:02:03 peter
  638. * removed newn and disposen nodes, the code is now directly
  639. inlined from pexpr
  640. * -an option that will write the secondpass nodes to the .s file, this
  641. requires EXTDEBUG define to actually write the info
  642. * fixed various internal errors and crashes due recent code changes
  643. Revision 1.20 2002/04/04 19:05:57 peter
  644. * removed unused units
  645. * use tlocation.size in cg.a_*loc*() routines
  646. Revision 1.19 2002/03/31 20:26:33 jonas
  647. + a_loadfpu_* and a_loadmm_* methods in tcg
  648. * register allocation is now handled by a class and is mostly processor
  649. independent (+rgobj.pas and i386/rgcpu.pas)
  650. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  651. * some small improvements and fixes to the optimizer
  652. * some register allocation fixes
  653. * some fpuvaroffset fixes in the unary minus node
  654. * push/popusedregisters is now called rg.save/restoreusedregisters and
  655. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  656. also better optimizable)
  657. * fixed and optimized register saving/restoring for new/dispose nodes
  658. * LOC_FPU locations now also require their "register" field to be set to
  659. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  660. - list field removed of the tnode class because it's not used currently
  661. and can cause hard-to-find bugs
  662. }