nmem.pas 34 KB

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