nmem.pas 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl
  4. Type checking and register allocation for memory related 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 nmem;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,
  23. symtype,symppu,symdef,symsym,symtable,
  24. cpubase;
  25. type
  26. tloadvmtnode = class(tunarynode)
  27. constructor create(l : tnode);virtual;
  28. function pass_1 : tnode;override;
  29. function det_resulttype:tnode;override;
  30. end;
  31. tloadvmtnodeclass = class of tloadvmtnode;
  32. thnewnode = class(tnode)
  33. objtype : ttype;
  34. constructor create(t:ttype);virtual;
  35. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  36. procedure ppuwrite(ppufile:tcompilerppufile);override;
  37. procedure derefimpl;override;
  38. function pass_1 : tnode;override;
  39. function det_resulttype:tnode;override;
  40. end;
  41. thnewnodeclass = class of thnewnode;
  42. thdisposenode = class(tunarynode)
  43. constructor create(l : tnode);virtual;
  44. function pass_1 : tnode;override;
  45. function det_resulttype:tnode;override;
  46. end;
  47. thdisposenodeclass = class of thdisposenode;
  48. taddrnode = class(tunarynode)
  49. getprocvardef : tprocvardef;
  50. constructor create(l : tnode);virtual;
  51. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  52. procedure ppuwrite(ppufile:tcompilerppufile);override;
  53. procedure mark_write;override;
  54. procedure derefimpl;override;
  55. function getcopy : tnode;override;
  56. function pass_1 : tnode;override;
  57. function det_resulttype:tnode;override;
  58. end;
  59. taddrnodeclass = class of taddrnode;
  60. tdoubleaddrnode = class(tunarynode)
  61. constructor create(l : tnode);virtual;
  62. function pass_1 : tnode;override;
  63. function det_resulttype:tnode;override;
  64. end;
  65. tdoubleaddrnodeclass = class of tdoubleaddrnode;
  66. tderefnode = class(tunarynode)
  67. constructor create(l : tnode);virtual;
  68. function pass_1 : tnode;override;
  69. function det_resulttype:tnode;override;
  70. procedure mark_write;override;
  71. end;
  72. tderefnodeclass = class of tderefnode;
  73. tsubscriptnode = class(tunarynode)
  74. vs : tvarsym;
  75. constructor create(varsym : tsym;l : tnode);virtual;
  76. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  77. procedure ppuwrite(ppufile:tcompilerppufile);override;
  78. procedure derefimpl;override;
  79. function getcopy : tnode;override;
  80. function pass_1 : tnode;override;
  81. function docompare(p: tnode): boolean; override;
  82. function det_resulttype:tnode;override;
  83. procedure mark_write;override;
  84. end;
  85. tsubscriptnodeclass = class of tsubscriptnode;
  86. tvecnode = class(tbinarynode)
  87. constructor create(l,r : tnode);virtual;
  88. function pass_1 : tnode;override;
  89. function det_resulttype:tnode;override;
  90. procedure mark_write;override;
  91. end;
  92. tvecnodeclass = class of tvecnode;
  93. tselfnode = class(tnode)
  94. classdef : tdef; { objectdef or classrefdef }
  95. constructor create(_class : tdef);virtual;
  96. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  97. procedure ppuwrite(ppufile:tcompilerppufile);override;
  98. procedure derefimpl;override;
  99. function pass_1 : tnode;override;
  100. function det_resulttype:tnode;override;
  101. end;
  102. tselfnodeclass = class of tselfnode;
  103. twithnode = class(tbinarynode)
  104. withsymtable : twithsymtable;
  105. tablecount : longint;
  106. withreference : treference;
  107. constructor create(symtable : twithsymtable;l,r : tnode;count : longint);virtual;
  108. destructor destroy;override;
  109. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  110. procedure ppuwrite(ppufile:tcompilerppufile);override;
  111. function getcopy : tnode;override;
  112. function pass_1 : tnode;override;
  113. function docompare(p: tnode): boolean; override;
  114. function det_resulttype:tnode;override;
  115. end;
  116. twithnodeclass = class of twithnode;
  117. var
  118. cloadvmtnode : tloadvmtnodeclass;
  119. chnewnode : thnewnodeclass;
  120. chdisposenode : thdisposenodeclass;
  121. caddrnode : taddrnodeclass;
  122. cdoubleaddrnode : tdoubleaddrnodeclass;
  123. cderefnode : tderefnodeclass;
  124. csubscriptnode : tsubscriptnodeclass;
  125. cvecnode : tvecnodeclass;
  126. cselfnode : tselfnodeclass;
  127. cwithnode : twithnodeclass;
  128. implementation
  129. uses
  130. globtype,systems,
  131. cutils,verbose,globals,
  132. symconst,symbase,defutil,defcmp,
  133. nbas,
  134. htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase
  135. ;
  136. {*****************************************************************************
  137. TLOADVMTNODE
  138. *****************************************************************************}
  139. constructor tloadvmtnode.create(l : tnode);
  140. begin
  141. inherited create(loadvmtn,l);
  142. end;
  143. function tloadvmtnode.det_resulttype:tnode;
  144. begin
  145. result:=nil;
  146. resulttypepass(left);
  147. if codegenerror then
  148. exit;
  149. resulttype.setdef(tclassrefdef.create(left.resulttype));
  150. end;
  151. function tloadvmtnode.pass_1 : tnode;
  152. begin
  153. result:=nil;
  154. registers32:=1;
  155. location.loc:=LOC_REGISTER;
  156. end;
  157. {*****************************************************************************
  158. THNEWNODE
  159. *****************************************************************************}
  160. constructor thnewnode.create(t:ttype);
  161. begin
  162. inherited create(hnewn);
  163. objtype:=t;
  164. end;
  165. constructor thnewnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  166. begin
  167. inherited ppuload(t,ppufile);
  168. ppufile.gettype(objtype);
  169. end;
  170. procedure thnewnode.ppuwrite(ppufile:tcompilerppufile);
  171. begin
  172. inherited ppuwrite(ppufile);
  173. ppufile.puttype(objtype);
  174. end;
  175. procedure thnewnode.derefimpl;
  176. begin
  177. inherited derefimpl;
  178. objtype.resolve;
  179. end;
  180. function thnewnode.det_resulttype:tnode;
  181. begin
  182. result:=nil;
  183. if objtype.def.deftype<>objectdef then
  184. Message(parser_e_pointer_to_class_expected);
  185. resulttype:=objtype;
  186. end;
  187. function thnewnode.pass_1 : tnode;
  188. begin
  189. result:=nil;
  190. end;
  191. {*****************************************************************************
  192. THDISPOSENODE
  193. *****************************************************************************}
  194. constructor thdisposenode.create(l : tnode);
  195. begin
  196. inherited create(hdisposen,l);
  197. end;
  198. function thdisposenode.det_resulttype:tnode;
  199. begin
  200. result:=nil;
  201. resulttypepass(left);
  202. if codegenerror then
  203. exit;
  204. if (left.resulttype.def.deftype<>pointerdef) then
  205. CGMessage1(type_e_pointer_type_expected,left.resulttype.def.typename);
  206. resulttype:=tpointerdef(left.resulttype.def).pointertype;
  207. end;
  208. function thdisposenode.pass_1 : tnode;
  209. begin
  210. result:=nil;
  211. firstpass(left);
  212. if codegenerror then
  213. exit;
  214. registers32:=left.registers32;
  215. registersfpu:=left.registersfpu;
  216. {$ifdef SUPPORT_MMX}
  217. registersmmx:=left.registersmmx;
  218. {$endif SUPPORT_MMX}
  219. if registers32<1 then
  220. registers32:=1;
  221. {
  222. if left.location.loc<>LOC_REFERENCE then
  223. CGMessage(cg_e_illegal_expression);
  224. }
  225. if left.location.loc=LOC_CREGISTER then
  226. inc(registers32);
  227. location.loc:=LOC_REFERENCE;
  228. end;
  229. {*****************************************************************************
  230. TADDRNODE
  231. *****************************************************************************}
  232. constructor taddrnode.create(l : tnode);
  233. begin
  234. inherited create(addrn,l);
  235. getprocvardef:=nil;
  236. end;
  237. constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  238. begin
  239. inherited ppuload(t,ppufile);
  240. getprocvardef:=tprocvardef(ppufile.getderef);
  241. end;
  242. procedure taddrnode.ppuwrite(ppufile:tcompilerppufile);
  243. begin
  244. inherited ppuwrite(ppufile);
  245. ppufile.putderef(getprocvardef);
  246. end;
  247. procedure Taddrnode.mark_write;
  248. begin
  249. {@procvar:=nil is legal in Delphi mode.}
  250. left.mark_write;
  251. end;
  252. procedure taddrnode.derefimpl;
  253. begin
  254. inherited derefimpl;
  255. resolvedef(pointer(getprocvardef));
  256. end;
  257. function taddrnode.getcopy : tnode;
  258. var
  259. p : taddrnode;
  260. begin
  261. p:=taddrnode(inherited getcopy);
  262. p.getprocvardef:=getprocvardef;
  263. getcopy:=p;
  264. end;
  265. function taddrnode.det_resulttype:tnode;
  266. var
  267. hp : tnode;
  268. hp2 : TParaItem;
  269. hp3 : tabstractprocdef;
  270. begin
  271. result:=nil;
  272. resulttypepass(left);
  273. if codegenerror then
  274. exit;
  275. { don't allow constants }
  276. if is_constnode(left) then
  277. begin
  278. aktfilepos:=left.fileinfo;
  279. CGMessage(type_e_no_addr_of_constant);
  280. exit;
  281. end;
  282. { tp @procvar support (type of @procvar is a void pointer)
  283. Note: we need to leave the addrn in the tree,
  284. else we can't see the difference between @procvar and procvar.
  285. we set the procvarload flag so a secondpass does nothing for
  286. this node (PFV) }
  287. if (m_tp_procvar in aktmodeswitches) then
  288. begin
  289. case left.nodetype of
  290. calln :
  291. begin
  292. { a load of a procvar can't have parameters }
  293. if assigned(tcallnode(left).left) then
  294. CGMessage(cg_e_illegal_expression);
  295. { is it a procvar? }
  296. hp:=tcallnode(left).right;
  297. if assigned(hp) then
  298. begin
  299. { remove calln node }
  300. tcallnode(left).right:=nil;
  301. left.free;
  302. left:=hp;
  303. include(flags,nf_procvarload);
  304. end;
  305. end;
  306. loadn,
  307. subscriptn,
  308. typeconvn,
  309. vecn,
  310. derefn :
  311. begin
  312. if left.resulttype.def.deftype=procvardef then
  313. include(flags,nf_procvarload);
  314. end;
  315. end;
  316. if nf_procvarload in flags then
  317. begin
  318. resulttype:=voidpointertype;
  319. exit;
  320. end;
  321. end;
  322. { proc 2 procvar ? }
  323. if left.nodetype=calln then
  324. { if it were a valid construct, the addr node would already have }
  325. { been removed in the parser. This happens for (in FPC mode) }
  326. { procvar1 := @procvar2(parameters); }
  327. CGMessage(cg_e_illegal_expression)
  328. else
  329. if (left.nodetype=loadn) and (tloadnode(left).symtableentry.typ=procsym) then
  330. begin
  331. { the address is already available when loading a procedure of object }
  332. if assigned(tloadnode(left).left) then
  333. include(flags,nf_procvarload);
  334. { result is a procedure variable }
  335. { No, to be TP compatible, you must return a voidpointer to
  336. the procedure that is stored in the procvar.}
  337. if not(m_tp_procvar in aktmodeswitches) then
  338. begin
  339. if assigned(getprocvardef) then
  340. hp3:=getprocvardef
  341. else
  342. hp3:=tabstractprocdef(tprocsym(tloadnode(left).symtableentry).first_procdef);
  343. { create procvardef }
  344. resulttype.setdef(tprocvardef.create);
  345. tprocvardef(resulttype.def).proctypeoption:=hp3.proctypeoption;
  346. tprocvardef(resulttype.def).proccalloption:=hp3.proccalloption;
  347. tprocvardef(resulttype.def).procoptions:=hp3.procoptions;
  348. tprocvardef(resulttype.def).rettype:=hp3.rettype;
  349. tprocvardef(resulttype.def).symtablelevel:=hp3.symtablelevel;
  350. { method ? then set the methodpointer flag }
  351. if (hp3.owner.symtabletype=objectsymtable) then
  352. include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
  353. { only need the address of the method? this is needed
  354. for @tobject.create }
  355. if not assigned(tloadnode(left).left) then
  356. include(tprocvardef(resulttype.def).procoptions,po_addressonly);
  357. { Add parameters in left to right order }
  358. hp2:=TParaItem(hp3.Para.first);
  359. while assigned(hp2) do
  360. begin
  361. tprocvardef(resulttype.def).concatpara(nil,hp2.paratype,hp2.parasym,hp2.paratyp,hp2.defaultvalue);
  362. hp2:=TParaItem(hp2.next);
  363. end;
  364. end
  365. else
  366. resulttype:=voidpointertype;
  367. end
  368. else
  369. begin
  370. { what are we getting the address from an absolute sym? }
  371. hp:=left;
  372. while assigned(hp) and (hp.nodetype in [vecn,derefn,subscriptn]) do
  373. hp:=tunarynode(hp).left;
  374. if assigned(hp) and (hp.nodetype=loadn) and
  375. ((tloadnode(hp).symtableentry.typ=absolutesym) and
  376. tabsolutesym(tloadnode(hp).symtableentry).absseg) then
  377. begin
  378. if not(cs_typed_addresses in aktlocalswitches) then
  379. resulttype:=voidfarpointertype
  380. else
  381. resulttype.setdef(tpointerdef.createfar(left.resulttype));
  382. end
  383. else
  384. begin
  385. if not(cs_typed_addresses in aktlocalswitches) then
  386. resulttype:=voidpointertype
  387. else
  388. resulttype.setdef(tpointerdef.create(left.resulttype));
  389. end;
  390. end;
  391. { this is like the function addr }
  392. inc(parsing_para_level);
  393. set_varstate(left,false);
  394. dec(parsing_para_level);
  395. end;
  396. function taddrnode.pass_1 : tnode;
  397. begin
  398. result:=nil;
  399. firstpass(left);
  400. if codegenerror then
  401. exit;
  402. make_not_regable(left);
  403. if nf_procvarload in flags then
  404. begin
  405. registers32:=left.registers32;
  406. registersfpu:=left.registersfpu;
  407. {$ifdef SUPPORT_MMX}
  408. registersmmx:=left.registersmmx;
  409. {$endif SUPPORT_MMX}
  410. if registers32<1 then
  411. registers32:=1;
  412. location.loc:=left.location.loc;
  413. exit;
  414. end;
  415. { we should allow loc_mem for @string }
  416. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  417. begin
  418. aktfilepos:=left.fileinfo;
  419. CGMessage(cg_e_illegal_expression);
  420. end;
  421. registers32:=left.registers32;
  422. registersfpu:=left.registersfpu;
  423. {$ifdef SUPPORT_MMX}
  424. registersmmx:=left.registersmmx;
  425. {$endif SUPPORT_MMX}
  426. if registers32<1 then
  427. registers32:=1;
  428. { is this right for object of methods ?? }
  429. location.loc:=LOC_REGISTER;
  430. end;
  431. {*****************************************************************************
  432. TDOUBLEADDRNODE
  433. *****************************************************************************}
  434. constructor tdoubleaddrnode.create(l : tnode);
  435. begin
  436. inherited create(doubleaddrn,l);
  437. end;
  438. function tdoubleaddrnode.det_resulttype:tnode;
  439. begin
  440. result:=nil;
  441. resulttypepass(left);
  442. if codegenerror then
  443. exit;
  444. inc(parsing_para_level);
  445. set_varstate(left,false);
  446. dec(parsing_para_level);
  447. if (left.resulttype.def.deftype)<>procvardef then
  448. CGMessage(cg_e_illegal_expression);
  449. resulttype:=voidpointertype;
  450. end;
  451. function tdoubleaddrnode.pass_1 : tnode;
  452. begin
  453. result:=nil;
  454. make_not_regable(left);
  455. firstpass(left);
  456. if codegenerror then
  457. exit;
  458. if (left.location.loc<>LOC_REFERENCE) then
  459. CGMessage(cg_e_illegal_expression);
  460. registers32:=left.registers32;
  461. registersfpu:=left.registersfpu;
  462. {$ifdef SUPPORT_MMX}
  463. registersmmx:=left.registersmmx;
  464. {$endif SUPPORT_MMX}
  465. if registers32<1 then
  466. registers32:=1;
  467. location.loc:=LOC_REGISTER;
  468. end;
  469. {*****************************************************************************
  470. TDEREFNODE
  471. *****************************************************************************}
  472. constructor tderefnode.create(l : tnode);
  473. begin
  474. inherited create(derefn,l);
  475. end;
  476. function tderefnode.det_resulttype:tnode;
  477. begin
  478. result:=nil;
  479. resulttypepass(left);
  480. set_varstate(left,true);
  481. if codegenerror then
  482. exit;
  483. if left.resulttype.def.deftype=pointerdef then
  484. resulttype:=tpointerdef(left.resulttype.def).pointertype
  485. else
  486. CGMessage(cg_e_invalid_qualifier);
  487. end;
  488. procedure Tderefnode.mark_write;
  489. begin
  490. include(flags,nf_write);
  491. end;
  492. function tderefnode.pass_1 : tnode;
  493. begin
  494. result:=nil;
  495. firstpass(left);
  496. if codegenerror then
  497. exit;
  498. registers32:=max(left.registers32,1);
  499. registersfpu:=left.registersfpu;
  500. {$ifdef SUPPORT_MMX}
  501. registersmmx:=left.registersmmx;
  502. {$endif SUPPORT_MMX}
  503. location.loc:=LOC_REFERENCE;
  504. end;
  505. {*****************************************************************************
  506. TSUBSCRIPTNODE
  507. *****************************************************************************}
  508. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  509. begin
  510. inherited create(subscriptn,l);
  511. { vs should be changed to tsym! }
  512. vs:=tvarsym(varsym);
  513. end;
  514. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  515. begin
  516. inherited ppuload(t,ppufile);
  517. vs:=tvarsym(ppufile.getderef);
  518. end;
  519. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  520. begin
  521. inherited ppuwrite(ppufile);
  522. ppufile.putderef(vs);
  523. end;
  524. procedure tsubscriptnode.derefimpl;
  525. begin
  526. inherited derefimpl;
  527. resolvesym(pointer(vs));
  528. end;
  529. function tsubscriptnode.getcopy : tnode;
  530. var
  531. p : tsubscriptnode;
  532. begin
  533. p:=tsubscriptnode(inherited getcopy);
  534. p.vs:=vs;
  535. getcopy:=p;
  536. end;
  537. function tsubscriptnode.det_resulttype:tnode;
  538. begin
  539. result:=nil;
  540. resulttypepass(left);
  541. resulttype:=vs.vartype;
  542. end;
  543. procedure Tsubscriptnode.mark_write;
  544. begin
  545. include(flags,nf_write);
  546. end;
  547. function tsubscriptnode.pass_1 : tnode;
  548. begin
  549. result:=nil;
  550. firstpass(left);
  551. if codegenerror then
  552. exit;
  553. registers32:=left.registers32;
  554. registersfpu:=left.registersfpu;
  555. {$ifdef SUPPORT_MMX}
  556. registersmmx:=left.registersmmx;
  557. {$endif SUPPORT_MMX}
  558. { classes must be dereferenced implicit }
  559. if is_class_or_interface(left.resulttype.def) then
  560. begin
  561. if registers32=0 then
  562. registers32:=1;
  563. location.loc:=LOC_REFERENCE;
  564. end
  565. else
  566. begin
  567. if (left.location.loc<>LOC_CREFERENCE) and
  568. (left.location.loc<>LOC_REFERENCE) then
  569. CGMessage(cg_e_illegal_expression);
  570. location.loc:=left.location.loc;
  571. end;
  572. end;
  573. function tsubscriptnode.docompare(p: tnode): boolean;
  574. begin
  575. docompare :=
  576. inherited docompare(p) and
  577. (vs = tsubscriptnode(p).vs);
  578. end;
  579. {*****************************************************************************
  580. TVECNODE
  581. *****************************************************************************}
  582. constructor tvecnode.create(l,r : tnode);
  583. begin
  584. inherited create(vecn,l,r);
  585. end;
  586. function tvecnode.det_resulttype:tnode;
  587. var
  588. htype : ttype;
  589. begin
  590. result:=nil;
  591. resulttypepass(left);
  592. resulttypepass(right);
  593. if codegenerror then
  594. exit;
  595. { maybe type conversion for the index value, but
  596. do not convert enums,booleans,char }
  597. if (right.resulttype.def.deftype<>enumdef) and
  598. not(is_char(right.resulttype.def)) and
  599. not(is_boolean(right.resulttype.def)) then
  600. begin
  601. inserttypeconv(right,s32bittype);
  602. end;
  603. case left.resulttype.def.deftype of
  604. arraydef :
  605. begin
  606. { check type of the index value }
  607. if (compare_defs(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,right.nodetype)=te_incompatible) then
  608. CGMessage(type_e_mismatch);
  609. resulttype:=tarraydef(left.resulttype.def).elementtype;
  610. end;
  611. pointerdef :
  612. begin
  613. { are we accessing a pointer[], then convert the pointer to
  614. an array first, in FPC this is allowed for all pointers in
  615. delphi/tp7 it's only allowed for pchars }
  616. if (m_fpc in aktmodeswitches) or
  617. is_pchar(left.resulttype.def) or
  618. is_pwidechar(left.resulttype.def) then
  619. begin
  620. { convert pointer to array }
  621. htype.setdef(tarraydef.create(0,$7fffffff,s32bittype));
  622. tarraydef(htype.def).setelementtype(tpointerdef(left.resulttype.def).pointertype);
  623. inserttypeconv(left,htype);
  624. resulttype:=tarraydef(htype.def).elementtype;
  625. end
  626. else
  627. CGMessage(type_e_array_required);
  628. end;
  629. stringdef :
  630. begin
  631. { indexed access to 0 element is only allowed for shortstrings }
  632. if (right.nodetype=ordconstn) and
  633. (tordconstnode(right).value=0) and
  634. not(is_shortstring(left.resulttype.def)) then
  635. CGMessage(cg_e_can_access_element_zero);
  636. case tstringdef(left.resulttype.def).string_typ of
  637. st_widestring :
  638. resulttype:=cwidechartype;
  639. st_ansistring :
  640. resulttype:=cchartype;
  641. st_longstring :
  642. resulttype:=cchartype;
  643. st_shortstring :
  644. resulttype:=cchartype;
  645. end;
  646. end
  647. else
  648. CGMessage(type_e_array_required);
  649. end;
  650. end;
  651. procedure Tvecnode.mark_write;
  652. begin
  653. include(flags,nf_write);
  654. end;
  655. function tvecnode.pass_1 : tnode;
  656. {$ifdef consteval}
  657. var
  658. tcsym : ttypedconstsym;
  659. {$endif}
  660. begin
  661. result:=nil;
  662. firstpass(left);
  663. firstpass(right);
  664. if codegenerror then
  665. exit;
  666. { the register calculation is easy if a const index is used }
  667. if right.nodetype=ordconstn then
  668. begin
  669. {$ifdef consteval}
  670. { constant evaluation }
  671. if (left.nodetype=loadn) and
  672. (left.symtableentry.typ=typedconstsym) then
  673. begin
  674. tcsym:=ttypedconstsym(left.symtableentry);
  675. if tcsym.defintion^.typ=stringdef then
  676. begin
  677. end;
  678. end;
  679. {$endif}
  680. registers32:=left.registers32;
  681. { for ansi/wide strings, we need at least one register }
  682. if is_ansistring(left.resulttype.def) or
  683. is_widestring(left.resulttype.def) or
  684. { ... as well as for dynamic arrays }
  685. is_dynamic_array(left.resulttype.def) then
  686. registers32:=max(registers32,1);
  687. end
  688. else
  689. begin
  690. { this rules are suboptimal, but they should give }
  691. { good results }
  692. registers32:=max(left.registers32,right.registers32);
  693. { for ansi/wide strings, we need at least one register }
  694. if is_ansistring(left.resulttype.def) or
  695. is_widestring(left.resulttype.def) or
  696. { ... as well as for dynamic arrays }
  697. is_dynamic_array(left.resulttype.def) then
  698. registers32:=max(registers32,1);
  699. { need we an extra register when doing the restore ? }
  700. if (left.registers32<=right.registers32) and
  701. { only if the node needs less than 3 registers }
  702. { two for the right node and one for the }
  703. { left address }
  704. (registers32<3) then
  705. inc(registers32);
  706. { need we an extra register for the index ? }
  707. if (right.location.loc<>LOC_REGISTER)
  708. { only if the right node doesn't need a register }
  709. and (right.registers32<1) then
  710. inc(registers32);
  711. { not correct, but what works better ?
  712. if left.registers32>0 then
  713. registers32:=max(registers32,2)
  714. else
  715. min. one register
  716. registers32:=max(registers32,1);
  717. }
  718. end;
  719. registersfpu:=max(left.registersfpu,right.registersfpu);
  720. {$ifdef SUPPORT_MMX}
  721. registersmmx:=max(left.registersmmx,right.registersmmx);
  722. {$endif SUPPORT_MMX}
  723. if left.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
  724. location.loc:=LOC_REFERENCE
  725. else
  726. location.loc:=LOC_CREFERENCE;
  727. end;
  728. {*****************************************************************************
  729. TSELFNODE
  730. *****************************************************************************}
  731. constructor tselfnode.create(_class : tdef);
  732. begin
  733. inherited create(selfn);
  734. classdef:=_class;
  735. end;
  736. constructor tselfnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  737. begin
  738. inherited ppuload(t,ppufile);
  739. classdef:=tdef(ppufile.getderef);
  740. end;
  741. procedure tselfnode.ppuwrite(ppufile:tcompilerppufile);
  742. begin
  743. inherited ppuwrite(ppufile);
  744. ppufile.putderef(classdef);
  745. end;
  746. procedure tselfnode.derefimpl;
  747. begin
  748. inherited derefimpl;
  749. resolvedef(pointer(classdef));
  750. end;
  751. function tselfnode.det_resulttype:tnode;
  752. begin
  753. result:=nil;
  754. resulttype.setdef(classdef);
  755. end;
  756. function tselfnode.pass_1 : tnode;
  757. begin
  758. result:=nil;
  759. if (resulttype.def.deftype=classrefdef) or
  760. is_class(resulttype.def) or
  761. (po_staticmethod in aktprocdef.procoptions) then
  762. location.loc:=LOC_CREGISTER
  763. else
  764. location.loc:=LOC_REFERENCE;
  765. end;
  766. {*****************************************************************************
  767. TWITHNODE
  768. *****************************************************************************}
  769. constructor twithnode.create(symtable : twithsymtable;l,r : tnode;count : longint);
  770. begin
  771. inherited create(withn,l,r);
  772. withsymtable:=symtable;
  773. tablecount:=count;
  774. FillChar(withreference,sizeof(withreference),0);
  775. set_file_line(l);
  776. end;
  777. destructor twithnode.destroy;
  778. var
  779. hsymt,
  780. symt : tsymtable;
  781. i : longint;
  782. begin
  783. symt:=withsymtable;
  784. for i:=1 to tablecount do
  785. begin
  786. if assigned(symt) then
  787. begin
  788. hsymt:=symt.next;
  789. symt.free;
  790. symt:=hsymt;
  791. end;
  792. end;
  793. inherited destroy;
  794. end;
  795. constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  796. begin
  797. inherited ppuload(t,ppufile);
  798. internalerror(200208192);
  799. end;
  800. procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
  801. begin
  802. inherited ppuwrite(ppufile);
  803. internalerror(200208193);
  804. end;
  805. function twithnode.getcopy : tnode;
  806. var
  807. p : twithnode;
  808. begin
  809. p:=twithnode(inherited getcopy);
  810. p.withsymtable:=withsymtable;
  811. p.tablecount:=tablecount;
  812. p.withreference:=withreference;
  813. result:=p;
  814. end;
  815. function twithnode.det_resulttype:tnode;
  816. var
  817. symtable : tsymtable;
  818. i : longint;
  819. begin
  820. result:=nil;
  821. resulttype:=voidtype;
  822. if assigned(left) and assigned(right) then
  823. begin
  824. resulttypepass(left);
  825. unset_varstate(left);
  826. set_varstate(left,true);
  827. if codegenerror then
  828. exit;
  829. symtable:=withsymtable;
  830. for i:=1 to tablecount do
  831. begin
  832. if (left.nodetype=loadn) and
  833. (tloadnode(left).symtable=aktprocdef.localst) then
  834. twithsymtable(symtable).direct_with:=true;
  835. twithsymtable(symtable).withnode:=self;
  836. symtable:=symtable.next;
  837. end;
  838. resulttypepass(right);
  839. if codegenerror then
  840. exit;
  841. end;
  842. resulttype:=voidtype;
  843. end;
  844. function twithnode.pass_1 : tnode;
  845. begin
  846. result:=nil;
  847. if assigned(left) and assigned(right) then
  848. begin
  849. firstpass(left);
  850. firstpass(right);
  851. if codegenerror then
  852. exit;
  853. left_right_max;
  854. end
  855. else
  856. begin
  857. { optimization }
  858. result:=nil;
  859. end;
  860. end;
  861. function twithnode.docompare(p: tnode): boolean;
  862. begin
  863. docompare :=
  864. inherited docompare(p) and
  865. (withsymtable = twithnode(p).withsymtable) and
  866. (tablecount = twithnode(p).tablecount);
  867. end;
  868. begin
  869. cloadvmtnode := tloadvmtnode;
  870. chnewnode := thnewnode;
  871. chdisposenode := thdisposenode;
  872. caddrnode := taddrnode;
  873. cdoubleaddrnode := tdoubleaddrnode;
  874. cderefnode := tderefnode;
  875. csubscriptnode := tsubscriptnode;
  876. cvecnode := tvecnode;
  877. cselfnode := tselfnode;
  878. cwithnode := twithnode;
  879. end.
  880. {
  881. $Log$
  882. Revision 1.47 2003-04-10 17:57:52 peter
  883. * vs_hidden released
  884. Revision 1.46 2003/01/30 21:46:57 peter
  885. * self fixes for static methods (merged)
  886. Revision 1.45 2003/01/09 21:52:37 peter
  887. * merged some verbosity options.
  888. * V_LineInfo is a verbosity flag to include line info
  889. Revision 1.44 2003/01/06 21:16:52 peter
  890. * po_addressonly added to retrieve the address of a methodpointer
  891. only, this is used for @tclass.method which has no self pointer
  892. Revision 1.43 2003/01/04 15:54:03 daniel
  893. * Fixed mark_write for @ operator
  894. (can happen when compiling @procvar:=nil (Delphi mode construction))
  895. Revision 1.42 2003/01/03 12:15:56 daniel
  896. * Removed ifdefs around notifications
  897. ifdefs around for loop optimizations remain
  898. Revision 1.41 2002/11/25 17:43:20 peter
  899. * splitted defbase in defutil,symutil,defcmp
  900. * merged isconvertable and is_equal into compare_defs(_ext)
  901. * made operator search faster by walking the list only once
  902. Revision 1.40 2002/09/27 21:13:28 carl
  903. * low-highval always checked if limit ober 2GB is reached (to avoid overflow)
  904. Revision 1.39 2002/09/01 18:44:17 peter
  905. * cleanup of tvecnode.det_resulttype
  906. * move 0 element of string access check to resulttype
  907. Revision 1.38 2002/09/01 13:28:38 daniel
  908. - write_access fields removed in favor of a flag
  909. Revision 1.37 2002/09/01 08:01:16 daniel
  910. * Removed sets from Tcallnode.det_resulttype
  911. + Added read/write notifications of variables. These will be usefull
  912. for providing information for several optimizations. For example
  913. the value of the loop variable of a for loop does matter is the
  914. variable is read after the for loop, but if it's no longer used
  915. or written, it doesn't matter and this can be used to optimize
  916. the loop code generation.
  917. Revision 1.36 2002/08/19 19:36:43 peter
  918. * More fixes for cross unit inlining, all tnodes are now implemented
  919. * Moved pocall_internconst to po_internconst because it is not a
  920. calling type at all and it conflicted when inlining of these small
  921. functions was requested
  922. Revision 1.35 2002/07/23 09:51:23 daniel
  923. * Tried to make Tprocsym.defs protected. I didn't succeed but the cleanups
  924. are worth comitting.
  925. Revision 1.34 2002/07/20 11:57:54 florian
  926. * types.pas renamed to defbase.pas because D6 contains a types
  927. unit so this would conflicts if D6 programms are compiled
  928. + Willamette/SSE2 instructions to assembler added
  929. Revision 1.33 2002/05/18 13:34:10 peter
  930. * readded missing revisions
  931. Revision 1.32 2002/05/16 19:46:39 carl
  932. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  933. + try to fix temp allocation (still in ifdef)
  934. + generic constructor calls
  935. + start of tassembler / tmodulebase class cleanup
  936. Revision 1.30 2002/05/12 16:53:07 peter
  937. * moved entry and exitcode to ncgutil and cgobj
  938. * foreach gets extra argument for passing local data to the
  939. iterator function
  940. * -CR checks also class typecasts at runtime by changing them
  941. into as
  942. * fixed compiler to cycle with the -CR option
  943. * fixed stabs with elf writer, finally the global variables can
  944. be watched
  945. * removed a lot of routines from cga unit and replaced them by
  946. calls to cgobj
  947. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  948. u32bit then the other is typecasted also to u32bit without giving
  949. a rangecheck warning/error.
  950. * fixed pascal calling method with reversing also the high tree in
  951. the parast, detected by tcalcst3 test
  952. Revision 1.29 2002/04/21 19:02:04 peter
  953. * removed newn and disposen nodes, the code is now directly
  954. inlined from pexpr
  955. * -an option that will write the secondpass nodes to the .s file, this
  956. requires EXTDEBUG define to actually write the info
  957. * fixed various internal errors and crashes due recent code changes
  958. Revision 1.28 2002/04/20 21:32:23 carl
  959. + generic FPC_CHECKPOINTER
  960. + first parameter offset in stack now portable
  961. * rename some constants
  962. + move some cpu stuff to other units
  963. - remove unused constents
  964. * fix stacksize for some targets
  965. * fix generic size problems which depend now on EXTEND_SIZE constant
  966. Revision 1.27 2002/04/02 17:11:29 peter
  967. * tlocation,treference update
  968. * LOC_CONSTANT added for better constant handling
  969. * secondadd splitted in multiple routines
  970. * location_force_reg added for loading a location to a register
  971. of a specified size
  972. * secondassignment parses now first the right and then the left node
  973. (this is compatible with Kylix). This saves a lot of push/pop especially
  974. with string operations
  975. * adapted some routines to use the new cg methods
  976. Revision 1.26 2002/04/01 20:57:13 jonas
  977. * fixed web bug 1907
  978. * fixed some other procvar related bugs (all related to accepting procvar
  979. constructs with either too many or too little parameters)
  980. (both merged, includes second typo fix of pexpr.pas)
  981. }