nmem.pas 34 KB

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