nmem.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  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. printnode(output,left);
  329. CGMessage(cg_e_illegal_expression);
  330. end;
  331. registers32:=left.registers32;
  332. registersfpu:=left.registersfpu;
  333. {$ifdef SUPPORT_MMX}
  334. registersmmx:=left.registersmmx;
  335. {$endif SUPPORT_MMX}
  336. if registers32<1 then
  337. registers32:=1;
  338. { is this right for object of methods ?? }
  339. expectloc:=LOC_REGISTER;
  340. end;
  341. {*****************************************************************************
  342. TDEREFNODE
  343. *****************************************************************************}
  344. constructor tderefnode.create(l : tnode);
  345. begin
  346. inherited create(derefn,l);
  347. end;
  348. function tderefnode.det_resulttype:tnode;
  349. begin
  350. result:=nil;
  351. resulttypepass(left);
  352. set_varstate(left,true);
  353. if codegenerror then
  354. exit;
  355. if left.resulttype.def.deftype=pointerdef then
  356. resulttype:=tpointerdef(left.resulttype.def).pointertype
  357. else
  358. CGMessage(cg_e_invalid_qualifier);
  359. end;
  360. procedure Tderefnode.mark_write;
  361. begin
  362. include(flags,nf_write);
  363. end;
  364. function tderefnode.pass_1 : tnode;
  365. begin
  366. result:=nil;
  367. firstpass(left);
  368. if codegenerror then
  369. exit;
  370. registers32:=max(left.registers32,1);
  371. registersfpu:=left.registersfpu;
  372. {$ifdef SUPPORT_MMX}
  373. registersmmx:=left.registersmmx;
  374. {$endif SUPPORT_MMX}
  375. expectloc:=LOC_REFERENCE;
  376. end;
  377. {*****************************************************************************
  378. TSUBSCRIPTNODE
  379. *****************************************************************************}
  380. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  381. begin
  382. inherited create(subscriptn,l);
  383. { vs should be changed to tsym! }
  384. vs:=tvarsym(varsym);
  385. end;
  386. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  387. begin
  388. inherited ppuload(t,ppufile);
  389. ppufile.getderef(vsderef);
  390. end;
  391. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  392. begin
  393. inherited ppuwrite(ppufile);
  394. ppufile.putderef(vs,vsderef);
  395. end;
  396. procedure tsubscriptnode.derefimpl;
  397. begin
  398. inherited derefimpl;
  399. vs:=tvarsym(vsderef.resolve);
  400. end;
  401. function tsubscriptnode.getcopy : tnode;
  402. var
  403. p : tsubscriptnode;
  404. begin
  405. p:=tsubscriptnode(inherited getcopy);
  406. p.vs:=vs;
  407. getcopy:=p;
  408. end;
  409. function tsubscriptnode.det_resulttype:tnode;
  410. begin
  411. result:=nil;
  412. resulttypepass(left);
  413. resulttype:=vs.vartype;
  414. end;
  415. procedure Tsubscriptnode.mark_write;
  416. begin
  417. include(flags,nf_write);
  418. end;
  419. function tsubscriptnode.pass_1 : tnode;
  420. begin
  421. result:=nil;
  422. firstpass(left);
  423. if codegenerror then
  424. exit;
  425. registers32:=left.registers32;
  426. registersfpu:=left.registersfpu;
  427. {$ifdef SUPPORT_MMX}
  428. registersmmx:=left.registersmmx;
  429. {$endif SUPPORT_MMX}
  430. { classes must be dereferenced implicit }
  431. if is_class_or_interface(left.resulttype.def) then
  432. begin
  433. if registers32=0 then
  434. registers32:=1;
  435. expectloc:=LOC_REFERENCE;
  436. end
  437. else
  438. begin
  439. if (left.expectloc<>LOC_CREFERENCE) and
  440. (left.expectloc<>LOC_REFERENCE) then
  441. CGMessage(cg_e_illegal_expression);
  442. expectloc:=left.expectloc;
  443. end;
  444. end;
  445. function tsubscriptnode.docompare(p: tnode): boolean;
  446. begin
  447. docompare :=
  448. inherited docompare(p) and
  449. (vs = tsubscriptnode(p).vs);
  450. end;
  451. {*****************************************************************************
  452. TVECNODE
  453. *****************************************************************************}
  454. constructor tvecnode.create(l,r : tnode);
  455. begin
  456. inherited create(vecn,l,r);
  457. end;
  458. function tvecnode.det_resulttype:tnode;
  459. var
  460. htype : ttype;
  461. begin
  462. result:=nil;
  463. resulttypepass(left);
  464. resulttypepass(right);
  465. if codegenerror then
  466. exit;
  467. { maybe type conversion for the index value, but
  468. do not convert enums,booleans,char }
  469. if (right.resulttype.def.deftype<>enumdef) and
  470. not(is_char(right.resulttype.def)) and
  471. not(is_boolean(right.resulttype.def)) then
  472. begin
  473. inserttypeconv(right,s32bittype);
  474. end;
  475. case left.resulttype.def.deftype of
  476. arraydef :
  477. begin
  478. { check type of the index value }
  479. if (compare_defs(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,right.nodetype)=te_incompatible) then
  480. CGMessage(type_e_mismatch);
  481. resulttype:=tarraydef(left.resulttype.def).elementtype;
  482. end;
  483. pointerdef :
  484. begin
  485. { are we accessing a pointer[], then convert the pointer to
  486. an array first, in FPC this is allowed for all pointers in
  487. delphi/tp7 it's only allowed for pchars }
  488. if (m_fpc in aktmodeswitches) or
  489. is_pchar(left.resulttype.def) or
  490. is_pwidechar(left.resulttype.def) then
  491. begin
  492. { convert pointer to array }
  493. htype.setdef(tarraydef.create(0,$7fffffff,s32bittype));
  494. tarraydef(htype.def).setelementtype(tpointerdef(left.resulttype.def).pointertype);
  495. inserttypeconv(left,htype);
  496. resulttype:=tarraydef(htype.def).elementtype;
  497. end
  498. else
  499. CGMessage(type_e_array_required);
  500. end;
  501. stringdef :
  502. begin
  503. { indexed access to 0 element is only allowed for shortstrings }
  504. if (right.nodetype=ordconstn) and
  505. (tordconstnode(right).value=0) and
  506. not(is_shortstring(left.resulttype.def)) then
  507. CGMessage(cg_e_can_access_element_zero);
  508. case tstringdef(left.resulttype.def).string_typ of
  509. st_widestring :
  510. resulttype:=cwidechartype;
  511. st_ansistring :
  512. resulttype:=cchartype;
  513. st_longstring :
  514. resulttype:=cchartype;
  515. st_shortstring :
  516. resulttype:=cchartype;
  517. end;
  518. end
  519. else
  520. CGMessage(type_e_array_required);
  521. end;
  522. end;
  523. procedure Tvecnode.mark_write;
  524. begin
  525. include(flags,nf_write);
  526. end;
  527. function tvecnode.pass_1 : tnode;
  528. {$ifdef consteval}
  529. var
  530. tcsym : ttypedconstsym;
  531. {$endif}
  532. begin
  533. result:=nil;
  534. firstpass(left);
  535. firstpass(right);
  536. if codegenerror then
  537. exit;
  538. if (nf_callunique in flags) and
  539. (is_ansistring(left.resulttype.def) or
  540. is_widestring(left.resulttype.def)) then
  541. begin
  542. left := ctypeconvnode.create_explicit(ccallnode.createintern('fpc_'+tstringdef(left.resulttype.def).stringtypname+'_unique',
  543. ccallparanode.create(
  544. ctypeconvnode.create_explicit(left,voidpointertype),nil)),
  545. left.resulttype);
  546. firstpass(left);
  547. { double resulttype passes somwhere else may cause this to be }
  548. { reset though :/ }
  549. exclude(flags,nf_callunique);
  550. end;
  551. { the register calculation is easy if a const index is used }
  552. if right.nodetype=ordconstn then
  553. begin
  554. {$ifdef consteval}
  555. { constant evaluation }
  556. if (left.nodetype=loadn) and
  557. (left.symtableentry.typ=typedconstsym) then
  558. begin
  559. tcsym:=ttypedconstsym(left.symtableentry);
  560. if tcsym.defintion^.typ=stringdef then
  561. begin
  562. end;
  563. end;
  564. {$endif}
  565. registers32:=left.registers32;
  566. { for ansi/wide strings, we need at least one register }
  567. if is_ansistring(left.resulttype.def) or
  568. is_widestring(left.resulttype.def) or
  569. { ... as well as for dynamic arrays }
  570. is_dynamic_array(left.resulttype.def) then
  571. registers32:=max(registers32,1);
  572. end
  573. else
  574. begin
  575. { this rules are suboptimal, but they should give }
  576. { good results }
  577. registers32:=max(left.registers32,right.registers32);
  578. { for ansi/wide strings, we need at least one register }
  579. if is_ansistring(left.resulttype.def) or
  580. is_widestring(left.resulttype.def) or
  581. { ... as well as for dynamic arrays }
  582. is_dynamic_array(left.resulttype.def) then
  583. registers32:=max(registers32,1);
  584. { need we an extra register when doing the restore ? }
  585. if (left.registers32<=right.registers32) and
  586. { only if the node needs less than 3 registers }
  587. { two for the right node and one for the }
  588. { left address }
  589. (registers32<3) then
  590. inc(registers32);
  591. { need we an extra register for the index ? }
  592. if (right.expectloc<>LOC_REGISTER)
  593. { only if the right node doesn't need a register }
  594. and (right.registers32<1) then
  595. inc(registers32);
  596. { not correct, but what works better ?
  597. if left.registers32>0 then
  598. registers32:=max(registers32,2)
  599. else
  600. min. one register
  601. registers32:=max(registers32,1);
  602. }
  603. end;
  604. registersfpu:=max(left.registersfpu,right.registersfpu);
  605. {$ifdef SUPPORT_MMX}
  606. registersmmx:=max(left.registersmmx,right.registersmmx);
  607. {$endif SUPPORT_MMX}
  608. if left.expectloc=LOC_CREFERENCE then
  609. expectloc:=LOC_CREFERENCE
  610. else
  611. expectloc:=LOC_REFERENCE;
  612. end;
  613. {*****************************************************************************
  614. TWITHNODE
  615. *****************************************************************************}
  616. constructor twithnode.create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
  617. begin
  618. inherited create(withn,l);
  619. withrefnode:=r;
  620. withsymtable:=symtable;
  621. tablecount:=count;
  622. set_file_line(l);
  623. end;
  624. destructor twithnode.destroy;
  625. var
  626. hsymt,
  627. symt : tsymtable;
  628. i : longint;
  629. begin
  630. symt:=withsymtable;
  631. for i:=1 to tablecount do
  632. begin
  633. if assigned(symt) then
  634. begin
  635. hsymt:=symt.next;
  636. symt.free;
  637. symt:=hsymt;
  638. end;
  639. end;
  640. inherited destroy;
  641. end;
  642. constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  643. begin
  644. inherited ppuload(t,ppufile);
  645. internalerror(200208192);
  646. end;
  647. procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
  648. begin
  649. inherited ppuwrite(ppufile);
  650. internalerror(200208193);
  651. end;
  652. function twithnode.getcopy : tnode;
  653. var
  654. p : twithnode;
  655. begin
  656. p:=twithnode(inherited getcopy);
  657. p.withsymtable:=withsymtable;
  658. p.tablecount:=tablecount;
  659. if assigned(p.withrefnode) then
  660. p.withrefnode:=withrefnode.getcopy
  661. else
  662. p.withrefnode:=nil;
  663. result:=p;
  664. end;
  665. function twithnode.det_resulttype:tnode;
  666. begin
  667. result:=nil;
  668. resulttype:=voidtype;
  669. resulttypepass(withrefnode);
  670. unset_varstate(withrefnode);
  671. set_varstate(withrefnode,true);
  672. if codegenerror then
  673. exit;
  674. if (withrefnode.nodetype=vecn) and
  675. (nf_memseg in withrefnode.flags) then
  676. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  677. if assigned(left) then
  678. resulttypepass(left);
  679. end;
  680. function twithnode.pass_1 : tnode;
  681. begin
  682. result:=nil;
  683. expectloc:=LOC_VOID;
  684. if assigned(left) then
  685. begin
  686. firstpass(left);
  687. registers32:=left.registers32;
  688. registersfpu:=left.registersfpu;
  689. {$ifdef SUPPORT_MMX}
  690. registersmmx:=left.registersmmx;
  691. {$endif SUPPORT_MMX}
  692. end;
  693. if assigned(withrefnode) then
  694. begin
  695. firstpass(withrefnode);
  696. if withrefnode.registers32 > registers32 then
  697. registers32:=withrefnode.registers32;
  698. if withrefnode.registersfpu > registersfpu then
  699. registers32:=withrefnode.registersfpu;
  700. {$ifdef SUPPORT_MMX}
  701. if withrefnode.registersmmx > registersmmx then
  702. registersmmx:=withrefnode.registersmmx;
  703. {$endif SUPPORT_MMX}
  704. end;
  705. end;
  706. function twithnode.docompare(p: tnode): boolean;
  707. begin
  708. docompare :=
  709. inherited docompare(p) and
  710. (withsymtable = twithnode(p).withsymtable) and
  711. (tablecount = twithnode(p).tablecount) and
  712. (withrefnode.isequal(twithnode(p).withrefnode));
  713. end;
  714. begin
  715. cloadvmtaddrnode := tloadvmtaddrnode;
  716. caddrnode := taddrnode;
  717. cderefnode := tderefnode;
  718. csubscriptnode := tsubscriptnode;
  719. cvecnode := tvecnode;
  720. cwithnode := twithnode;
  721. end.
  722. {
  723. $Log$
  724. Revision 1.61 2003-09-03 11:18:37 florian
  725. * fixed arm concatcopy
  726. + arm support in the common compiler sources added
  727. * moved some generic cg code around
  728. + tfputype added
  729. * ...
  730. Revision 1.60 2003/08/10 17:25:23 peter
  731. * fixed some reported bugs
  732. Revision 1.59 2003/06/17 19:24:08 jonas
  733. * fixed conversion of fpc_*str_unique to compilerproc
  734. Revision 1.58 2003/06/17 16:34:44 jonas
  735. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  736. * renamed all_intregisters to volatile_intregisters and made it
  737. processor dependent
  738. Revision 1.57 2003/06/07 20:26:32 peter
  739. * re-resolving added instead of reloading from ppu
  740. * tderef object added to store deref info for resolving
  741. Revision 1.56 2003/06/07 18:57:04 jonas
  742. + added freeintparaloc
  743. * ppc get/freeintparaloc now check whether the parameter regs are
  744. properly allocated/deallocated (and get an extra list para)
  745. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  746. * fixed lot of missing pi_do_call's
  747. Revision 1.55 2003/05/24 17:15:24 jonas
  748. * added missing firstpass for withrefnode
  749. Revision 1.54 2003/05/11 14:45:12 peter
  750. * tloadnode does not support objectsymtable,withsymtable anymore
  751. * withnode cleanup
  752. * direct with rewritten to use temprefnode
  753. Revision 1.53 2003/05/09 17:47:02 peter
  754. * self moved to hidden parameter
  755. * removed hdisposen,hnewn,selfn
  756. Revision 1.52 2003/05/05 14:53:16 peter
  757. * vs_hidden replaced by is_hidden boolean
  758. Revision 1.51 2003/04/27 11:21:33 peter
  759. * aktprocdef renamed to current_procdef
  760. * procinfo renamed to current_procinfo
  761. * procinfo will now be stored in current_module so it can be
  762. cleaned up properly
  763. * gen_main_procsym changed to create_main_proc and release_main_proc
  764. to also generate a tprocinfo structure
  765. * fixed unit implicit initfinal
  766. Revision 1.50 2003/04/27 07:29:50 peter
  767. * current_procdef cleanup, current_procdef is now always nil when parsing
  768. a new procdef declaration
  769. * aktprocsym removed
  770. * lexlevel removed, use symtable.symtablelevel instead
  771. * implicit init/final code uses the normal genentry/genexit
  772. * funcret state checking updated for new funcret handling
  773. Revision 1.49 2003/04/23 10:10:54 peter
  774. * procvar is not compared in addrn
  775. Revision 1.48 2003/04/22 23:50:23 peter
  776. * firstpass uses expectloc
  777. * checks if there are differences between the expectloc and
  778. location.loc from secondpass in EXTDEBUG
  779. Revision 1.47 2003/04/10 17:57:52 peter
  780. * vs_hidden released
  781. Revision 1.46 2003/01/30 21:46:57 peter
  782. * self fixes for static methods (merged)
  783. Revision 1.45 2003/01/09 21:52:37 peter
  784. * merged some verbosity options.
  785. * V_LineInfo is a verbosity flag to include line info
  786. Revision 1.44 2003/01/06 21:16:52 peter
  787. * po_addressonly added to retrieve the address of a methodpointer
  788. only, this is used for @tclass.method which has no self pointer
  789. Revision 1.43 2003/01/04 15:54:03 daniel
  790. * Fixed mark_write for @ operator
  791. (can happen when compiling @procvar:=nil (Delphi mode construction))
  792. Revision 1.42 2003/01/03 12:15:56 daniel
  793. * Removed ifdefs around notifications
  794. ifdefs around for loop optimizations remain
  795. Revision 1.41 2002/11/25 17:43:20 peter
  796. * splitted defbase in defutil,symutil,defcmp
  797. * merged isconvertable and is_equal into compare_defs(_ext)
  798. * made operator search faster by walking the list only once
  799. Revision 1.40 2002/09/27 21:13:28 carl
  800. * low-highval always checked if limit ober 2GB is reached (to avoid overflow)
  801. Revision 1.39 2002/09/01 18:44:17 peter
  802. * cleanup of tvecnode.det_resulttype
  803. * move 0 element of string access check to resulttype
  804. Revision 1.38 2002/09/01 13:28:38 daniel
  805. - write_access fields removed in favor of a flag
  806. Revision 1.37 2002/09/01 08:01:16 daniel
  807. * Removed sets from Tcallnode.det_resulttype
  808. + Added read/write notifications of variables. These will be usefull
  809. for providing information for several optimizations. For example
  810. the value of the loop variable of a for loop does matter is the
  811. variable is read after the for loop, but if it's no longer used
  812. or written, it doesn't matter and this can be used to optimize
  813. the loop code generation.
  814. Revision 1.36 2002/08/19 19:36:43 peter
  815. * More fixes for cross unit inlining, all tnodes are now implemented
  816. * Moved pocall_internconst to po_internconst because it is not a
  817. calling type at all and it conflicted when inlining of these small
  818. functions was requested
  819. Revision 1.35 2002/07/23 09:51:23 daniel
  820. * Tried to make Tprocsym.defs protected. I didn't succeed but the cleanups
  821. are worth comitting.
  822. Revision 1.34 2002/07/20 11:57:54 florian
  823. * types.pas renamed to defbase.pas because D6 contains a types
  824. unit so this would conflicts if D6 programms are compiled
  825. + Willamette/SSE2 instructions to assembler added
  826. Revision 1.33 2002/05/18 13:34:10 peter
  827. * readded missing revisions
  828. Revision 1.32 2002/05/16 19:46:39 carl
  829. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  830. + try to fix temp allocation (still in ifdef)
  831. + generic constructor calls
  832. + start of tassembler / tmodulebase class cleanup
  833. Revision 1.30 2002/05/12 16:53:07 peter
  834. * moved entry and exitcode to ncgutil and cgobj
  835. * foreach gets extra argument for passing local data to the
  836. iterator function
  837. * -CR checks also class typecasts at runtime by changing them
  838. into as
  839. * fixed compiler to cycle with the -CR option
  840. * fixed stabs with elf writer, finally the global variables can
  841. be watched
  842. * removed a lot of routines from cga unit and replaced them by
  843. calls to cgobj
  844. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  845. u32bit then the other is typecasted also to u32bit without giving
  846. a rangecheck warning/error.
  847. * fixed pascal calling method with reversing also the high tree in
  848. the parast, detected by tcalcst3 test
  849. Revision 1.29 2002/04/21 19:02:04 peter
  850. * removed newn and disposen nodes, the code is now directly
  851. inlined from pexpr
  852. * -an option that will write the secondpass nodes to the .s file, this
  853. requires EXTDEBUG define to actually write the info
  854. * fixed various internal errors and crashes due recent code changes
  855. Revision 1.28 2002/04/20 21:32:23 carl
  856. + generic FPC_CHECKPOINTER
  857. + first parameter offset in stack now portable
  858. * rename some constants
  859. + move some cpu stuff to other units
  860. - remove unused constents
  861. * fix stacksize for some targets
  862. * fix generic size problems which depend now on EXTEND_SIZE constant
  863. Revision 1.27 2002/04/02 17:11:29 peter
  864. * tlocation,treference update
  865. * LOC_CONSTANT added for better constant handling
  866. * secondadd splitted in multiple routines
  867. * location_force_reg added for loading a location to a register
  868. of a specified size
  869. * secondassignment parses now first the right and then the left node
  870. (this is compatible with Kylix). This saves a lot of push/pop especially
  871. with string operations
  872. * adapted some routines to use the new cg methods
  873. Revision 1.26 2002/04/01 20:57:13 jonas
  874. * fixed web bug 1907
  875. * fixed some other procvar related bugs (all related to accepting procvar
  876. constructs with either too many or too little parameters)
  877. (both merged, includes second typo fix of pexpr.pas)
  878. }