nmem.pas 36 KB

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