nbas.pas 29 KB

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