nbas.pas 35 KB

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