nmem.pas 32 KB

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