nmem.pas 39 KB

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