nmem.pas 34 KB

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