nmem.pas 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159
  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. { we need to process the parameters reverse so they are inserted
  354. in the correct right2left order (PFV) }
  355. hp2:=TParaItem(hp3.Para.last);
  356. while assigned(hp2) do
  357. begin
  358. tprocvardef(resulttype.def).concatpara(hp2.paratype,hp2.parasym,hp2.paratyp,hp2.defaultvalue);
  359. hp2:=TParaItem(hp2.previous);
  360. end;
  361. end
  362. else
  363. resulttype:=voidpointertype;
  364. end
  365. else
  366. begin
  367. { what are we getting the address from an absolute sym? }
  368. hp:=left;
  369. while assigned(hp) and (hp.nodetype in [vecn,derefn,subscriptn]) do
  370. hp:=tunarynode(hp).left;
  371. if assigned(hp) and (hp.nodetype=loadn) and
  372. ((tloadnode(hp).symtableentry.typ=absolutesym) and
  373. tabsolutesym(tloadnode(hp).symtableentry).absseg) then
  374. begin
  375. if not(cs_typed_addresses in aktlocalswitches) then
  376. resulttype:=voidfarpointertype
  377. else
  378. resulttype.setdef(tpointerdef.createfar(left.resulttype));
  379. end
  380. else
  381. begin
  382. if not(cs_typed_addresses in aktlocalswitches) then
  383. resulttype:=voidpointertype
  384. else
  385. resulttype.setdef(tpointerdef.create(left.resulttype));
  386. end;
  387. end;
  388. { this is like the function addr }
  389. inc(parsing_para_level);
  390. set_varstate(left,false);
  391. dec(parsing_para_level);
  392. end;
  393. function taddrnode.pass_1 : tnode;
  394. begin
  395. result:=nil;
  396. firstpass(left);
  397. if codegenerror then
  398. exit;
  399. make_not_regable(left);
  400. if nf_procvarload in flags then
  401. begin
  402. registers32:=left.registers32;
  403. registersfpu:=left.registersfpu;
  404. {$ifdef SUPPORT_MMX}
  405. registersmmx:=left.registersmmx;
  406. {$endif SUPPORT_MMX}
  407. if registers32<1 then
  408. registers32:=1;
  409. location.loc:=left.location.loc;
  410. exit;
  411. end;
  412. { we should allow loc_mem for @string }
  413. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  414. begin
  415. aktfilepos:=left.fileinfo;
  416. CGMessage(cg_e_illegal_expression);
  417. end;
  418. registers32:=left.registers32;
  419. registersfpu:=left.registersfpu;
  420. {$ifdef SUPPORT_MMX}
  421. registersmmx:=left.registersmmx;
  422. {$endif SUPPORT_MMX}
  423. if registers32<1 then
  424. registers32:=1;
  425. { is this right for object of methods ?? }
  426. location.loc:=LOC_REGISTER;
  427. end;
  428. {*****************************************************************************
  429. TDOUBLEADDRNODE
  430. *****************************************************************************}
  431. constructor tdoubleaddrnode.create(l : tnode);
  432. begin
  433. inherited create(doubleaddrn,l);
  434. end;
  435. function tdoubleaddrnode.det_resulttype:tnode;
  436. begin
  437. result:=nil;
  438. resulttypepass(left);
  439. if codegenerror then
  440. exit;
  441. inc(parsing_para_level);
  442. set_varstate(left,false);
  443. dec(parsing_para_level);
  444. if (left.resulttype.def.deftype)<>procvardef then
  445. CGMessage(cg_e_illegal_expression);
  446. resulttype:=voidpointertype;
  447. end;
  448. function tdoubleaddrnode.pass_1 : tnode;
  449. begin
  450. result:=nil;
  451. make_not_regable(left);
  452. firstpass(left);
  453. if codegenerror then
  454. exit;
  455. if (left.location.loc<>LOC_REFERENCE) then
  456. CGMessage(cg_e_illegal_expression);
  457. registers32:=left.registers32;
  458. registersfpu:=left.registersfpu;
  459. {$ifdef SUPPORT_MMX}
  460. registersmmx:=left.registersmmx;
  461. {$endif SUPPORT_MMX}
  462. if registers32<1 then
  463. registers32:=1;
  464. location.loc:=LOC_REGISTER;
  465. end;
  466. {*****************************************************************************
  467. TDEREFNODE
  468. *****************************************************************************}
  469. constructor tderefnode.create(l : tnode);
  470. begin
  471. inherited create(derefn,l);
  472. end;
  473. function tderefnode.det_resulttype:tnode;
  474. begin
  475. result:=nil;
  476. resulttypepass(left);
  477. set_varstate(left,true);
  478. if codegenerror then
  479. exit;
  480. if left.resulttype.def.deftype=pointerdef then
  481. resulttype:=tpointerdef(left.resulttype.def).pointertype
  482. else
  483. CGMessage(cg_e_invalid_qualifier);
  484. end;
  485. procedure Tderefnode.mark_write;
  486. begin
  487. include(flags,nf_write);
  488. end;
  489. function tderefnode.pass_1 : tnode;
  490. begin
  491. result:=nil;
  492. firstpass(left);
  493. if codegenerror then
  494. exit;
  495. registers32:=max(left.registers32,1);
  496. registersfpu:=left.registersfpu;
  497. {$ifdef SUPPORT_MMX}
  498. registersmmx:=left.registersmmx;
  499. {$endif SUPPORT_MMX}
  500. location.loc:=LOC_REFERENCE;
  501. end;
  502. {*****************************************************************************
  503. TSUBSCRIPTNODE
  504. *****************************************************************************}
  505. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  506. begin
  507. inherited create(subscriptn,l);
  508. { vs should be changed to tsym! }
  509. vs:=tvarsym(varsym);
  510. end;
  511. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  512. begin
  513. inherited ppuload(t,ppufile);
  514. vs:=tvarsym(ppufile.getderef);
  515. end;
  516. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  517. begin
  518. inherited ppuwrite(ppufile);
  519. ppufile.putderef(vs);
  520. end;
  521. procedure tsubscriptnode.derefimpl;
  522. begin
  523. inherited derefimpl;
  524. resolvesym(pointer(vs));
  525. end;
  526. function tsubscriptnode.getcopy : tnode;
  527. var
  528. p : tsubscriptnode;
  529. begin
  530. p:=tsubscriptnode(inherited getcopy);
  531. p.vs:=vs;
  532. getcopy:=p;
  533. end;
  534. function tsubscriptnode.det_resulttype:tnode;
  535. begin
  536. result:=nil;
  537. resulttypepass(left);
  538. resulttype:=vs.vartype;
  539. end;
  540. procedure Tsubscriptnode.mark_write;
  541. begin
  542. include(flags,nf_write);
  543. end;
  544. function tsubscriptnode.pass_1 : tnode;
  545. begin
  546. result:=nil;
  547. firstpass(left);
  548. if codegenerror then
  549. exit;
  550. registers32:=left.registers32;
  551. registersfpu:=left.registersfpu;
  552. {$ifdef SUPPORT_MMX}
  553. registersmmx:=left.registersmmx;
  554. {$endif SUPPORT_MMX}
  555. { classes must be dereferenced implicit }
  556. if is_class_or_interface(left.resulttype.def) then
  557. begin
  558. if registers32=0 then
  559. registers32:=1;
  560. location.loc:=LOC_REFERENCE;
  561. end
  562. else
  563. begin
  564. if (left.location.loc<>LOC_CREFERENCE) and
  565. (left.location.loc<>LOC_REFERENCE) then
  566. CGMessage(cg_e_illegal_expression);
  567. location.loc:=left.location.loc;
  568. end;
  569. end;
  570. function tsubscriptnode.docompare(p: tnode): boolean;
  571. begin
  572. docompare :=
  573. inherited docompare(p) and
  574. (vs = tsubscriptnode(p).vs);
  575. end;
  576. {*****************************************************************************
  577. TVECNODE
  578. *****************************************************************************}
  579. constructor tvecnode.create(l,r : tnode);
  580. begin
  581. inherited create(vecn,l,r);
  582. end;
  583. function tvecnode.det_resulttype:tnode;
  584. var
  585. htype : ttype;
  586. ct : tconverttype;
  587. begin
  588. result:=nil;
  589. resulttypepass(left);
  590. resulttypepass(right);
  591. if codegenerror then
  592. exit;
  593. { maybe type conversion for the index value, but
  594. do not convert enums,booleans,char }
  595. if (right.resulttype.def.deftype<>enumdef) and
  596. not(is_char(right.resulttype.def)) and
  597. not(is_boolean(right.resulttype.def)) then
  598. begin
  599. inserttypeconv(right,s32bittype);
  600. end;
  601. case left.resulttype.def.deftype of
  602. arraydef :
  603. begin
  604. { check type of the index value }
  605. if (compare_defs(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,right.nodetype)=te_incompatible) then
  606. CGMessage(type_e_mismatch);
  607. resulttype:=tarraydef(left.resulttype.def).elementtype;
  608. end;
  609. pointerdef :
  610. begin
  611. { are we accessing a pointer[], then convert the pointer to
  612. an array first, in FPC this is allowed for all pointers in
  613. delphi/tp7 it's only allowed for pchars }
  614. if (m_fpc in aktmodeswitches) or
  615. is_pchar(left.resulttype.def) or
  616. is_pwidechar(left.resulttype.def) then
  617. begin
  618. { convert pointer to array }
  619. htype.setdef(tarraydef.create(0,$7fffffff,s32bittype));
  620. tarraydef(htype.def).setelementtype(tpointerdef(left.resulttype.def).pointertype);
  621. inserttypeconv(left,htype);
  622. resulttype:=tarraydef(htype.def).elementtype;
  623. end
  624. else
  625. CGMessage(type_e_array_required);
  626. end;
  627. stringdef :
  628. begin
  629. { indexed access to 0 element is only allowed for shortstrings }
  630. if (right.nodetype=ordconstn) and
  631. (tordconstnode(right).value=0) and
  632. not(is_shortstring(left.resulttype.def)) then
  633. CGMessage(cg_e_can_access_element_zero);
  634. case tstringdef(left.resulttype.def).string_typ of
  635. st_widestring :
  636. resulttype:=cwidechartype;
  637. st_ansistring :
  638. resulttype:=cchartype;
  639. st_longstring :
  640. resulttype:=cchartype;
  641. st_shortstring :
  642. resulttype:=cchartype;
  643. end;
  644. end
  645. else
  646. CGMessage(type_e_array_required);
  647. end;
  648. end;
  649. procedure Tvecnode.mark_write;
  650. begin
  651. include(flags,nf_write);
  652. end;
  653. function tvecnode.pass_1 : tnode;
  654. {$ifdef consteval}
  655. var
  656. tcsym : ttypedconstsym;
  657. {$endif}
  658. begin
  659. result:=nil;
  660. firstpass(left);
  661. firstpass(right);
  662. if codegenerror then
  663. exit;
  664. { the register calculation is easy if a const index is used }
  665. if right.nodetype=ordconstn then
  666. begin
  667. {$ifdef consteval}
  668. { constant evaluation }
  669. if (left.nodetype=loadn) and
  670. (left.symtableentry.typ=typedconstsym) then
  671. begin
  672. tcsym:=ttypedconstsym(left.symtableentry);
  673. if tcsym.defintion^.typ=stringdef then
  674. begin
  675. end;
  676. end;
  677. {$endif}
  678. registers32:=left.registers32;
  679. { for ansi/wide strings, we need at least one register }
  680. if is_ansistring(left.resulttype.def) or
  681. is_widestring(left.resulttype.def) or
  682. { ... as well as for dynamic arrays }
  683. is_dynamic_array(left.resulttype.def) then
  684. registers32:=max(registers32,1);
  685. end
  686. else
  687. begin
  688. { this rules are suboptimal, but they should give }
  689. { good results }
  690. registers32:=max(left.registers32,right.registers32);
  691. { for ansi/wide strings, we need at least one register }
  692. if is_ansistring(left.resulttype.def) or
  693. is_widestring(left.resulttype.def) or
  694. { ... as well as for dynamic arrays }
  695. is_dynamic_array(left.resulttype.def) then
  696. registers32:=max(registers32,1);
  697. { need we an extra register when doing the restore ? }
  698. if (left.registers32<=right.registers32) and
  699. { only if the node needs less than 3 registers }
  700. { two for the right node and one for the }
  701. { left address }
  702. (registers32<3) then
  703. inc(registers32);
  704. { need we an extra register for the index ? }
  705. if (right.location.loc<>LOC_REGISTER)
  706. { only if the right node doesn't need a register }
  707. and (right.registers32<1) then
  708. inc(registers32);
  709. { not correct, but what works better ?
  710. if left.registers32>0 then
  711. registers32:=max(registers32,2)
  712. else
  713. min. one register
  714. registers32:=max(registers32,1);
  715. }
  716. end;
  717. registersfpu:=max(left.registersfpu,right.registersfpu);
  718. {$ifdef SUPPORT_MMX}
  719. registersmmx:=max(left.registersmmx,right.registersmmx);
  720. {$endif SUPPORT_MMX}
  721. if left.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
  722. location.loc:=LOC_REFERENCE
  723. else
  724. location.loc:=LOC_CREFERENCE;
  725. end;
  726. {*****************************************************************************
  727. TSELFNODE
  728. *****************************************************************************}
  729. constructor tselfnode.create(_class : tdef);
  730. begin
  731. inherited create(selfn);
  732. classdef:=_class;
  733. end;
  734. constructor tselfnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  735. begin
  736. inherited ppuload(t,ppufile);
  737. classdef:=tdef(ppufile.getderef);
  738. end;
  739. procedure tselfnode.ppuwrite(ppufile:tcompilerppufile);
  740. begin
  741. inherited ppuwrite(ppufile);
  742. ppufile.putderef(classdef);
  743. end;
  744. procedure tselfnode.derefimpl;
  745. begin
  746. inherited derefimpl;
  747. resolvedef(pointer(classdef));
  748. end;
  749. function tselfnode.det_resulttype:tnode;
  750. begin
  751. result:=nil;
  752. resulttype.setdef(classdef);
  753. end;
  754. function tselfnode.pass_1 : tnode;
  755. begin
  756. result:=nil;
  757. if (resulttype.def.deftype=classrefdef) or
  758. is_class(resulttype.def) then
  759. location.loc:=LOC_CREGISTER
  760. else
  761. location.loc:=LOC_REFERENCE;
  762. end;
  763. {*****************************************************************************
  764. TWITHNODE
  765. *****************************************************************************}
  766. constructor twithnode.create(symtable : twithsymtable;l,r : tnode;count : longint);
  767. begin
  768. inherited create(withn,l,r);
  769. withsymtable:=symtable;
  770. tablecount:=count;
  771. FillChar(withreference,sizeof(withreference),0);
  772. set_file_line(l);
  773. end;
  774. destructor twithnode.destroy;
  775. var
  776. hsymt,
  777. symt : tsymtable;
  778. i : longint;
  779. begin
  780. symt:=withsymtable;
  781. for i:=1 to tablecount do
  782. begin
  783. if assigned(symt) then
  784. begin
  785. hsymt:=symt.next;
  786. symt.free;
  787. symt:=hsymt;
  788. end;
  789. end;
  790. inherited destroy;
  791. end;
  792. constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  793. begin
  794. inherited ppuload(t,ppufile);
  795. internalerror(200208192);
  796. end;
  797. procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
  798. begin
  799. inherited ppuwrite(ppufile);
  800. internalerror(200208193);
  801. end;
  802. function twithnode.getcopy : tnode;
  803. var
  804. p : twithnode;
  805. begin
  806. p:=twithnode(inherited getcopy);
  807. p.withsymtable:=withsymtable;
  808. p.tablecount:=tablecount;
  809. p.withreference:=withreference;
  810. result:=p;
  811. end;
  812. function twithnode.det_resulttype:tnode;
  813. var
  814. symtable : tsymtable;
  815. i : longint;
  816. begin
  817. result:=nil;
  818. resulttype:=voidtype;
  819. if assigned(left) and assigned(right) then
  820. begin
  821. resulttypepass(left);
  822. unset_varstate(left);
  823. set_varstate(left,true);
  824. if codegenerror then
  825. exit;
  826. symtable:=withsymtable;
  827. for i:=1 to tablecount do
  828. begin
  829. if (left.nodetype=loadn) and
  830. (tloadnode(left).symtable=aktprocdef.localst) then
  831. twithsymtable(symtable).direct_with:=true;
  832. twithsymtable(symtable).withnode:=self;
  833. symtable:=symtable.next;
  834. end;
  835. resulttypepass(right);
  836. if codegenerror then
  837. exit;
  838. end;
  839. resulttype:=voidtype;
  840. end;
  841. function twithnode.pass_1 : tnode;
  842. begin
  843. result:=nil;
  844. if assigned(left) and assigned(right) then
  845. begin
  846. firstpass(left);
  847. firstpass(right);
  848. if codegenerror then
  849. exit;
  850. left_right_max;
  851. end
  852. else
  853. begin
  854. { optimization }
  855. result:=nil;
  856. end;
  857. end;
  858. function twithnode.docompare(p: tnode): boolean;
  859. begin
  860. docompare :=
  861. inherited docompare(p) and
  862. (withsymtable = twithnode(p).withsymtable) and
  863. (tablecount = twithnode(p).tablecount);
  864. end;
  865. begin
  866. cloadvmtnode := tloadvmtnode;
  867. chnewnode := thnewnode;
  868. chdisposenode := thdisposenode;
  869. caddrnode := taddrnode;
  870. cdoubleaddrnode := tdoubleaddrnode;
  871. cderefnode := tderefnode;
  872. csubscriptnode := tsubscriptnode;
  873. cvecnode := tvecnode;
  874. cselfnode := tselfnode;
  875. cwithnode := twithnode;
  876. end.
  877. {
  878. $Log$
  879. Revision 1.43 2003-01-04 15:54:03 daniel
  880. * Fixed mark_write for @ operator
  881. (can happen when compiling @procvar:=nil (Delphi mode construction))
  882. Revision 1.42 2003/01/03 12:15:56 daniel
  883. * Removed ifdefs around notifications
  884. ifdefs around for loop optimizations remain
  885. Revision 1.41 2002/11/25 17:43:20 peter
  886. * splitted defbase in defutil,symutil,defcmp
  887. * merged isconvertable and is_equal into compare_defs(_ext)
  888. * made operator search faster by walking the list only once
  889. Revision 1.40 2002/09/27 21:13:28 carl
  890. * low-highval always checked if limit ober 2GB is reached (to avoid overflow)
  891. Revision 1.39 2002/09/01 18:44:17 peter
  892. * cleanup of tvecnode.det_resulttype
  893. * move 0 element of string access check to resulttype
  894. Revision 1.38 2002/09/01 13:28:38 daniel
  895. - write_access fields removed in favor of a flag
  896. Revision 1.37 2002/09/01 08:01:16 daniel
  897. * Removed sets from Tcallnode.det_resulttype
  898. + Added read/write notifications of variables. These will be usefull
  899. for providing information for several optimizations. For example
  900. the value of the loop variable of a for loop does matter is the
  901. variable is read after the for loop, but if it's no longer used
  902. or written, it doesn't matter and this can be used to optimize
  903. the loop code generation.
  904. Revision 1.36 2002/08/19 19:36:43 peter
  905. * More fixes for cross unit inlining, all tnodes are now implemented
  906. * Moved pocall_internconst to po_internconst because it is not a
  907. calling type at all and it conflicted when inlining of these small
  908. functions was requested
  909. Revision 1.35 2002/07/23 09:51:23 daniel
  910. * Tried to make Tprocsym.defs protected. I didn't succeed but the cleanups
  911. are worth comitting.
  912. Revision 1.34 2002/07/20 11:57:54 florian
  913. * types.pas renamed to defbase.pas because D6 contains a types
  914. unit so this would conflicts if D6 programms are compiled
  915. + Willamette/SSE2 instructions to assembler added
  916. Revision 1.33 2002/05/18 13:34:10 peter
  917. * readded missing revisions
  918. Revision 1.32 2002/05/16 19:46:39 carl
  919. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  920. + try to fix temp allocation (still in ifdef)
  921. + generic constructor calls
  922. + start of tassembler / tmodulebase class cleanup
  923. Revision 1.30 2002/05/12 16:53:07 peter
  924. * moved entry and exitcode to ncgutil and cgobj
  925. * foreach gets extra argument for passing local data to the
  926. iterator function
  927. * -CR checks also class typecasts at runtime by changing them
  928. into as
  929. * fixed compiler to cycle with the -CR option
  930. * fixed stabs with elf writer, finally the global variables can
  931. be watched
  932. * removed a lot of routines from cga unit and replaced them by
  933. calls to cgobj
  934. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  935. u32bit then the other is typecasted also to u32bit without giving
  936. a rangecheck warning/error.
  937. * fixed pascal calling method with reversing also the high tree in
  938. the parast, detected by tcalcst3 test
  939. Revision 1.29 2002/04/21 19:02:04 peter
  940. * removed newn and disposen nodes, the code is now directly
  941. inlined from pexpr
  942. * -an option that will write the secondpass nodes to the .s file, this
  943. requires EXTDEBUG define to actually write the info
  944. * fixed various internal errors and crashes due recent code changes
  945. Revision 1.28 2002/04/20 21:32:23 carl
  946. + generic FPC_CHECKPOINTER
  947. + first parameter offset in stack now portable
  948. * rename some constants
  949. + move some cpu stuff to other units
  950. - remove unused constents
  951. * fix stacksize for some targets
  952. * fix generic size problems which depend now on EXTEND_SIZE constant
  953. Revision 1.27 2002/04/02 17:11:29 peter
  954. * tlocation,treference update
  955. * LOC_CONSTANT added for better constant handling
  956. * secondadd splitted in multiple routines
  957. * location_force_reg added for loading a location to a register
  958. of a specified size
  959. * secondassignment parses now first the right and then the left node
  960. (this is compatible with Kylix). This saves a lot of push/pop especially
  961. with string operations
  962. * adapted some routines to use the new cg methods
  963. Revision 1.26 2002/04/01 20:57:13 jonas
  964. * fixed web bug 1907
  965. * fixed some other procvar related bugs (all related to accepting procvar
  966. constructs with either too many or too little parameters)
  967. (both merged, includes second typo fix of pexpr.pas)
  968. }