nmem.pas 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  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. 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 : tobjectdef;
  81. constructor create(_class : tobjectdef);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 : tobjectdef);
  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. symt : tsymtable;
  667. i : longint;
  668. begin
  669. symt:=withsymtable;
  670. for i:=1 to tablecount do
  671. begin
  672. if assigned(symt) then
  673. begin
  674. withsymtable:=twithsymtable(symt.next);
  675. symt.free;
  676. end;
  677. symt:=withsymtable;
  678. end;
  679. inherited destroy;
  680. end;
  681. function twithnode.getcopy : tnode;
  682. var
  683. p : twithnode;
  684. begin
  685. p:=twithnode(inherited getcopy);
  686. p.withsymtable:=withsymtable;
  687. p.tablecount:=tablecount;
  688. p.withreference:=withreference;
  689. result:=p;
  690. end;
  691. function twithnode.det_resulttype:tnode;
  692. var
  693. symtable : twithsymtable;
  694. i : longint;
  695. begin
  696. result:=nil;
  697. resulttype:=voidtype;
  698. if assigned(left) and assigned(right) then
  699. begin
  700. resulttypepass(left);
  701. unset_varstate(left);
  702. set_varstate(left,true);
  703. if codegenerror then
  704. exit;
  705. symtable:=withsymtable;
  706. for i:=1 to tablecount do
  707. begin
  708. if (left.nodetype=loadn) and
  709. (tloadnode(left).symtable=aktprocdef.localst) then
  710. symtable.direct_with:=true;
  711. symtable.withnode:=self;
  712. symtable:=twithsymtable(symtable.next);
  713. end;
  714. resulttypepass(right);
  715. if codegenerror then
  716. exit;
  717. end;
  718. resulttype:=voidtype;
  719. end;
  720. function twithnode.pass_1 : tnode;
  721. begin
  722. result:=nil;
  723. if assigned(left) and assigned(right) then
  724. begin
  725. firstpass(left);
  726. firstpass(right);
  727. if codegenerror then
  728. exit;
  729. left_right_max;
  730. end
  731. else
  732. begin
  733. { optimization }
  734. result:=nil;
  735. end;
  736. end;
  737. function twithnode.docompare(p: tnode): boolean;
  738. begin
  739. docompare :=
  740. inherited docompare(p) and
  741. (withsymtable = twithnode(p).withsymtable) and
  742. (tablecount = twithnode(p).tablecount);
  743. end;
  744. begin
  745. cloadvmtnode := tloadvmtnode;
  746. chnewnode := thnewnode;
  747. chdisposenode := thdisposenode;
  748. caddrnode := taddrnode;
  749. cdoubleaddrnode := tdoubleaddrnode;
  750. cderefnode := tderefnode;
  751. csubscriptnode := tsubscriptnode;
  752. cvecnode := tvecnode;
  753. cselfnode := tselfnode;
  754. cwithnode := twithnode;
  755. end.
  756. {
  757. $Log$
  758. Revision 1.29 2002-04-21 19:02:04 peter
  759. * removed newn and disposen nodes, the code is now directly
  760. inlined from pexpr
  761. * -an option that will write the secondpass nodes to the .s file, this
  762. requires EXTDEBUG define to actually write the info
  763. * fixed various internal errors and crashes due recent code changes
  764. Revision 1.28 2002/04/20 21:32:23 carl
  765. + generic FPC_CHECKPOINTER
  766. + first parameter offset in stack now portable
  767. * rename some constants
  768. + move some cpu stuff to other units
  769. - remove unused constents
  770. * fix stacksize for some targets
  771. * fix generic size problems which depend now on EXTEND_SIZE constant
  772. Revision 1.27 2002/04/02 17:11:29 peter
  773. * tlocation,treference update
  774. * LOC_CONSTANT added for better constant handling
  775. * secondadd splitted in multiple routines
  776. * location_force_reg added for loading a location to a register
  777. of a specified size
  778. * secondassignment parses now first the right and then the left node
  779. (this is compatible with Kylix). This saves a lot of push/pop especially
  780. with string operations
  781. * adapted some routines to use the new cg methods
  782. Revision 1.26 2002/04/01 20:57:13 jonas
  783. * fixed web bug 1907
  784. * fixed some other procvar related bugs (all related to accepting procvar
  785. constructs with either too many or too little parameters)
  786. (both merged, includes second typo fix of pexpr.pas)
  787. Revision 1.25 2001/12/06 17:57:34 florian
  788. + parasym to tparaitem added
  789. Revision 1.24 2001/12/03 21:48:42 peter
  790. * freemem change to value parameter
  791. * torddef low/high range changed to int64
  792. Revision 1.23 2001/11/02 22:58:02 peter
  793. * procsym definition rewrite
  794. Revision 1.22 2001/10/28 17:22:25 peter
  795. * allow assignment of overloaded procedures to procvars when we know
  796. which procedure to take
  797. Revision 1.20 2001/09/02 21:12:07 peter
  798. * move class of definitions into type section for delphi
  799. Revision 1.19 2001/08/26 13:36:42 florian
  800. * some cg reorganisation
  801. * some PPC updates
  802. Revision 1.18 2001/04/13 22:15:21 peter
  803. * removed wrongly placed set_varstate in subscriptnode
  804. Revision 1.17 2001/04/13 01:22:10 peter
  805. * symtable change to classes
  806. * range check generation and errors fixed, make cycle DEBUG=1 works
  807. * memory leaks fixed
  808. Revision 1.16 2001/04/02 21:20:31 peter
  809. * resulttype rewrite
  810. Revision 1.15 2001/03/23 00:16:07 florian
  811. + some stuff to compile FreeCLX added
  812. Revision 1.14 2000/12/31 11:14:11 jonas
  813. + implemented/fixed docompare() mathods for all nodes (not tested)
  814. + nopt.pas, nadd.pas, i386/n386opt.pas: optimized nodes for adding strings
  815. and constant strings/chars together
  816. * n386add.pas: don't copy temp strings (of size 256) to another temp string
  817. when adding
  818. Revision 1.13 2000/12/25 00:07:26 peter
  819. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  820. tlinkedlist objects)
  821. Revision 1.12 2000/12/05 15:19:50 jonas
  822. * fixed webbug 1268 ("merged")
  823. Revision 1.11 2000/11/29 00:30:34 florian
  824. * unused units removed from uses clause
  825. * some changes for widestrings
  826. Revision 1.10 2000/11/04 14:25:20 florian
  827. + merged Attila's changes for interfaces, not tested yet
  828. Revision 1.9 2000/10/31 22:02:49 peter
  829. * symtable splitted, no real code changes
  830. Revision 1.8 2000/10/21 18:16:11 florian
  831. * a lot of changes:
  832. - basic dyn. array support
  833. - basic C++ support
  834. - some work for interfaces done
  835. ....
  836. Revision 1.7 2000/10/14 21:52:55 peter
  837. * fixed memory leaks
  838. Revision 1.6 2000/10/14 10:14:51 peter
  839. * moehrendorf oct 2000 rewrite
  840. Revision 1.5 2000/10/01 19:48:24 peter
  841. * lot of compile updates for cg11
  842. Revision 1.4 2000/09/28 19:49:52 florian
  843. *** empty log message ***
  844. Revision 1.3 2000/09/25 15:37:14 florian
  845. * more fixes
  846. Revision 1.2 2000/09/25 15:05:25 florian
  847. * some updates
  848. Revision 1.1 2000/09/25 09:58:22 florian
  849. * first revision for testing purpose
  850. }