nmem.pas 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  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. begin
  586. left := ctypeconvnode.create_explicit(ccallnode.createintern('fpc_'+tstringdef(left.resulttype.def).stringtypname+'_unique',
  587. ccallparanode.create(
  588. ctypeconvnode.create_explicit(left,voidpointertype),nil)),
  589. left.resulttype);
  590. firstpass(left);
  591. { double resulttype passes somwhere else may cause this to be }
  592. { reset though :/ }
  593. exclude(flags,nf_callunique);
  594. end;
  595. { the register calculation is easy if a const index is used }
  596. if right.nodetype=ordconstn then
  597. begin
  598. {$ifdef consteval}
  599. { constant evaluation }
  600. if (left.nodetype=loadn) and
  601. (left.symtableentry.typ=typedconstsym) then
  602. begin
  603. tcsym:=ttypedconstsym(left.symtableentry);
  604. if tcsym.defintion^.typ=stringdef then
  605. begin
  606. end;
  607. end;
  608. {$endif}
  609. registers32:=left.registers32;
  610. { for ansi/wide strings, we need at least one register }
  611. if is_ansistring(left.resulttype.def) or
  612. is_widestring(left.resulttype.def) or
  613. { ... as well as for dynamic arrays }
  614. is_dynamic_array(left.resulttype.def) then
  615. registers32:=max(registers32,1);
  616. end
  617. else
  618. begin
  619. { this rules are suboptimal, but they should give }
  620. { good results }
  621. registers32:=max(left.registers32,right.registers32);
  622. { for ansi/wide strings, we need at least one register }
  623. if is_ansistring(left.resulttype.def) or
  624. is_widestring(left.resulttype.def) or
  625. { ... as well as for dynamic arrays }
  626. is_dynamic_array(left.resulttype.def) then
  627. registers32:=max(registers32,1);
  628. { need we an extra register when doing the restore ? }
  629. if (left.registers32<=right.registers32) and
  630. { only if the node needs less than 3 registers }
  631. { two for the right node and one for the }
  632. { left address }
  633. (registers32<3) then
  634. inc(registers32);
  635. { need we an extra register for the index ? }
  636. if (right.expectloc<>LOC_REGISTER)
  637. { only if the right node doesn't need a register }
  638. and (right.registers32<1) then
  639. inc(registers32);
  640. { not correct, but what works better ?
  641. if left.registers32>0 then
  642. registers32:=max(registers32,2)
  643. else
  644. min. one register
  645. registers32:=max(registers32,1);
  646. }
  647. end;
  648. registersfpu:=max(left.registersfpu,right.registersfpu);
  649. {$ifdef SUPPORT_MMX}
  650. registersmmx:=max(left.registersmmx,right.registersmmx);
  651. {$endif SUPPORT_MMX}
  652. if left.expectloc=LOC_CREFERENCE then
  653. expectloc:=LOC_CREFERENCE
  654. else
  655. expectloc:=LOC_REFERENCE;
  656. end;
  657. {*****************************************************************************
  658. TWITHNODE
  659. *****************************************************************************}
  660. constructor twithnode.create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
  661. begin
  662. inherited create(withn,l);
  663. withrefnode:=r;
  664. withsymtable:=symtable;
  665. tablecount:=count;
  666. set_file_line(l);
  667. end;
  668. destructor twithnode.destroy;
  669. var
  670. hsymt,
  671. symt : tsymtable;
  672. i : longint;
  673. begin
  674. symt:=withsymtable;
  675. for i:=1 to tablecount do
  676. begin
  677. if assigned(symt) then
  678. begin
  679. hsymt:=symt.next;
  680. symt.free;
  681. symt:=hsymt;
  682. end;
  683. end;
  684. inherited destroy;
  685. end;
  686. constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  687. begin
  688. inherited ppuload(t,ppufile);
  689. internalerror(200208192);
  690. end;
  691. procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
  692. begin
  693. inherited ppuwrite(ppufile);
  694. internalerror(200208193);
  695. end;
  696. function twithnode.getcopy : tnode;
  697. var
  698. p : twithnode;
  699. begin
  700. p:=twithnode(inherited getcopy);
  701. p.withsymtable:=withsymtable;
  702. p.tablecount:=tablecount;
  703. if assigned(p.withrefnode) then
  704. p.withrefnode:=withrefnode.getcopy
  705. else
  706. p.withrefnode:=nil;
  707. result:=p;
  708. end;
  709. function twithnode.det_resulttype:tnode;
  710. begin
  711. result:=nil;
  712. resulttype:=voidtype;
  713. resulttypepass(withrefnode);
  714. unset_varstate(withrefnode);
  715. set_varstate(withrefnode,true);
  716. if codegenerror then
  717. exit;
  718. if (withrefnode.nodetype=vecn) and
  719. (nf_memseg in withrefnode.flags) then
  720. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  721. if assigned(left) then
  722. resulttypepass(left);
  723. end;
  724. function twithnode.pass_1 : tnode;
  725. begin
  726. result:=nil;
  727. expectloc:=LOC_VOID;
  728. if assigned(left) then
  729. begin
  730. firstpass(left);
  731. registers32:=left.registers32;
  732. registersfpu:=left.registersfpu;
  733. {$ifdef SUPPORT_MMX}
  734. registersmmx:=left.registersmmx;
  735. {$endif SUPPORT_MMX}
  736. end;
  737. if assigned(withrefnode) then
  738. begin
  739. firstpass(withrefnode);
  740. if withrefnode.registers32 > registers32 then
  741. registers32:=withrefnode.registers32;
  742. if withrefnode.registersfpu > registersfpu then
  743. registers32:=withrefnode.registersfpu;
  744. {$ifdef SUPPORT_MMX}
  745. if withrefnode.registersmmx > registersmmx then
  746. registersmmx:=withrefnode.registersmmx;
  747. {$endif SUPPORT_MMX}
  748. end;
  749. end;
  750. function twithnode.docompare(p: tnode): boolean;
  751. begin
  752. docompare :=
  753. inherited docompare(p) and
  754. (withsymtable = twithnode(p).withsymtable) and
  755. (tablecount = twithnode(p).tablecount) and
  756. (withrefnode.isequal(twithnode(p).withrefnode));
  757. end;
  758. begin
  759. cloadvmtaddrnode := tloadvmtaddrnode;
  760. caddrnode := taddrnode;
  761. cdoubleaddrnode := tdoubleaddrnode;
  762. cderefnode := tderefnode;
  763. csubscriptnode := tsubscriptnode;
  764. cvecnode := tvecnode;
  765. cwithnode := twithnode;
  766. end.
  767. {
  768. $Log$
  769. Revision 1.59 2003-06-17 19:24:08 jonas
  770. * fixed conversion of fpc_*str_unique to compilerproc
  771. Revision 1.58 2003/06/17 16:34:44 jonas
  772. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  773. * renamed all_intregisters to volatile_intregisters and made it
  774. processor dependent
  775. Revision 1.57 2003/06/07 20:26:32 peter
  776. * re-resolving added instead of reloading from ppu
  777. * tderef object added to store deref info for resolving
  778. Revision 1.56 2003/06/07 18:57:04 jonas
  779. + added freeintparaloc
  780. * ppc get/freeintparaloc now check whether the parameter regs are
  781. properly allocated/deallocated (and get an extra list para)
  782. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  783. * fixed lot of missing pi_do_call's
  784. Revision 1.55 2003/05/24 17:15:24 jonas
  785. * added missing firstpass for withrefnode
  786. Revision 1.54 2003/05/11 14:45:12 peter
  787. * tloadnode does not support objectsymtable,withsymtable anymore
  788. * withnode cleanup
  789. * direct with rewritten to use temprefnode
  790. Revision 1.53 2003/05/09 17:47:02 peter
  791. * self moved to hidden parameter
  792. * removed hdisposen,hnewn,selfn
  793. Revision 1.52 2003/05/05 14:53:16 peter
  794. * vs_hidden replaced by is_hidden boolean
  795. Revision 1.51 2003/04/27 11:21:33 peter
  796. * aktprocdef renamed to current_procdef
  797. * procinfo renamed to current_procinfo
  798. * procinfo will now be stored in current_module so it can be
  799. cleaned up properly
  800. * gen_main_procsym changed to create_main_proc and release_main_proc
  801. to also generate a tprocinfo structure
  802. * fixed unit implicit initfinal
  803. Revision 1.50 2003/04/27 07:29:50 peter
  804. * current_procdef cleanup, current_procdef is now always nil when parsing
  805. a new procdef declaration
  806. * aktprocsym removed
  807. * lexlevel removed, use symtable.symtablelevel instead
  808. * implicit init/final code uses the normal genentry/genexit
  809. * funcret state checking updated for new funcret handling
  810. Revision 1.49 2003/04/23 10:10:54 peter
  811. * procvar is not compared in addrn
  812. Revision 1.48 2003/04/22 23:50:23 peter
  813. * firstpass uses expectloc
  814. * checks if there are differences between the expectloc and
  815. location.loc from secondpass in EXTDEBUG
  816. Revision 1.47 2003/04/10 17:57:52 peter
  817. * vs_hidden released
  818. Revision 1.46 2003/01/30 21:46:57 peter
  819. * self fixes for static methods (merged)
  820. Revision 1.45 2003/01/09 21:52:37 peter
  821. * merged some verbosity options.
  822. * V_LineInfo is a verbosity flag to include line info
  823. Revision 1.44 2003/01/06 21:16:52 peter
  824. * po_addressonly added to retrieve the address of a methodpointer
  825. only, this is used for @tclass.method which has no self pointer
  826. Revision 1.43 2003/01/04 15:54:03 daniel
  827. * Fixed mark_write for @ operator
  828. (can happen when compiling @procvar:=nil (Delphi mode construction))
  829. Revision 1.42 2003/01/03 12:15:56 daniel
  830. * Removed ifdefs around notifications
  831. ifdefs around for loop optimizations remain
  832. Revision 1.41 2002/11/25 17:43:20 peter
  833. * splitted defbase in defutil,symutil,defcmp
  834. * merged isconvertable and is_equal into compare_defs(_ext)
  835. * made operator search faster by walking the list only once
  836. Revision 1.40 2002/09/27 21:13:28 carl
  837. * low-highval always checked if limit ober 2GB is reached (to avoid overflow)
  838. Revision 1.39 2002/09/01 18:44:17 peter
  839. * cleanup of tvecnode.det_resulttype
  840. * move 0 element of string access check to resulttype
  841. Revision 1.38 2002/09/01 13:28:38 daniel
  842. - write_access fields removed in favor of a flag
  843. Revision 1.37 2002/09/01 08:01:16 daniel
  844. * Removed sets from Tcallnode.det_resulttype
  845. + Added read/write notifications of variables. These will be usefull
  846. for providing information for several optimizations. For example
  847. the value of the loop variable of a for loop does matter is the
  848. variable is read after the for loop, but if it's no longer used
  849. or written, it doesn't matter and this can be used to optimize
  850. the loop code generation.
  851. Revision 1.36 2002/08/19 19:36:43 peter
  852. * More fixes for cross unit inlining, all tnodes are now implemented
  853. * Moved pocall_internconst to po_internconst because it is not a
  854. calling type at all and it conflicted when inlining of these small
  855. functions was requested
  856. Revision 1.35 2002/07/23 09:51:23 daniel
  857. * Tried to make Tprocsym.defs protected. I didn't succeed but the cleanups
  858. are worth comitting.
  859. Revision 1.34 2002/07/20 11:57:54 florian
  860. * types.pas renamed to defbase.pas because D6 contains a types
  861. unit so this would conflicts if D6 programms are compiled
  862. + Willamette/SSE2 instructions to assembler added
  863. Revision 1.33 2002/05/18 13:34:10 peter
  864. * readded missing revisions
  865. Revision 1.32 2002/05/16 19:46:39 carl
  866. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  867. + try to fix temp allocation (still in ifdef)
  868. + generic constructor calls
  869. + start of tassembler / tmodulebase class cleanup
  870. Revision 1.30 2002/05/12 16:53:07 peter
  871. * moved entry and exitcode to ncgutil and cgobj
  872. * foreach gets extra argument for passing local data to the
  873. iterator function
  874. * -CR checks also class typecasts at runtime by changing them
  875. into as
  876. * fixed compiler to cycle with the -CR option
  877. * fixed stabs with elf writer, finally the global variables can
  878. be watched
  879. * removed a lot of routines from cga unit and replaced them by
  880. calls to cgobj
  881. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  882. u32bit then the other is typecasted also to u32bit without giving
  883. a rangecheck warning/error.
  884. * fixed pascal calling method with reversing also the high tree in
  885. the parast, detected by tcalcst3 test
  886. Revision 1.29 2002/04/21 19:02:04 peter
  887. * removed newn and disposen nodes, the code is now directly
  888. inlined from pexpr
  889. * -an option that will write the secondpass nodes to the .s file, this
  890. requires EXTDEBUG define to actually write the info
  891. * fixed various internal errors and crashes due recent code changes
  892. Revision 1.28 2002/04/20 21:32:23 carl
  893. + generic FPC_CHECKPOINTER
  894. + first parameter offset in stack now portable
  895. * rename some constants
  896. + move some cpu stuff to other units
  897. - remove unused constents
  898. * fix stacksize for some targets
  899. * fix generic size problems which depend now on EXTEND_SIZE constant
  900. Revision 1.27 2002/04/02 17:11:29 peter
  901. * tlocation,treference update
  902. * LOC_CONSTANT added for better constant handling
  903. * secondadd splitted in multiple routines
  904. * location_force_reg added for loading a location to a register
  905. of a specified size
  906. * secondassignment parses now first the right and then the left node
  907. (this is compatible with Kylix). This saves a lot of push/pop especially
  908. with string operations
  909. * adapted some routines to use the new cg methods
  910. Revision 1.26 2002/04/01 20:57:13 jonas
  911. * fixed web bug 1907
  912. * fixed some other procvar related bugs (all related to accepting procvar
  913. constructs with either too many or too little parameters)
  914. (both merged, includes second typo fix of pexpr.pas)
  915. }