nmem.pas 35 KB

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