nmem.pas 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  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. symdef,symsym,symtable,symtype;
  24. type
  25. tloadvmtaddrnode = class(tunarynode)
  26. constructor create(l : tnode);virtual;
  27. function pass_1 : tnode;override;
  28. function det_resulttype:tnode;override;
  29. end;
  30. tloadvmtaddrnodeclass = class of tloadvmtaddrnode;
  31. tloadparentfpnode = class(tunarynode)
  32. parentpd : tprocdef;
  33. parentpdderef : tderef;
  34. constructor create(pd:tprocdef);virtual;
  35. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  36. procedure ppuwrite(ppufile:tcompilerppufile);override;
  37. procedure buildderefimpl;override;
  38. procedure derefimpl;override;
  39. function pass_1 : tnode;override;
  40. function det_resulttype:tnode;override;
  41. function getcopy : tnode;override;
  42. end;
  43. tloadparentfpnodeclass = class of tloadparentfpnode;
  44. taddrnode = class(tunarynode)
  45. getprocvardef : tprocvardef;
  46. getprocvardefderef : tderef;
  47. constructor create(l : tnode);virtual;
  48. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  49. procedure ppuwrite(ppufile:tcompilerppufile);override;
  50. procedure mark_write;override;
  51. procedure buildderefimpl;override;
  52. procedure derefimpl;override;
  53. function getcopy : tnode;override;
  54. function pass_1 : tnode;override;
  55. function det_resulttype:tnode;override;
  56. end;
  57. taddrnodeclass = class of taddrnode;
  58. tderefnode = class(tunarynode)
  59. constructor create(l : tnode);virtual;
  60. function pass_1 : tnode;override;
  61. function det_resulttype:tnode;override;
  62. procedure mark_write;override;
  63. end;
  64. tderefnodeclass = class of tderefnode;
  65. tsubscriptnode = class(tunarynode)
  66. vs : tfieldvarsym;
  67. vsderef : tderef;
  68. constructor create(varsym : tsym;l : tnode);virtual;
  69. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  70. procedure ppuwrite(ppufile:tcompilerppufile);override;
  71. procedure buildderefimpl;override;
  72. procedure derefimpl;override;
  73. function getcopy : tnode;override;
  74. function pass_1 : tnode;override;
  75. function docompare(p: tnode): boolean; override;
  76. function det_resulttype:tnode;override;
  77. procedure mark_write;override;
  78. end;
  79. tsubscriptnodeclass = class of tsubscriptnode;
  80. tvecnode = class(tbinarynode)
  81. constructor create(l,r : tnode);virtual;
  82. function pass_1 : tnode;override;
  83. function det_resulttype:tnode;override;
  84. procedure mark_write;override;
  85. end;
  86. tvecnodeclass = class of tvecnode;
  87. twithnode = class(tunarynode)
  88. withsymtable : twithsymtable;
  89. tablecount : longint;
  90. withrefnode : tnode;
  91. constructor create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
  92. destructor destroy;override;
  93. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  94. procedure ppuwrite(ppufile:tcompilerppufile);override;
  95. function getcopy : tnode;override;
  96. function pass_1 : tnode;override;
  97. function docompare(p: tnode): boolean; override;
  98. function det_resulttype:tnode;override;
  99. end;
  100. twithnodeclass = class of twithnode;
  101. var
  102. cloadvmtaddrnode : tloadvmtaddrnodeclass;
  103. cloadparentfpnode : tloadparentfpnodeclass;
  104. caddrnode : taddrnodeclass;
  105. cderefnode : tderefnodeclass;
  106. csubscriptnode : tsubscriptnodeclass;
  107. cvecnode : tvecnodeclass;
  108. cwithnode : twithnodeclass;
  109. implementation
  110. uses
  111. globtype,systems,
  112. cutils,cclasses,verbose,globals,
  113. symconst,symbase,defutil,defcmp,
  114. nbas,nutils,
  115. htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase,procinfo
  116. ;
  117. {*****************************************************************************
  118. TLOADVMTADDRNODE
  119. *****************************************************************************}
  120. constructor tloadvmtaddrnode.create(l : tnode);
  121. begin
  122. inherited create(loadvmtaddrn,l);
  123. end;
  124. function tloadvmtaddrnode.det_resulttype:tnode;
  125. begin
  126. result:=nil;
  127. resulttypepass(left);
  128. if codegenerror then
  129. exit;
  130. case left.resulttype.def.deftype of
  131. classrefdef :
  132. resulttype:=left.resulttype;
  133. objectdef :
  134. resulttype.setdef(tclassrefdef.create(left.resulttype));
  135. else
  136. Message(parser_e_pointer_to_class_expected);
  137. end;
  138. end;
  139. function tloadvmtaddrnode.pass_1 : tnode;
  140. begin
  141. result:=nil;
  142. expectloc:=LOC_REGISTER;
  143. if left.nodetype<>typen then
  144. begin
  145. firstpass(left);
  146. registersint:=left.registersint;
  147. end;
  148. if registersint<1 then
  149. registersint:=1;
  150. end;
  151. {*****************************************************************************
  152. TLOADPARENTFPNODE
  153. *****************************************************************************}
  154. constructor tloadparentfpnode.create(pd:tprocdef);
  155. begin
  156. inherited create(loadparentfpn,nil);
  157. if not assigned(pd) then
  158. internalerror(200309288);
  159. if (pd.parast.symtablelevel>current_procinfo.procdef.parast.symtablelevel) then
  160. internalerror(200309284);
  161. parentpd:=pd;
  162. end;
  163. constructor tloadparentfpnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  164. begin
  165. inherited ppuload(t,ppufile);
  166. ppufile.getderef(parentpdderef);
  167. end;
  168. procedure tloadparentfpnode.ppuwrite(ppufile:tcompilerppufile);
  169. begin
  170. inherited ppuwrite(ppufile);
  171. ppufile.putderef(parentpdderef);
  172. end;
  173. procedure tloadparentfpnode.buildderefimpl;
  174. begin
  175. inherited buildderefimpl;
  176. parentpdderef.build(parentpd);
  177. end;
  178. procedure tloadparentfpnode.derefimpl;
  179. begin
  180. inherited derefimpl;
  181. parentpd:=tprocdef(parentpdderef.resolve);
  182. end;
  183. function tloadparentfpnode.getcopy : tnode;
  184. var
  185. p : tloadparentfpnode;
  186. begin
  187. p:=tloadparentfpnode(inherited getcopy);
  188. p.parentpd:=parentpd;
  189. getcopy:=p;
  190. end;
  191. function tloadparentfpnode.det_resulttype:tnode;
  192. begin
  193. result:=nil;
  194. resulttype:=voidpointertype;
  195. end;
  196. function tloadparentfpnode.pass_1 : tnode;
  197. begin
  198. result:=nil;
  199. expectloc:=LOC_REGISTER;
  200. registersint:=1;
  201. end;
  202. {*****************************************************************************
  203. TADDRNODE
  204. *****************************************************************************}
  205. constructor taddrnode.create(l : tnode);
  206. begin
  207. inherited create(addrn,l);
  208. getprocvardef:=nil;
  209. end;
  210. constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  211. begin
  212. inherited ppuload(t,ppufile);
  213. ppufile.getderef(getprocvardefderef);
  214. end;
  215. procedure taddrnode.ppuwrite(ppufile:tcompilerppufile);
  216. begin
  217. inherited ppuwrite(ppufile);
  218. ppufile.putderef(getprocvardefderef);
  219. end;
  220. procedure Taddrnode.mark_write;
  221. begin
  222. {@procvar:=nil is legal in Delphi mode.}
  223. left.mark_write;
  224. end;
  225. procedure taddrnode.buildderefimpl;
  226. begin
  227. inherited buildderefimpl;
  228. getprocvardefderef.build(getprocvardef);
  229. end;
  230. procedure taddrnode.derefimpl;
  231. begin
  232. inherited derefimpl;
  233. getprocvardef:=tprocvardef(getprocvardefderef.resolve);
  234. end;
  235. function taddrnode.getcopy : tnode;
  236. var
  237. p : taddrnode;
  238. begin
  239. p:=taddrnode(inherited getcopy);
  240. p.getprocvardef:=getprocvardef;
  241. getcopy:=p;
  242. end;
  243. procedure copyparasym(p:TNamedIndexItem;arg:pointer);
  244. var
  245. newparast : tsymtable absolute arg;
  246. vs : tparavarsym;
  247. begin
  248. if tsym(p).typ<>paravarsym then
  249. exit;
  250. with tparavarsym(p) do
  251. begin
  252. vs:=tparavarsym.create(realname,paranr,varspez,vartype);
  253. vs.varoptions:=varoptions;
  254. // vs.paraloc[callerside]:=paraloc[callerside].getcopy;
  255. // vs.paraloc[callerside]:=paraloc[callerside].getcopy;
  256. vs.defaultconstsym:=defaultconstsym;
  257. newparast.insert(vs);
  258. end;
  259. end;
  260. function taddrnode.det_resulttype:tnode;
  261. var
  262. hp : tnode;
  263. hp2 : TParavarsym;
  264. hp3 : tabstractprocdef;
  265. begin
  266. result:=nil;
  267. resulttypepass(left);
  268. if codegenerror then
  269. exit;
  270. make_not_regable(left);
  271. { don't allow constants }
  272. if is_constnode(left) then
  273. begin
  274. aktfilepos:=left.fileinfo;
  275. CGMessage(type_e_no_addr_of_constant);
  276. exit;
  277. end;
  278. { tp @procvar support (type of @procvar is a void pointer)
  279. Note: we need to leave the addrn in the tree,
  280. else we can't see the difference between @procvar and procvar.
  281. we set the procvarload flag so a secondpass does nothing for
  282. this node (PFV) }
  283. if (m_tp_procvar in aktmodeswitches) then
  284. begin
  285. case left.nodetype of
  286. calln :
  287. begin
  288. { a load of a procvar can't have parameters }
  289. if assigned(tcallnode(left).left) then
  290. CGMessage(parser_e_illegal_expression);
  291. { is it a procvar? }
  292. hp:=tcallnode(left).right;
  293. if assigned(hp) then
  294. begin
  295. { remove calln node }
  296. tcallnode(left).right:=nil;
  297. left.free;
  298. left:=hp;
  299. include(flags,nf_procvarload);
  300. end;
  301. end;
  302. loadn,
  303. subscriptn,
  304. typeconvn,
  305. vecn,
  306. derefn :
  307. begin
  308. if left.resulttype.def.deftype=procvardef then
  309. include(flags,nf_procvarload);
  310. end;
  311. end;
  312. if nf_procvarload in flags then
  313. begin
  314. resulttype:=voidpointertype;
  315. exit;
  316. end;
  317. end;
  318. { proc 2 procvar ? }
  319. if left.nodetype=calln then
  320. { if it were a valid construct, the addr node would already have }
  321. { been removed in the parser. This happens for (in FPC mode) }
  322. { procvar1 := @procvar2(parameters); }
  323. CGMessage(parser_e_illegal_expression)
  324. else
  325. if (left.nodetype=loadn) and (tloadnode(left).symtableentry.typ=procsym) then
  326. begin
  327. { the address is already available when loading a procedure of object }
  328. if assigned(tloadnode(left).left) then
  329. include(flags,nf_procvarload);
  330. { result is a procedure variable }
  331. { No, to be TP compatible, you must return a voidpointer to
  332. the procedure that is stored in the procvar.}
  333. if not(m_tp_procvar in aktmodeswitches) then
  334. begin
  335. if assigned(getprocvardef) and
  336. (tprocsym(tloadnode(left).symtableentry).procdef_count>1) then
  337. begin
  338. hp3:=tprocsym(tloadnode(left).symtableentry).search_procdef_byprocvardef(getprocvardef);
  339. if not assigned(hp3) then
  340. begin
  341. IncompatibleTypes(tprocsym(tloadnode(left).symtableentry).first_procdef,getprocvardef);
  342. exit;
  343. end;
  344. end
  345. else
  346. hp3:=tabstractprocdef(tprocsym(tloadnode(left).symtableentry).first_procdef);
  347. { create procvardef }
  348. resulttype.setdef(tprocvardef.create(hp3.parast.symtablelevel));
  349. tprocvardef(resulttype.def).proctypeoption:=hp3.proctypeoption;
  350. tprocvardef(resulttype.def).proccalloption:=hp3.proccalloption;
  351. tprocvardef(resulttype.def).procoptions:=hp3.procoptions;
  352. tprocvardef(resulttype.def).rettype:=hp3.rettype;
  353. { method ? then set the methodpointer flag }
  354. if (hp3.owner.symtabletype=objectsymtable) then
  355. include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
  356. { only need the address of the method? this is needed
  357. for @tobject.create }
  358. if not assigned(tloadnode(left).left) then
  359. include(tprocvardef(resulttype.def).procoptions,po_addressonly);
  360. { Add parameters use only references, we don't need to keep the
  361. parast. We use the parast from the original function to calculate
  362. our parameter data and reset it afterwards }
  363. hp3.parast.foreach_static(@copyparasym,tprocvardef(resulttype.def).parast);
  364. tprocvardef(resulttype.def).calcparas;
  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. {$ifdef i386}
  376. if assigned(hp) and
  377. (hp.nodetype=loadn) and
  378. ((tloadnode(hp).symtableentry.typ=absolutevarsym) and
  379. tabsolutevarsym(tloadnode(hp).symtableentry).absseg) then
  380. begin
  381. if not(nf_typedaddr in flags) then
  382. resulttype:=voidfarpointertype
  383. else
  384. resulttype.setdef(tpointerdef.createfar(left.resulttype));
  385. end
  386. else
  387. {$endif i386}
  388. begin
  389. if not(nf_typedaddr in flags) then
  390. resulttype:=voidpointertype
  391. else
  392. resulttype.setdef(tpointerdef.create(left.resulttype));
  393. end;
  394. end;
  395. { this is like the function addr }
  396. inc(parsing_para_level);
  397. set_varstate(left,vs_used,false);
  398. dec(parsing_para_level);
  399. end;
  400. function taddrnode.pass_1 : tnode;
  401. begin
  402. result:=nil;
  403. firstpass(left);
  404. if codegenerror then
  405. exit;
  406. if nf_procvarload in flags then
  407. begin
  408. registersint:=left.registersint;
  409. registersfpu:=left.registersfpu;
  410. {$ifdef SUPPORT_MMX}
  411. registersmmx:=left.registersmmx;
  412. {$endif SUPPORT_MMX}
  413. if registersint<1 then
  414. registersint:=1;
  415. expectloc:=left.expectloc;
  416. exit;
  417. end;
  418. { we should allow loc_mem for @string }
  419. if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  420. begin
  421. aktfilepos:=left.fileinfo;
  422. CGMessage(parser_e_illegal_expression);
  423. end;
  424. registersint:=left.registersint;
  425. registersfpu:=left.registersfpu;
  426. {$ifdef SUPPORT_MMX}
  427. registersmmx:=left.registersmmx;
  428. {$endif SUPPORT_MMX}
  429. if registersint<1 then
  430. registersint:=1;
  431. { is this right for object of methods ?? }
  432. expectloc:=LOC_REGISTER;
  433. end;
  434. {*****************************************************************************
  435. TDEREFNODE
  436. *****************************************************************************}
  437. constructor tderefnode.create(l : tnode);
  438. begin
  439. inherited create(derefn,l);
  440. end;
  441. function tderefnode.det_resulttype:tnode;
  442. begin
  443. result:=nil;
  444. resulttypepass(left);
  445. set_varstate(left,vs_used,true);
  446. if codegenerror then
  447. exit;
  448. { tp procvar support }
  449. maybe_call_procvar(left,true);
  450. if left.resulttype.def.deftype=pointerdef then
  451. resulttype:=tpointerdef(left.resulttype.def).pointertype
  452. else
  453. CGMessage(parser_e_invalid_qualifier);
  454. end;
  455. procedure Tderefnode.mark_write;
  456. begin
  457. include(flags,nf_write);
  458. end;
  459. function tderefnode.pass_1 : tnode;
  460. begin
  461. result:=nil;
  462. firstpass(left);
  463. if codegenerror then
  464. exit;
  465. registersint:=max(left.registersint,1);
  466. registersfpu:=left.registersfpu;
  467. {$ifdef SUPPORT_MMX}
  468. registersmmx:=left.registersmmx;
  469. {$endif SUPPORT_MMX}
  470. expectloc:=LOC_REFERENCE;
  471. end;
  472. {*****************************************************************************
  473. TSUBSCRIPTNODE
  474. *****************************************************************************}
  475. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  476. begin
  477. inherited create(subscriptn,l);
  478. { vs should be changed to tsym! }
  479. vs:=tfieldvarsym(varsym);
  480. end;
  481. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  482. begin
  483. inherited ppuload(t,ppufile);
  484. ppufile.getderef(vsderef);
  485. end;
  486. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  487. begin
  488. inherited ppuwrite(ppufile);
  489. ppufile.putderef(vsderef);
  490. end;
  491. procedure tsubscriptnode.buildderefimpl;
  492. begin
  493. inherited buildderefimpl;
  494. vsderef.build(vs);
  495. end;
  496. procedure tsubscriptnode.derefimpl;
  497. begin
  498. inherited derefimpl;
  499. vs:=tfieldvarsym(vsderef.resolve);
  500. end;
  501. function tsubscriptnode.getcopy : tnode;
  502. var
  503. p : tsubscriptnode;
  504. begin
  505. p:=tsubscriptnode(inherited getcopy);
  506. p.vs:=vs;
  507. getcopy:=p;
  508. end;
  509. function tsubscriptnode.det_resulttype:tnode;
  510. begin
  511. result:=nil;
  512. resulttypepass(left);
  513. { tp procvar support }
  514. maybe_call_procvar(left,true);
  515. resulttype:=vs.vartype;
  516. end;
  517. procedure Tsubscriptnode.mark_write;
  518. begin
  519. include(flags,nf_write);
  520. end;
  521. function tsubscriptnode.pass_1 : tnode;
  522. begin
  523. result:=nil;
  524. firstpass(left);
  525. if codegenerror then
  526. exit;
  527. registersint:=left.registersint;
  528. registersfpu:=left.registersfpu;
  529. {$ifdef SUPPORT_MMX}
  530. registersmmx:=left.registersmmx;
  531. {$endif SUPPORT_MMX}
  532. { classes must be dereferenced implicit }
  533. if is_class_or_interface(left.resulttype.def) then
  534. begin
  535. if registersint=0 then
  536. registersint:=1;
  537. expectloc:=LOC_REFERENCE;
  538. end
  539. else
  540. begin
  541. if (left.expectloc<>LOC_CREFERENCE) and
  542. (left.expectloc<>LOC_REFERENCE) then
  543. CGMessage(parser_e_illegal_expression);
  544. expectloc:=left.expectloc;
  545. end;
  546. end;
  547. function tsubscriptnode.docompare(p: tnode): boolean;
  548. begin
  549. docompare :=
  550. inherited docompare(p) and
  551. (vs = tsubscriptnode(p).vs);
  552. end;
  553. {*****************************************************************************
  554. TVECNODE
  555. *****************************************************************************}
  556. constructor tvecnode.create(l,r : tnode);
  557. begin
  558. inherited create(vecn,l,r);
  559. end;
  560. function tvecnode.det_resulttype:tnode;
  561. var
  562. htype : ttype;
  563. valid : boolean;
  564. begin
  565. result:=nil;
  566. resulttypepass(left);
  567. resulttypepass(right);
  568. { In p[1] p is always valid, it is not possible to
  569. declared a shortstring or normal array that has
  570. undefined number of elements. Dynamic array and
  571. ansi/widestring needs to be valid }
  572. valid:=is_dynamic_array(left.resulttype.def) or
  573. is_ansistring(left.resulttype.def) or
  574. is_widestring(left.resulttype.def);
  575. set_varstate(left,vs_used,valid);
  576. set_varstate(right,vs_used,true);
  577. if codegenerror then
  578. exit;
  579. { maybe type conversion for the index value, but
  580. do not convert enums,booleans,char }
  581. if (right.resulttype.def.deftype<>enumdef) and
  582. not(is_char(right.resulttype.def)) and
  583. not(is_boolean(right.resulttype.def)) then
  584. begin
  585. inserttypeconv(right,s32inttype);
  586. end;
  587. case left.resulttype.def.deftype of
  588. arraydef :
  589. begin
  590. { check type of the index value }
  591. if (compare_defs(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,right.nodetype)=te_incompatible) then
  592. IncompatibleTypes(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def);
  593. resulttype:=tarraydef(left.resulttype.def).elementtype;
  594. end;
  595. pointerdef :
  596. begin
  597. { are we accessing a pointer[], then convert the pointer to
  598. an array first, in FPC this is allowed for all pointers in
  599. delphi/tp7 it's only allowed for pchars }
  600. if (m_fpc in aktmodeswitches) or
  601. is_pchar(left.resulttype.def) or
  602. is_pwidechar(left.resulttype.def) then
  603. begin
  604. { convert pointer to array }
  605. htype.setdef(tarraydef.create_from_pointer(tpointerdef(left.resulttype.def).pointertype));
  606. inserttypeconv(left,htype);
  607. resulttype:=tarraydef(htype.def).elementtype;
  608. end
  609. else
  610. CGMessage(type_e_array_required);
  611. end;
  612. stringdef :
  613. begin
  614. { indexed access to 0 element is only allowed for shortstrings }
  615. if (right.nodetype=ordconstn) and
  616. (tordconstnode(right).value=0) and
  617. not(is_shortstring(left.resulttype.def)) then
  618. CGMessage(cg_e_can_access_element_zero);
  619. case tstringdef(left.resulttype.def).string_typ of
  620. st_widestring :
  621. resulttype:=cwidechartype;
  622. {$ifdef ansistring_bits}
  623. st_ansistring16,st_ansistring32,st_ansistring64 :
  624. {$else}
  625. st_ansistring :
  626. {$endif}
  627. resulttype:=cchartype;
  628. st_longstring :
  629. resulttype:=cchartype;
  630. st_shortstring :
  631. resulttype:=cchartype;
  632. end;
  633. end;
  634. variantdef :
  635. resulttype:=cvarianttype;
  636. else
  637. CGMessage(type_e_array_required);
  638. end;
  639. end;
  640. procedure Tvecnode.mark_write;
  641. begin
  642. include(flags,nf_write);
  643. end;
  644. function tvecnode.pass_1 : tnode;
  645. {$ifdef consteval}
  646. var
  647. tcsym : ttypedconstsym;
  648. {$endif}
  649. begin
  650. result:=nil;
  651. firstpass(left);
  652. firstpass(right);
  653. if codegenerror then
  654. exit;
  655. if (nf_callunique in flags) and
  656. (is_ansistring(left.resulttype.def) or
  657. is_widestring(left.resulttype.def)) then
  658. begin
  659. left := ctypeconvnode.create_internal(ccallnode.createintern('fpc_'+tstringdef(left.resulttype.def).stringtypname+'_unique',
  660. ccallparanode.create(
  661. ctypeconvnode.create_internal(left,voidpointertype),nil)),
  662. left.resulttype);
  663. firstpass(left);
  664. { double resulttype passes somwhere else may cause this to be }
  665. { reset though :/ }
  666. exclude(flags,nf_callunique);
  667. end;
  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. registersint:=left.registersint;
  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. registersint:=max(registersint,1);
  689. end
  690. else
  691. begin
  692. { this rules are suboptimal, but they should give }
  693. { good results }
  694. registersint:=max(left.registersint,right.registersint);
  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. registersint:=max(registersint,1);
  701. { need we an extra register when doing the restore ? }
  702. if (left.registersint<=right.registersint) 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. (registersint<3) then
  707. inc(registersint);
  708. { need we an extra register for the index ? }
  709. if (right.expectloc<>LOC_REGISTER)
  710. { only if the right node doesn't need a register }
  711. and (right.registersint<1) then
  712. inc(registersint);
  713. { not correct, but what works better ?
  714. if left.registersint>0 then
  715. registersint:=max(registersint,2)
  716. else
  717. min. one register
  718. registersint:=max(registersint,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.expectloc=LOC_CREFERENCE then
  726. expectloc:=LOC_CREFERENCE
  727. else
  728. expectloc:=LOC_REFERENCE;
  729. end;
  730. {*****************************************************************************
  731. TWITHNODE
  732. *****************************************************************************}
  733. constructor twithnode.create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
  734. begin
  735. inherited create(withn,l);
  736. withrefnode:=r;
  737. withsymtable:=symtable;
  738. tablecount:=count;
  739. set_file_line(l);
  740. end;
  741. destructor twithnode.destroy;
  742. var
  743. hsymt,
  744. symt : tsymtable;
  745. i : longint;
  746. begin
  747. symt:=withsymtable;
  748. for i:=1 to tablecount do
  749. begin
  750. if assigned(symt) then
  751. begin
  752. hsymt:=symt.next;
  753. symt.free;
  754. symt:=hsymt;
  755. end;
  756. end;
  757. inherited destroy;
  758. end;
  759. constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  760. begin
  761. inherited ppuload(t,ppufile);
  762. internalerror(200208192);
  763. end;
  764. procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
  765. begin
  766. inherited ppuwrite(ppufile);
  767. internalerror(200208193);
  768. end;
  769. function twithnode.getcopy : tnode;
  770. var
  771. p : twithnode;
  772. begin
  773. p:=twithnode(inherited getcopy);
  774. p.withsymtable:=withsymtable;
  775. p.tablecount:=tablecount;
  776. if assigned(p.withrefnode) then
  777. p.withrefnode:=withrefnode.getcopy
  778. else
  779. p.withrefnode:=nil;
  780. result:=p;
  781. end;
  782. function twithnode.det_resulttype:tnode;
  783. begin
  784. result:=nil;
  785. resulttype:=voidtype;
  786. resulttypepass(withrefnode);
  787. //unset_varstate(withrefnode);
  788. set_varstate(withrefnode,vs_used,true);
  789. if codegenerror then
  790. exit;
  791. if (withrefnode.nodetype=vecn) and
  792. (nf_memseg in withrefnode.flags) then
  793. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  794. if assigned(left) then
  795. resulttypepass(left);
  796. end;
  797. function twithnode.pass_1 : tnode;
  798. begin
  799. result:=nil;
  800. expectloc:=LOC_VOID;
  801. if assigned(left) then
  802. begin
  803. firstpass(left);
  804. registersint:=left.registersint;
  805. registersfpu:=left.registersfpu;
  806. {$ifdef SUPPORT_MMX}
  807. registersmmx:=left.registersmmx;
  808. {$endif SUPPORT_MMX}
  809. end;
  810. if assigned(withrefnode) then
  811. begin
  812. firstpass(withrefnode);
  813. if withrefnode.registersint > registersint then
  814. registersint:=withrefnode.registersint;
  815. if withrefnode.registersfpu > registersfpu then
  816. registersint:=withrefnode.registersfpu;
  817. {$ifdef SUPPORT_MMX}
  818. if withrefnode.registersmmx > registersmmx then
  819. registersmmx:=withrefnode.registersmmx;
  820. {$endif SUPPORT_MMX}
  821. end;
  822. end;
  823. function twithnode.docompare(p: tnode): boolean;
  824. begin
  825. docompare :=
  826. inherited docompare(p) and
  827. (withsymtable = twithnode(p).withsymtable) and
  828. (tablecount = twithnode(p).tablecount) and
  829. (withrefnode.isequal(twithnode(p).withrefnode));
  830. end;
  831. begin
  832. cloadvmtaddrnode := tloadvmtaddrnode;
  833. caddrnode := taddrnode;
  834. cderefnode := tderefnode;
  835. csubscriptnode := tsubscriptnode;
  836. cvecnode := tvecnode;
  837. cwithnode := twithnode;
  838. end.
  839. {
  840. $Log$
  841. Revision 1.89 2004-11-15 23:35:31 peter
  842. * tparaitem removed, use tparavarsym instead
  843. * parameter order is now calculated from paranr value in tparavarsym
  844. Revision 1.88 2004/11/08 22:09:59 peter
  845. * tvarsym splitted
  846. Revision 1.87 2004/11/02 12:55:16 peter
  847. * nf_internal flag for internal inserted typeconvs. This will
  848. supress the generation of warning/hints
  849. Revision 1.86 2004/09/26 17:45:30 peter
  850. * simple regvar support, not yet finished
  851. Revision 1.85 2004/06/20 08:55:29 florian
  852. * logs truncated
  853. Revision 1.84 2004/06/16 20:07:09 florian
  854. * dwarf branch merged
  855. Revision 1.83 2004/04/29 19:56:37 daniel
  856. * Prepare compiler infrastructure for multiple ansistring types
  857. Revision 1.82.2.1 2004/04/28 19:55:51 peter
  858. * new warning for ordinal-pointer when size is different
  859. * fixed some cg_e_ messages to the correct section type_e_ or parser_e_
  860. Revision 1.82 2004/03/29 14:42:52 peter
  861. * variant array support
  862. Revision 1.81 2004/03/18 16:19:03 peter
  863. * fixed operator overload allowing for pointer-string
  864. * replaced some type_e_mismatch with more informational messages
  865. }