nmem.pas 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. {
  2. $Id$
  3. Copyright (c) 2000 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 defines.inc}
  20. interface
  21. uses
  22. node,
  23. symtype,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. constructor create;virtual;
  34. function pass_1 : tnode;override;
  35. function det_resulttype:tnode;override;
  36. end;
  37. thnewnodeclass = class of thnewnode;
  38. tnewnode = class(tunarynode)
  39. constructor create(l : tnode);virtual;
  40. function pass_1 : tnode;override;
  41. function det_resulttype:tnode;override;
  42. end;
  43. tnewnodeclass = class of tnewnode;
  44. thdisposenode = class(tunarynode)
  45. constructor create(l : tnode);virtual;
  46. function pass_1 : tnode;override;
  47. function det_resulttype:tnode;override;
  48. end;
  49. thdisposenodeclass = class of thdisposenode;
  50. tsimplenewdisposenode = class(tunarynode)
  51. constructor create(n : tnodetype;l : tnode);
  52. function pass_1 : tnode;override;
  53. function det_resulttype:tnode;override;
  54. end;
  55. tsimplenewdisposenodeclass = class of tsimplenewdisposenode;
  56. taddrnode = class(tunarynode)
  57. getprocvardef : tprocvardef;
  58. constructor create(l : tnode);virtual;
  59. function pass_1 : tnode;override;
  60. function det_resulttype:tnode;override;
  61. end;
  62. taddrnodeclass = class of taddrnode;
  63. tdoubleaddrnode = class(tunarynode)
  64. constructor create(l : tnode);virtual;
  65. function pass_1 : tnode;override;
  66. function det_resulttype:tnode;override;
  67. end;
  68. tdoubleaddrnodeclass = class of tdoubleaddrnode;
  69. tderefnode = class(tunarynode)
  70. constructor create(l : tnode);virtual;
  71. function pass_1 : tnode;override;
  72. function det_resulttype:tnode;override;
  73. end;
  74. tderefnodeclass = class of tderefnode;
  75. tsubscriptnode = class(tunarynode)
  76. vs : tvarsym;
  77. constructor create(varsym : tsym;l : tnode);virtual;
  78. function getcopy : tnode;override;
  79. function pass_1 : tnode;override;
  80. function docompare(p: tnode): boolean; override;
  81. function det_resulttype:tnode;override;
  82. end;
  83. tsubscriptnodeclass = class of tsubscriptnode;
  84. tvecnode = class(tbinarynode)
  85. constructor create(l,r : tnode);virtual;
  86. function pass_1 : tnode;override;
  87. function det_resulttype:tnode;override;
  88. end;
  89. tvecnodeclass = class of tvecnode;
  90. tselfnode = class(tnode)
  91. classdef : tobjectdef;
  92. constructor create(_class : tobjectdef);virtual;
  93. function pass_1 : tnode;override;
  94. function det_resulttype:tnode;override;
  95. end;
  96. tselfnodeclass = class of tselfnode;
  97. twithnode = class(tbinarynode)
  98. withsymtable : twithsymtable;
  99. tablecount : longint;
  100. withreference : preference;
  101. constructor create(symtable : twithsymtable;l,r : tnode;count : longint);virtual;
  102. destructor destroy;override;
  103. function getcopy : tnode;override;
  104. function pass_1 : tnode;override;
  105. function docompare(p: tnode): boolean; override;
  106. function det_resulttype:tnode;override;
  107. end;
  108. twithnodeclass = class of twithnode;
  109. var
  110. cloadvmtnode : tloadvmtnodeclass;
  111. chnewnode : thnewnodeclass;
  112. cnewnode : tnewnodeclass;
  113. chdisposenode : thdisposenodeclass;
  114. csimplenewdisposenode : tsimplenewdisposenodeclass;
  115. caddrnode : taddrnodeclass;
  116. cdoubleaddrnode : tdoubleaddrnodeclass;
  117. cderefnode : tderefnodeclass;
  118. csubscriptnode : tsubscriptnodeclass;
  119. cvecnode : tvecnodeclass;
  120. cselfnode : tselfnodeclass;
  121. cwithnode : twithnodeclass;
  122. implementation
  123. uses
  124. globtype,systems,
  125. cutils,verbose,globals,
  126. symconst,symbase,types,
  127. htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase
  128. ;
  129. {*****************************************************************************
  130. TLOADVMTNODE
  131. *****************************************************************************}
  132. constructor tloadvmtnode.create(l : tnode);
  133. begin
  134. inherited create(loadvmtn,l);
  135. end;
  136. function tloadvmtnode.det_resulttype:tnode;
  137. begin
  138. result:=nil;
  139. resulttypepass(left);
  140. if codegenerror then
  141. exit;
  142. resulttype.setdef(tclassrefdef.create(left.resulttype));
  143. end;
  144. function tloadvmtnode.pass_1 : tnode;
  145. begin
  146. result:=nil;
  147. registers32:=1;
  148. location.loc:=LOC_REGISTER;
  149. end;
  150. {*****************************************************************************
  151. THNEWNODE
  152. *****************************************************************************}
  153. constructor thnewnode.create;
  154. begin
  155. inherited create(hnewn);
  156. end;
  157. function thnewnode.det_resulttype:tnode;
  158. begin
  159. result:=nil;
  160. resulttype:=voidtype;
  161. end;
  162. function thnewnode.pass_1 : tnode;
  163. begin
  164. result:=nil;
  165. end;
  166. {*****************************************************************************
  167. TNEWNODE
  168. *****************************************************************************}
  169. constructor tnewnode.create(l : tnode);
  170. begin
  171. inherited create(newn,l);
  172. end;
  173. function tnewnode.det_resulttype:tnode;
  174. begin
  175. result:=nil;
  176. if assigned(left) then
  177. resulttypepass(left);
  178. resulttype:=voidtype;
  179. end;
  180. function tnewnode.pass_1 : tnode;
  181. {$ifdef NEW_COMPILERPROC}
  182. var
  183. temp : ttempcreatenode;
  184. newstatement : tstatementnode;
  185. newblock : tblocknode;
  186. {$endif NEW_COMPILERPROC}
  187. begin
  188. result:=nil;
  189. {$ifdef NEW_COMPILERPROC}
  190. { create the blocknode which will hold the generated statements + }
  191. { an initial dummy statement }
  192. newstatement := cstatementnode.create(nil,cnothingnode.create);
  193. newblock := cblocknode.create(newstatement);
  194. { create temp for result }
  195. temp := ctempcreatenode.create(resulttype,
  196. resulttype.size,true);
  197. newstatement.left := cstatementnode.create(nil,temp);
  198. { create parameter }
  199. sizepara := ccallparanode.create(cordconstnode.create
  200. (tpointerdef(resulttype.def).pointertype.def.size,s32bittype),nil);
  201. { create the call and assign the result to dest }
  202. { the assignment will take care of rangechecking }
  203. newstatement.left := cstatementnode.create(nil,cassignmentnode.create(
  204. ctemprefnode.create(tempcode),
  205. ccallnode.createintern('fpc_getmem',sizepara)));
  206. newstatement := tstatementnode(newstatement.left);
  207. if tpointerdef(resulttype.def).pointertype.def.needs_inittable then
  208. begin
  209. para := ccallparanode.create(cloadnode.create
  210. (tpointerdef(resulttype.def).pointertype.def.size,s32bittype),
  211. ccallparanode.create(cordconstnode.create
  212. (tpointerdef(resulttype.def).pointertype.def.size,s32bittype),nil));
  213. newstatement.left := cstatementnode.create(nil,cassignmentnode.create(
  214. ctemprefnode.create(tempcode),
  215. ccallnode.createintern('fpc_initialize',sizepara)));
  216. newstatement := tstatementnode(newstatement.left);
  217. new(r);
  218. reset_reference(r^);
  219. r^.symbol:=tstoreddef(tpointerdef(resulttype.def).pointertype.def).get_rtti_label(initrtti);
  220. emitpushreferenceaddr(r^);
  221. dispose(r);
  222. { push pointer we just allocated, we need to initialize the
  223. data located at that pointer not the pointer self (PFV) }
  224. emit_push_loc(location);
  225. emitcall('FPC_INITIALIZE');
  226. end;
  227. { and return it }
  228. result := newblock;
  229. {$endif NEW_COMPILERPROC}
  230. if assigned(left) then
  231. begin
  232. firstpass(left);
  233. if codegenerror then
  234. exit;
  235. registers32:=left.registers32;
  236. registersfpu:=left.registersfpu;
  237. {$ifdef SUPPORT_MMX}
  238. registersmmx:=left.registersmmx;
  239. {$endif SUPPORT_MMX}
  240. location.loc:=LOC_REGISTER
  241. end
  242. else
  243. location.loc:=LOC_REFERENCE;
  244. procinfo^.flags:=procinfo^.flags or pi_do_call;
  245. end;
  246. {*****************************************************************************
  247. THDISPOSENODE
  248. *****************************************************************************}
  249. constructor thdisposenode.create(l : tnode);
  250. begin
  251. inherited create(hdisposen,l);
  252. end;
  253. function thdisposenode.det_resulttype:tnode;
  254. begin
  255. result:=nil;
  256. resulttypepass(left);
  257. if codegenerror then
  258. exit;
  259. resulttype:=tpointerdef(left.resulttype.def).pointertype;
  260. end;
  261. function thdisposenode.pass_1 : tnode;
  262. begin
  263. result:=nil;
  264. firstpass(left);
  265. if codegenerror then
  266. exit;
  267. registers32:=left.registers32;
  268. registersfpu:=left.registersfpu;
  269. {$ifdef SUPPORT_MMX}
  270. registersmmx:=left.registersmmx;
  271. {$endif SUPPORT_MMX}
  272. if registers32<1 then
  273. registers32:=1;
  274. {
  275. if left.location.loc<>LOC_REFERENCE then
  276. CGMessage(cg_e_illegal_expression);
  277. }
  278. if left.location.loc=LOC_CREGISTER then
  279. inc(registers32);
  280. location.loc:=LOC_REFERENCE;
  281. end;
  282. {*****************************************************************************
  283. TSIMPLENEWDISPOSENODE
  284. *****************************************************************************}
  285. constructor tsimplenewdisposenode.create(n : tnodetype;l : tnode);
  286. begin
  287. inherited create(n,l);
  288. end;
  289. function tsimplenewdisposenode.det_resulttype:tnode;
  290. begin
  291. result:=nil;
  292. resulttypepass(left);
  293. if codegenerror then
  294. exit;
  295. if (left.resulttype.def.deftype<>pointerdef) then
  296. CGMessage1(type_e_pointer_type_expected,left.resulttype.def.typename);
  297. resulttype:=voidtype;
  298. end;
  299. function tsimplenewdisposenode.pass_1 : tnode;
  300. begin
  301. result:=nil;
  302. { this cannot be in a register !! }
  303. make_not_regable(left);
  304. firstpass(left);
  305. if codegenerror then
  306. exit;
  307. registers32:=left.registers32;
  308. registersfpu:=left.registersfpu;
  309. {$ifdef SUPPORT_MMX}
  310. registersmmx:=left.registersmmx;
  311. {$endif SUPPORT_MMX}
  312. procinfo^.flags:=procinfo^.flags or pi_do_call;
  313. end;
  314. {*****************************************************************************
  315. TADDRNODE
  316. *****************************************************************************}
  317. constructor taddrnode.create(l : tnode);
  318. begin
  319. inherited create(addrn,l);
  320. end;
  321. function taddrnode.det_resulttype:tnode;
  322. var
  323. hp : tnode;
  324. hp2 : TParaItem;
  325. hp3 : tabstractprocdef;
  326. begin
  327. result:=nil;
  328. resulttypepass(left);
  329. if codegenerror then
  330. exit;
  331. { don't allow constants }
  332. if is_constnode(left) then
  333. begin
  334. aktfilepos:=left.fileinfo;
  335. CGMessage(type_e_no_addr_of_constant);
  336. exit;
  337. end;
  338. { tp @procvar support (type of @procvar is a void pointer)
  339. Note: we need to leave the addrn in the tree,
  340. else we can't see the difference between @procvar and procvar.
  341. we set the procvarload flag so a secondpass does nothing for
  342. this node (PFV) }
  343. if (m_tp_procvar in aktmodeswitches) then
  344. begin
  345. case left.nodetype of
  346. calln :
  347. begin
  348. { is it a procvar? }
  349. hp:=tcallnode(left).right;
  350. if assigned(hp) then
  351. begin
  352. { remove calln node }
  353. tcallnode(left).right:=nil;
  354. left.free;
  355. left:=hp;
  356. include(flags,nf_procvarload);
  357. end;
  358. end;
  359. loadn,
  360. subscriptn,
  361. typeconvn,
  362. vecn,
  363. derefn :
  364. begin
  365. if left.resulttype.def.deftype=procvardef then
  366. include(flags,nf_procvarload);
  367. end;
  368. end;
  369. if nf_procvarload in flags then
  370. begin
  371. resulttype:=voidpointertype;
  372. exit;
  373. end;
  374. end;
  375. { proc 2 procvar ? }
  376. if left.nodetype=calln then
  377. internalerror(200103253)
  378. else
  379. if (left.nodetype=loadn) and (tloadnode(left).symtableentry.typ=procsym) then
  380. begin
  381. { the address is already available when loading a procedure of object }
  382. if assigned(tloadnode(left).left) then
  383. include(flags,nf_procvarload);
  384. { result is a procedure variable }
  385. { No, to be TP compatible, you must return a voidpointer to
  386. the procedure that is stored in the procvar.}
  387. if not(m_tp_procvar in aktmodeswitches) then
  388. begin
  389. if assigned(getprocvardef) then
  390. hp3:=getprocvardef
  391. else
  392. hp3:=tabstractprocdef(tprocsym(tloadnode(left).symtableentry).defs^.def);
  393. { create procvardef }
  394. resulttype.setdef(tprocvardef.create);
  395. tprocvardef(resulttype.def).proctypeoption:=hp3.proctypeoption;
  396. tprocvardef(resulttype.def).proccalloption:=hp3.proccalloption;
  397. tprocvardef(resulttype.def).procoptions:=hp3.procoptions;
  398. tprocvardef(resulttype.def).rettype:=hp3.rettype;
  399. tprocvardef(resulttype.def).symtablelevel:=hp3.symtablelevel;
  400. { method ? then set the methodpointer flag }
  401. if (hp3.owner.symtabletype=objectsymtable) then
  402. include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
  403. { we need to process the parameters reverse so they are inserted
  404. in the correct right2left order (PFV) }
  405. hp2:=TParaItem(hp3.Para.last);
  406. while assigned(hp2) do
  407. begin
  408. tprocvardef(resulttype.def).concatpara(hp2.paratype,hp2.parasym,hp2.paratyp,hp2.defaultvalue);
  409. hp2:=TParaItem(hp2.previous);
  410. end;
  411. end
  412. else
  413. resulttype:=voidpointertype;
  414. end
  415. else
  416. begin
  417. { what are we getting the address from an absolute sym? }
  418. hp:=left;
  419. while assigned(hp) and (hp.nodetype in [vecn,derefn,subscriptn]) do
  420. hp:=tunarynode(hp).left;
  421. if assigned(hp) and (hp.nodetype=loadn) and
  422. ((tloadnode(hp).symtableentry.typ=absolutesym) and
  423. tabsolutesym(tloadnode(hp).symtableentry).absseg) then
  424. begin
  425. if not(cs_typed_addresses in aktlocalswitches) then
  426. resulttype:=voidfarpointertype
  427. else
  428. resulttype.setdef(tpointerdef.createfar(left.resulttype));
  429. end
  430. else
  431. begin
  432. if not(cs_typed_addresses in aktlocalswitches) then
  433. resulttype:=voidpointertype
  434. else
  435. resulttype.setdef(tpointerdef.create(left.resulttype));
  436. end;
  437. end;
  438. { this is like the function addr }
  439. inc(parsing_para_level);
  440. set_varstate(left,false);
  441. dec(parsing_para_level);
  442. end;
  443. function taddrnode.pass_1 : tnode;
  444. begin
  445. result:=nil;
  446. firstpass(left);
  447. if codegenerror then
  448. exit;
  449. make_not_regable(left);
  450. if nf_procvarload in flags then
  451. begin
  452. registers32:=left.registers32;
  453. registersfpu:=left.registersfpu;
  454. {$ifdef SUPPORT_MMX}
  455. registersmmx:=left.registersmmx;
  456. {$endif SUPPORT_MMX}
  457. if registers32<1 then
  458. registers32:=1;
  459. location.loc:=left.location.loc;
  460. exit;
  461. end;
  462. { we should allow loc_mem for @string }
  463. if not(left.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  464. begin
  465. aktfilepos:=left.fileinfo;
  466. CGMessage(cg_e_illegal_expression);
  467. end;
  468. registers32:=left.registers32;
  469. registersfpu:=left.registersfpu;
  470. {$ifdef SUPPORT_MMX}
  471. registersmmx:=left.registersmmx;
  472. {$endif SUPPORT_MMX}
  473. if registers32<1 then
  474. registers32:=1;
  475. { is this right for object of methods ?? }
  476. location.loc:=LOC_REGISTER;
  477. end;
  478. {*****************************************************************************
  479. TDOUBLEADDRNODE
  480. *****************************************************************************}
  481. constructor tdoubleaddrnode.create(l : tnode);
  482. begin
  483. inherited create(doubleaddrn,l);
  484. end;
  485. function tdoubleaddrnode.det_resulttype:tnode;
  486. begin
  487. result:=nil;
  488. resulttypepass(left);
  489. if codegenerror then
  490. exit;
  491. inc(parsing_para_level);
  492. set_varstate(left,false);
  493. dec(parsing_para_level);
  494. if (left.resulttype.def.deftype)<>procvardef then
  495. CGMessage(cg_e_illegal_expression);
  496. resulttype:=voidpointertype;
  497. end;
  498. function tdoubleaddrnode.pass_1 : tnode;
  499. begin
  500. result:=nil;
  501. make_not_regable(left);
  502. firstpass(left);
  503. if codegenerror then
  504. exit;
  505. if (left.location.loc<>LOC_REFERENCE) then
  506. CGMessage(cg_e_illegal_expression);
  507. registers32:=left.registers32;
  508. registersfpu:=left.registersfpu;
  509. {$ifdef SUPPORT_MMX}
  510. registersmmx:=left.registersmmx;
  511. {$endif SUPPORT_MMX}
  512. if registers32<1 then
  513. registers32:=1;
  514. location.loc:=LOC_REGISTER;
  515. end;
  516. {*****************************************************************************
  517. TDEREFNODE
  518. *****************************************************************************}
  519. constructor tderefnode.create(l : tnode);
  520. begin
  521. inherited create(derefn,l);
  522. end;
  523. function tderefnode.det_resulttype:tnode;
  524. begin
  525. result:=nil;
  526. resulttypepass(left);
  527. set_varstate(left,true);
  528. if codegenerror then
  529. exit;
  530. if left.resulttype.def.deftype=pointerdef then
  531. resulttype:=tpointerdef(left.resulttype.def).pointertype
  532. else
  533. CGMessage(cg_e_invalid_qualifier);
  534. end;
  535. function tderefnode.pass_1 : tnode;
  536. begin
  537. result:=nil;
  538. firstpass(left);
  539. if codegenerror then
  540. exit;
  541. registers32:=max(left.registers32,1);
  542. registersfpu:=left.registersfpu;
  543. {$ifdef SUPPORT_MMX}
  544. registersmmx:=left.registersmmx;
  545. {$endif SUPPORT_MMX}
  546. location.loc:=LOC_REFERENCE;
  547. end;
  548. {*****************************************************************************
  549. TSUBSCRIPTNODE
  550. *****************************************************************************}
  551. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  552. begin
  553. inherited create(subscriptn,l);
  554. { vs should be changed to tsym! }
  555. vs:=tvarsym(varsym);
  556. end;
  557. function tsubscriptnode.getcopy : tnode;
  558. var
  559. p : tsubscriptnode;
  560. begin
  561. p:=tsubscriptnode(inherited getcopy);
  562. p.vs:=vs;
  563. getcopy:=p;
  564. end;
  565. function tsubscriptnode.det_resulttype:tnode;
  566. begin
  567. result:=nil;
  568. resulttypepass(left);
  569. resulttype:=vs.vartype;
  570. end;
  571. function tsubscriptnode.pass_1 : tnode;
  572. begin
  573. result:=nil;
  574. firstpass(left);
  575. if codegenerror then
  576. exit;
  577. registers32:=left.registers32;
  578. registersfpu:=left.registersfpu;
  579. {$ifdef SUPPORT_MMX}
  580. registersmmx:=left.registersmmx;
  581. {$endif SUPPORT_MMX}
  582. { classes must be dereferenced implicit }
  583. if is_class_or_interface(left.resulttype.def) then
  584. begin
  585. if registers32=0 then
  586. registers32:=1;
  587. location.loc:=LOC_REFERENCE;
  588. end
  589. else
  590. begin
  591. if (left.location.loc<>LOC_MEM) and
  592. (left.location.loc<>LOC_REFERENCE) then
  593. CGMessage(cg_e_illegal_expression);
  594. set_location(location,left.location);
  595. end;
  596. end;
  597. function tsubscriptnode.docompare(p: tnode): boolean;
  598. begin
  599. docompare :=
  600. inherited docompare(p) and
  601. (vs = tsubscriptnode(p).vs);
  602. end;
  603. {*****************************************************************************
  604. TVECNODE
  605. *****************************************************************************}
  606. constructor tvecnode.create(l,r : tnode);
  607. begin
  608. inherited create(vecn,l,r);
  609. end;
  610. function tvecnode.det_resulttype:tnode;
  611. var
  612. htype : ttype;
  613. ct : tconverttype;
  614. begin
  615. result:=nil;
  616. resulttypepass(left);
  617. resulttypepass(right);
  618. if codegenerror then
  619. exit;
  620. { range check only for arrays }
  621. if (left.resulttype.def.deftype=arraydef) then
  622. begin
  623. if (isconvertable(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,
  624. ct,ordconstn,false)=0) and
  625. not(is_equal(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def)) then
  626. CGMessage(type_e_mismatch);
  627. end;
  628. { Never convert a boolean or a char !}
  629. { maybe type conversion }
  630. if (right.resulttype.def.deftype<>enumdef) and
  631. not(is_char(right.resulttype.def)) and
  632. not(is_boolean(right.resulttype.def)) then
  633. begin
  634. inserttypeconv(right,s32bittype);
  635. end;
  636. { are we accessing a pointer[], then convert the pointer to
  637. an array first, in FPC this is allowed for all pointers in
  638. delphi/tp7 it's only allowed for pchars }
  639. if (left.resulttype.def.deftype=pointerdef) and
  640. ((m_fpc in aktmodeswitches) or
  641. is_pchar(left.resulttype.def) or
  642. is_pwidechar(left.resulttype.def)) then
  643. begin
  644. { convert pointer to array }
  645. htype.setdef(tarraydef.create(0,$7fffffff,s32bittype));
  646. tarraydef(htype.def).elementtype:=tpointerdef(left.resulttype.def).pointertype;
  647. inserttypeconv(left,htype);
  648. resulttype:=tarraydef(htype.def).elementtype;
  649. end;
  650. { determine return type }
  651. if not assigned(resulttype.def) then
  652. if left.resulttype.def.deftype=arraydef then
  653. resulttype:=tarraydef(left.resulttype.def).elementtype
  654. else if left.resulttype.def.deftype=stringdef then
  655. begin
  656. { indexed access to strings }
  657. case tstringdef(left.resulttype.def).string_typ of
  658. st_widestring :
  659. resulttype:=cwidechartype;
  660. st_ansistring :
  661. resulttype:=cchartype;
  662. st_longstring :
  663. resulttype:=cchartype;
  664. st_shortstring :
  665. resulttype:=cchartype;
  666. end;
  667. end
  668. else
  669. CGMessage(type_e_array_required);
  670. end;
  671. function tvecnode.pass_1 : tnode;
  672. {$ifdef consteval}
  673. var
  674. tcsym : ttypedconstsym;
  675. {$endif}
  676. begin
  677. result:=nil;
  678. firstpass(left);
  679. firstpass(right);
  680. if codegenerror then
  681. exit;
  682. { the register calculation is easy if a const index is used }
  683. if right.nodetype=ordconstn then
  684. begin
  685. {$ifdef consteval}
  686. { constant evaluation }
  687. if (left.nodetype=loadn) and
  688. (left.symtableentry.typ=typedconstsym) then
  689. begin
  690. tcsym:=ttypedconstsym(left.symtableentry);
  691. if tcsym.defintion^.typ=stringdef then
  692. begin
  693. end;
  694. end;
  695. {$endif}
  696. registers32:=left.registers32;
  697. { for ansi/wide strings, we need at least one register }
  698. if is_ansistring(left.resulttype.def) or
  699. is_widestring(left.resulttype.def) or
  700. { ... as well as for dynamic arrays }
  701. is_dynamic_array(left.resulttype.def) then
  702. registers32:=max(registers32,1);
  703. end
  704. else
  705. begin
  706. { this rules are suboptimal, but they should give }
  707. { good results }
  708. registers32:=max(left.registers32,right.registers32);
  709. { for ansi/wide strings, we need at least one register }
  710. if is_ansistring(left.resulttype.def) or
  711. is_widestring(left.resulttype.def) or
  712. { ... as well as for dynamic arrays }
  713. is_dynamic_array(left.resulttype.def) then
  714. registers32:=max(registers32,1);
  715. { need we an extra register when doing the restore ? }
  716. if (left.registers32<=right.registers32) and
  717. { only if the node needs less than 3 registers }
  718. { two for the right node and one for the }
  719. { left address }
  720. (registers32<3) then
  721. inc(registers32);
  722. { need we an extra register for the index ? }
  723. if (right.location.loc<>LOC_REGISTER)
  724. { only if the right node doesn't need a register }
  725. and (right.registers32<1) then
  726. inc(registers32);
  727. { not correct, but what works better ?
  728. if left.registers32>0 then
  729. registers32:=max(registers32,2)
  730. else
  731. min. one register
  732. registers32:=max(registers32,1);
  733. }
  734. end;
  735. registersfpu:=max(left.registersfpu,right.registersfpu);
  736. {$ifdef SUPPORT_MMX}
  737. registersmmx:=max(left.registersmmx,right.registersmmx);
  738. {$endif SUPPORT_MMX}
  739. if left.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
  740. location.loc:=LOC_REFERENCE
  741. else
  742. location.loc:=LOC_MEM;
  743. end;
  744. {*****************************************************************************
  745. TSELFNODE
  746. *****************************************************************************}
  747. constructor tselfnode.create(_class : tobjectdef);
  748. begin
  749. inherited create(selfn);
  750. classdef:=_class;
  751. end;
  752. function tselfnode.det_resulttype:tnode;
  753. begin
  754. result:=nil;
  755. resulttype.setdef(classdef);
  756. end;
  757. function tselfnode.pass_1 : tnode;
  758. begin
  759. result:=nil;
  760. if (resulttype.def.deftype=classrefdef) or
  761. is_class(resulttype.def) then
  762. location.loc:=LOC_CREGISTER
  763. else
  764. location.loc:=LOC_REFERENCE;
  765. end;
  766. {*****************************************************************************
  767. TWITHNODE
  768. *****************************************************************************}
  769. constructor twithnode.create(symtable : twithsymtable;l,r : tnode;count : longint);
  770. begin
  771. inherited create(withn,l,r);
  772. withsymtable:=symtable;
  773. tablecount:=count;
  774. withreference:=nil;
  775. set_file_line(l);
  776. end;
  777. destructor twithnode.destroy;
  778. var
  779. symt : tsymtable;
  780. i : longint;
  781. begin
  782. symt:=withsymtable;
  783. for i:=1 to tablecount do
  784. begin
  785. if assigned(symt) then
  786. begin
  787. withsymtable:=twithsymtable(symt.next);
  788. symt.free;
  789. end;
  790. symt:=withsymtable;
  791. end;
  792. inherited destroy;
  793. end;
  794. function twithnode.getcopy : tnode;
  795. var
  796. p : twithnode;
  797. begin
  798. p:=twithnode(inherited getcopy);
  799. p.withsymtable:=withsymtable;
  800. p.tablecount:=tablecount;
  801. p.withreference:=withreference;
  802. result:=p;
  803. end;
  804. function twithnode.det_resulttype:tnode;
  805. var
  806. symtable : twithsymtable;
  807. i : longint;
  808. begin
  809. result:=nil;
  810. resulttype:=voidtype;
  811. if assigned(left) and assigned(right) then
  812. begin
  813. resulttypepass(left);
  814. unset_varstate(left);
  815. set_varstate(left,true);
  816. if codegenerror then
  817. exit;
  818. symtable:=withsymtable;
  819. for i:=1 to tablecount do
  820. begin
  821. if (left.nodetype=loadn) and
  822. (tloadnode(left).symtable=aktprocdef.localst) then
  823. symtable.direct_with:=true;
  824. symtable.withnode:=self;
  825. symtable:=twithsymtable(symtable.next);
  826. end;
  827. resulttypepass(right);
  828. if codegenerror then
  829. exit;
  830. end;
  831. resulttype:=voidtype;
  832. end;
  833. function twithnode.pass_1 : tnode;
  834. begin
  835. result:=nil;
  836. if assigned(left) and assigned(right) then
  837. begin
  838. firstpass(left);
  839. firstpass(right);
  840. if codegenerror then
  841. exit;
  842. left_right_max;
  843. end
  844. else
  845. begin
  846. { optimization }
  847. result:=nil;
  848. end;
  849. end;
  850. function twithnode.docompare(p: tnode): boolean;
  851. begin
  852. docompare :=
  853. inherited docompare(p) and
  854. (withsymtable = twithnode(p).withsymtable) and
  855. (tablecount = twithnode(p).tablecount);
  856. end;
  857. begin
  858. cloadvmtnode := tloadvmtnode;
  859. chnewnode := thnewnode;
  860. cnewnode := tnewnode;
  861. chdisposenode := thdisposenode;
  862. csimplenewdisposenode := tsimplenewdisposenode;
  863. caddrnode := taddrnode;
  864. cdoubleaddrnode := tdoubleaddrnode;
  865. cderefnode := tderefnode;
  866. csubscriptnode := tsubscriptnode;
  867. cvecnode := tvecnode;
  868. cselfnode := tselfnode;
  869. cwithnode := twithnode;
  870. end.
  871. {
  872. $Log$
  873. Revision 1.25 2001-12-06 17:57:34 florian
  874. + parasym to tparaitem added
  875. Revision 1.24 2001/12/03 21:48:42 peter
  876. * freemem change to value parameter
  877. * torddef low/high range changed to int64
  878. Revision 1.23 2001/11/02 22:58:02 peter
  879. * procsym definition rewrite
  880. Revision 1.22 2001/10/28 17:22:25 peter
  881. * allow assignment of overloaded procedures to procvars when we know
  882. which procedure to take
  883. Revision 1.20 2001/09/02 21:12:07 peter
  884. * move class of definitions into type section for delphi
  885. Revision 1.19 2001/08/26 13:36:42 florian
  886. * some cg reorganisation
  887. * some PPC updates
  888. Revision 1.18 2001/04/13 22:15:21 peter
  889. * removed wrongly placed set_varstate in subscriptnode
  890. Revision 1.17 2001/04/13 01:22:10 peter
  891. * symtable change to classes
  892. * range check generation and errors fixed, make cycle DEBUG=1 works
  893. * memory leaks fixed
  894. Revision 1.16 2001/04/02 21:20:31 peter
  895. * resulttype rewrite
  896. Revision 1.15 2001/03/23 00:16:07 florian
  897. + some stuff to compile FreeCLX added
  898. Revision 1.14 2000/12/31 11:14:11 jonas
  899. + implemented/fixed docompare() mathods for all nodes (not tested)
  900. + nopt.pas, nadd.pas, i386/n386opt.pas: optimized nodes for adding strings
  901. and constant strings/chars together
  902. * n386add.pas: don't copy temp strings (of size 256) to another temp string
  903. when adding
  904. Revision 1.13 2000/12/25 00:07:26 peter
  905. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  906. tlinkedlist objects)
  907. Revision 1.12 2000/12/05 15:19:50 jonas
  908. * fixed webbug 1268 ("merged")
  909. Revision 1.11 2000/11/29 00:30:34 florian
  910. * unused units removed from uses clause
  911. * some changes for widestrings
  912. Revision 1.10 2000/11/04 14:25:20 florian
  913. + merged Attila's changes for interfaces, not tested yet
  914. Revision 1.9 2000/10/31 22:02:49 peter
  915. * symtable splitted, no real code changes
  916. Revision 1.8 2000/10/21 18:16:11 florian
  917. * a lot of changes:
  918. - basic dyn. array support
  919. - basic C++ support
  920. - some work for interfaces done
  921. ....
  922. Revision 1.7 2000/10/14 21:52:55 peter
  923. * fixed memory leaks
  924. Revision 1.6 2000/10/14 10:14:51 peter
  925. * moehrendorf oct 2000 rewrite
  926. Revision 1.5 2000/10/01 19:48:24 peter
  927. * lot of compile updates for cg11
  928. Revision 1.4 2000/09/28 19:49:52 florian
  929. *** empty log message ***
  930. Revision 1.3 2000/09/25 15:37:14 florian
  931. * more fixes
  932. Revision 1.2 2000/09/25 15:05:25 florian
  933. * some updates
  934. Revision 1.1 2000/09/25 09:58:22 florian
  935. * first revision for testing purpose
  936. }