nmem.pas 31 KB

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