nbas.pas 30 KB

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