nmem.pas 35 KB

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