nmem.pas 38 KB

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