nmem.pas 40 KB

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