nmem.pas 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  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. type
  25. tloadvmtaddrnode = class(tunarynode)
  26. constructor create(l : tnode);virtual;
  27. function pass_1 : tnode;override;
  28. function det_resulttype:tnode;override;
  29. end;
  30. tloadvmtaddrnodeclass = class of tloadvmtaddrnode;
  31. tloadparentfpnode = class(tunarynode)
  32. parentpd : tprocdef;
  33. parentpdderef : tderef;
  34. constructor create(pd:tprocdef);virtual;
  35. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  36. procedure ppuwrite(ppufile:tcompilerppufile);override;
  37. procedure buildderefimpl;override;
  38. procedure derefimpl;override;
  39. function pass_1 : tnode;override;
  40. function det_resulttype:tnode;override;
  41. function getcopy : tnode;override;
  42. end;
  43. tloadparentfpnodeclass = class of tloadparentfpnode;
  44. taddrnode = class(tunarynode)
  45. getprocvardef : tprocvardef;
  46. getprocvardefderef : tderef;
  47. constructor create(l : tnode);virtual;
  48. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  49. procedure ppuwrite(ppufile:tcompilerppufile);override;
  50. procedure mark_write;override;
  51. procedure buildderefimpl;override;
  52. procedure derefimpl;override;
  53. function getcopy : tnode;override;
  54. function pass_1 : tnode;override;
  55. function det_resulttype:tnode;override;
  56. end;
  57. taddrnodeclass = class of taddrnode;
  58. tderefnode = class(tunarynode)
  59. constructor create(l : tnode);virtual;
  60. function pass_1 : tnode;override;
  61. function det_resulttype:tnode;override;
  62. procedure mark_write;override;
  63. end;
  64. tderefnodeclass = class of tderefnode;
  65. tsubscriptnode = class(tunarynode)
  66. vs : tfieldvarsym;
  67. vsderef : tderef;
  68. constructor create(varsym : tsym;l : tnode);virtual;
  69. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  70. procedure ppuwrite(ppufile:tcompilerppufile);override;
  71. procedure buildderefimpl;override;
  72. procedure derefimpl;override;
  73. function getcopy : tnode;override;
  74. function pass_1 : tnode;override;
  75. function docompare(p: tnode): boolean; override;
  76. function det_resulttype:tnode;override;
  77. procedure mark_write;override;
  78. end;
  79. tsubscriptnodeclass = class of tsubscriptnode;
  80. tvecnode = class(tbinarynode)
  81. constructor create(l,r : tnode);virtual;
  82. function pass_1 : tnode;override;
  83. function det_resulttype:tnode;override;
  84. procedure mark_write;override;
  85. end;
  86. tvecnodeclass = class of tvecnode;
  87. twithnode = class(tunarynode)
  88. withsymtable : twithsymtable;
  89. tablecount : longint;
  90. withrefnode : tnode;
  91. constructor create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
  92. destructor destroy;override;
  93. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  94. procedure ppuwrite(ppufile:tcompilerppufile);override;
  95. function getcopy : tnode;override;
  96. function pass_1 : tnode;override;
  97. function docompare(p: tnode): boolean; override;
  98. function det_resulttype:tnode;override;
  99. end;
  100. twithnodeclass = class of twithnode;
  101. var
  102. cloadvmtaddrnode : tloadvmtaddrnodeclass;
  103. cloadparentfpnode : tloadparentfpnodeclass;
  104. caddrnode : taddrnodeclass;
  105. cderefnode : tderefnodeclass;
  106. csubscriptnode : tsubscriptnodeclass;
  107. cvecnode : tvecnodeclass;
  108. cwithnode : twithnodeclass;
  109. implementation
  110. uses
  111. globtype,systems,
  112. cutils,cclasses,verbose,globals,
  113. symconst,symbase,defutil,defcmp,
  114. nbas,nutils,
  115. htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase,procinfo
  116. ;
  117. {*****************************************************************************
  118. TLOADVMTADDRNODE
  119. *****************************************************************************}
  120. constructor tloadvmtaddrnode.create(l : tnode);
  121. begin
  122. inherited create(loadvmtaddrn,l);
  123. end;
  124. function tloadvmtaddrnode.det_resulttype:tnode;
  125. begin
  126. result:=nil;
  127. resulttypepass(left);
  128. if codegenerror then
  129. exit;
  130. case left.resulttype.def.deftype of
  131. classrefdef :
  132. resulttype:=left.resulttype;
  133. objectdef :
  134. resulttype.setdef(tclassrefdef.create(left.resulttype));
  135. else
  136. Message(parser_e_pointer_to_class_expected);
  137. end;
  138. end;
  139. function tloadvmtaddrnode.pass_1 : tnode;
  140. begin
  141. result:=nil;
  142. expectloc:=LOC_REGISTER;
  143. if left.nodetype<>typen then
  144. begin
  145. firstpass(left);
  146. registersint:=left.registersint;
  147. end;
  148. if registersint<1 then
  149. registersint:=1;
  150. end;
  151. {*****************************************************************************
  152. TLOADPARENTFPNODE
  153. *****************************************************************************}
  154. constructor tloadparentfpnode.create(pd:tprocdef);
  155. begin
  156. inherited create(loadparentfpn,nil);
  157. if not assigned(pd) then
  158. internalerror(200309288);
  159. if (pd.parast.symtablelevel>current_procinfo.procdef.parast.symtablelevel) then
  160. internalerror(200309284);
  161. parentpd:=pd;
  162. end;
  163. constructor tloadparentfpnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  164. begin
  165. inherited ppuload(t,ppufile);
  166. ppufile.getderef(parentpdderef);
  167. end;
  168. procedure tloadparentfpnode.ppuwrite(ppufile:tcompilerppufile);
  169. begin
  170. inherited ppuwrite(ppufile);
  171. ppufile.putderef(parentpdderef);
  172. end;
  173. procedure tloadparentfpnode.buildderefimpl;
  174. begin
  175. inherited buildderefimpl;
  176. parentpdderef.build(parentpd);
  177. end;
  178. procedure tloadparentfpnode.derefimpl;
  179. begin
  180. inherited derefimpl;
  181. parentpd:=tprocdef(parentpdderef.resolve);
  182. end;
  183. function tloadparentfpnode.getcopy : tnode;
  184. var
  185. p : tloadparentfpnode;
  186. begin
  187. p:=tloadparentfpnode(inherited getcopy);
  188. p.parentpd:=parentpd;
  189. getcopy:=p;
  190. end;
  191. function tloadparentfpnode.det_resulttype:tnode;
  192. begin
  193. result:=nil;
  194. resulttype:=voidpointertype;
  195. end;
  196. function tloadparentfpnode.pass_1 : tnode;
  197. begin
  198. result:=nil;
  199. expectloc:=LOC_REGISTER;
  200. registersint:=1;
  201. end;
  202. {*****************************************************************************
  203. TADDRNODE
  204. *****************************************************************************}
  205. constructor taddrnode.create(l : tnode);
  206. begin
  207. inherited create(addrn,l);
  208. getprocvardef:=nil;
  209. end;
  210. constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  211. begin
  212. inherited ppuload(t,ppufile);
  213. ppufile.getderef(getprocvardefderef);
  214. end;
  215. procedure taddrnode.ppuwrite(ppufile:tcompilerppufile);
  216. begin
  217. inherited ppuwrite(ppufile);
  218. ppufile.putderef(getprocvardefderef);
  219. end;
  220. procedure Taddrnode.mark_write;
  221. begin
  222. {@procvar:=nil is legal in Delphi mode.}
  223. left.mark_write;
  224. end;
  225. procedure taddrnode.buildderefimpl;
  226. begin
  227. inherited buildderefimpl;
  228. getprocvardefderef.build(getprocvardef);
  229. end;
  230. procedure taddrnode.derefimpl;
  231. begin
  232. inherited derefimpl;
  233. getprocvardef:=tprocvardef(getprocvardefderef.resolve);
  234. end;
  235. function taddrnode.getcopy : tnode;
  236. var
  237. p : taddrnode;
  238. begin
  239. p:=taddrnode(inherited getcopy);
  240. p.getprocvardef:=getprocvardef;
  241. getcopy:=p;
  242. end;
  243. procedure copyparasym(p:TNamedIndexItem;arg:pointer);
  244. var
  245. newparast : tsymtable absolute arg;
  246. vs : tparavarsym;
  247. begin
  248. if tsym(p).typ<>paravarsym then
  249. exit;
  250. with tparavarsym(p) do
  251. begin
  252. vs:=tparavarsym.create(realname,paranr,varspez,vartype);
  253. vs.varoptions:=varoptions;
  254. // vs.paraloc[callerside]:=paraloc[callerside].getcopy;
  255. // vs.paraloc[callerside]:=paraloc[callerside].getcopy;
  256. vs.defaultconstsym:=defaultconstsym;
  257. newparast.insert(vs);
  258. end;
  259. end;
  260. function taddrnode.det_resulttype:tnode;
  261. var
  262. hp : tnode;
  263. hp3 : tabstractprocdef;
  264. begin
  265. result:=nil;
  266. resulttypepass(left);
  267. if codegenerror then
  268. exit;
  269. make_not_regable(left);
  270. { don't allow constants }
  271. if is_constnode(left) then
  272. begin
  273. aktfilepos:=left.fileinfo;
  274. CGMessage(type_e_no_addr_of_constant);
  275. exit;
  276. end;
  277. { tp @procvar support (type of @procvar is a void pointer)
  278. Note: we need to leave the addrn in the tree,
  279. else we can't see the difference between @procvar and procvar.
  280. we set the procvarload flag so a secondpass does nothing for
  281. this node (PFV) }
  282. if (m_tp_procvar in aktmodeswitches) then
  283. begin
  284. case left.nodetype of
  285. calln :
  286. begin
  287. { a load of a procvar can't have parameters }
  288. if assigned(tcallnode(left).left) then
  289. CGMessage(parser_e_illegal_expression);
  290. { is it a procvar? }
  291. hp:=tcallnode(left).right;
  292. if assigned(hp) then
  293. begin
  294. { remove calln node }
  295. tcallnode(left).right:=nil;
  296. left.free;
  297. left:=hp;
  298. include(flags,nf_procvarload);
  299. end;
  300. end;
  301. loadn,
  302. subscriptn,
  303. typeconvn,
  304. vecn,
  305. derefn :
  306. begin
  307. if left.resulttype.def.deftype=procvardef then
  308. include(flags,nf_procvarload);
  309. end;
  310. end;
  311. if nf_procvarload in flags then
  312. begin
  313. resulttype:=voidpointertype;
  314. exit;
  315. end;
  316. end;
  317. { proc 2 procvar ? }
  318. if left.nodetype=calln then
  319. { if it were a valid construct, the addr node would already have }
  320. { been removed in the parser. This happens for (in FPC mode) }
  321. { procvar1 := @procvar2(parameters); }
  322. CGMessage(parser_e_illegal_expression)
  323. else
  324. if (left.nodetype=loadn) and (tloadnode(left).symtableentry.typ=procsym) then
  325. begin
  326. { result is a procedure variable }
  327. { No, to be TP compatible, you must return a voidpointer to
  328. the procedure that is stored in the procvar.}
  329. if not(m_tp_procvar in aktmodeswitches) then
  330. begin
  331. if assigned(getprocvardef) and
  332. (tprocsym(tloadnode(left).symtableentry).procdef_count>1) then
  333. begin
  334. hp3:=tprocsym(tloadnode(left).symtableentry).search_procdef_byprocvardef(getprocvardef);
  335. if not assigned(hp3) then
  336. begin
  337. IncompatibleTypes(tprocsym(tloadnode(left).symtableentry).first_procdef,getprocvardef);
  338. exit;
  339. end;
  340. end
  341. else
  342. hp3:=tabstractprocdef(tprocsym(tloadnode(left).symtableentry).first_procdef);
  343. { create procvardef }
  344. resulttype.setdef(tprocvardef.create(hp3.parast.symtablelevel));
  345. tprocvardef(resulttype.def).proctypeoption:=hp3.proctypeoption;
  346. tprocvardef(resulttype.def).proccalloption:=hp3.proccalloption;
  347. tprocvardef(resulttype.def).procoptions:=hp3.procoptions;
  348. tprocvardef(resulttype.def).rettype:=hp3.rettype;
  349. { method ? then set the methodpointer flag }
  350. if (hp3.owner.symtabletype=objectsymtable) then
  351. include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
  352. { only need the address of the method? this is needed
  353. for @tobject.create }
  354. if assigned(tloadnode(left).left) then
  355. include(flags,nf_procvarload)
  356. else
  357. include(tprocvardef(resulttype.def).procoptions,po_addressonly);
  358. { Add parameters use only references, we don't need to keep the
  359. parast. We use the parast from the original function to calculate
  360. our parameter data and reset it afterwards }
  361. hp3.parast.foreach_static(@copyparasym,tprocvardef(resulttype.def).parast);
  362. tprocvardef(resulttype.def).calcparas;
  363. end
  364. else
  365. begin
  366. if assigned(tloadnode(left).left) then
  367. CGMessage(parser_e_illegal_expression);
  368. resulttype:=voidpointertype;
  369. end;
  370. end
  371. else
  372. begin
  373. { what are we getting the address from an absolute sym? }
  374. hp:=left;
  375. while assigned(hp) and (hp.nodetype in [vecn,derefn,subscriptn]) do
  376. hp:=tunarynode(hp).left;
  377. {$ifdef i386}
  378. if assigned(hp) and
  379. (hp.nodetype=loadn) and
  380. ((tloadnode(hp).symtableentry.typ=absolutevarsym) and
  381. tabsolutevarsym(tloadnode(hp).symtableentry).absseg) then
  382. begin
  383. if not(nf_typedaddr in flags) then
  384. resulttype:=voidfarpointertype
  385. else
  386. resulttype.setdef(tpointerdef.createfar(left.resulttype));
  387. end
  388. else
  389. {$endif i386}
  390. begin
  391. if not(nf_typedaddr in flags) then
  392. resulttype:=voidpointertype
  393. else
  394. resulttype.setdef(tpointerdef.create(left.resulttype));
  395. end;
  396. end;
  397. { this is like the function addr }
  398. inc(parsing_para_level);
  399. set_varstate(left,vs_used,false);
  400. dec(parsing_para_level);
  401. end;
  402. function taddrnode.pass_1 : tnode;
  403. begin
  404. result:=nil;
  405. firstpass(left);
  406. if codegenerror then
  407. exit;
  408. if nf_procvarload in flags then
  409. begin
  410. registersint:=left.registersint;
  411. registersfpu:=left.registersfpu;
  412. {$ifdef SUPPORT_MMX}
  413. registersmmx:=left.registersmmx;
  414. {$endif SUPPORT_MMX}
  415. if registersint<1 then
  416. registersint:=1;
  417. expectloc:=left.expectloc;
  418. exit;
  419. end;
  420. { we should allow loc_mem for @string }
  421. if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  422. begin
  423. aktfilepos:=left.fileinfo;
  424. CGMessage(parser_e_illegal_expression);
  425. end;
  426. registersint:=left.registersint;
  427. registersfpu:=left.registersfpu;
  428. {$ifdef SUPPORT_MMX}
  429. registersmmx:=left.registersmmx;
  430. {$endif SUPPORT_MMX}
  431. if registersint<1 then
  432. registersint:=1;
  433. { is this right for object of methods ?? }
  434. expectloc:=LOC_REGISTER;
  435. end;
  436. {*****************************************************************************
  437. TDEREFNODE
  438. *****************************************************************************}
  439. constructor tderefnode.create(l : tnode);
  440. begin
  441. inherited create(derefn,l);
  442. end;
  443. function tderefnode.det_resulttype:tnode;
  444. begin
  445. result:=nil;
  446. resulttypepass(left);
  447. set_varstate(left,vs_used,true);
  448. if codegenerror then
  449. exit;
  450. { tp procvar support }
  451. maybe_call_procvar(left,true);
  452. if left.resulttype.def.deftype=pointerdef then
  453. resulttype:=tpointerdef(left.resulttype.def).pointertype
  454. else
  455. CGMessage(parser_e_invalid_qualifier);
  456. end;
  457. procedure Tderefnode.mark_write;
  458. begin
  459. include(flags,nf_write);
  460. end;
  461. function tderefnode.pass_1 : tnode;
  462. begin
  463. result:=nil;
  464. firstpass(left);
  465. if codegenerror then
  466. exit;
  467. registersint:=max(left.registersint,1);
  468. registersfpu:=left.registersfpu;
  469. {$ifdef SUPPORT_MMX}
  470. registersmmx:=left.registersmmx;
  471. {$endif SUPPORT_MMX}
  472. expectloc:=LOC_REFERENCE;
  473. end;
  474. {*****************************************************************************
  475. TSUBSCRIPTNODE
  476. *****************************************************************************}
  477. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  478. begin
  479. inherited create(subscriptn,l);
  480. { vs should be changed to tsym! }
  481. vs:=tfieldvarsym(varsym);
  482. end;
  483. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  484. begin
  485. inherited ppuload(t,ppufile);
  486. ppufile.getderef(vsderef);
  487. end;
  488. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  489. begin
  490. inherited ppuwrite(ppufile);
  491. ppufile.putderef(vsderef);
  492. end;
  493. procedure tsubscriptnode.buildderefimpl;
  494. begin
  495. inherited buildderefimpl;
  496. vsderef.build(vs);
  497. end;
  498. procedure tsubscriptnode.derefimpl;
  499. begin
  500. inherited derefimpl;
  501. vs:=tfieldvarsym(vsderef.resolve);
  502. end;
  503. function tsubscriptnode.getcopy : tnode;
  504. var
  505. p : tsubscriptnode;
  506. begin
  507. p:=tsubscriptnode(inherited getcopy);
  508. p.vs:=vs;
  509. getcopy:=p;
  510. end;
  511. function tsubscriptnode.det_resulttype:tnode;
  512. begin
  513. result:=nil;
  514. resulttypepass(left);
  515. { tp procvar support }
  516. maybe_call_procvar(left,true);
  517. resulttype:=vs.vartype;
  518. end;
  519. procedure Tsubscriptnode.mark_write;
  520. begin
  521. include(flags,nf_write);
  522. end;
  523. function tsubscriptnode.pass_1 : tnode;
  524. begin
  525. result:=nil;
  526. firstpass(left);
  527. if codegenerror then
  528. exit;
  529. registersint:=left.registersint;
  530. registersfpu:=left.registersfpu;
  531. {$ifdef SUPPORT_MMX}
  532. registersmmx:=left.registersmmx;
  533. {$endif SUPPORT_MMX}
  534. { classes must be dereferenced implicit }
  535. if is_class_or_interface(left.resulttype.def) then
  536. begin
  537. if registersint=0 then
  538. registersint:=1;
  539. expectloc:=LOC_REFERENCE;
  540. end
  541. else
  542. begin
  543. if (left.expectloc<>LOC_CREFERENCE) and
  544. (left.expectloc<>LOC_REFERENCE) then
  545. CGMessage(parser_e_illegal_expression);
  546. expectloc:=left.expectloc;
  547. end;
  548. end;
  549. function tsubscriptnode.docompare(p: tnode): boolean;
  550. begin
  551. docompare :=
  552. inherited docompare(p) and
  553. (vs = tsubscriptnode(p).vs);
  554. end;
  555. {*****************************************************************************
  556. TVECNODE
  557. *****************************************************************************}
  558. constructor tvecnode.create(l,r : tnode);
  559. begin
  560. inherited create(vecn,l,r);
  561. end;
  562. function tvecnode.det_resulttype:tnode;
  563. var
  564. htype : ttype;
  565. valid : boolean;
  566. begin
  567. result:=nil;
  568. resulttypepass(left);
  569. resulttypepass(right);
  570. { In p[1] p is always valid, it is not possible to
  571. declared a shortstring or normal array that has
  572. undefined number of elements. Dynamic array and
  573. ansi/widestring needs to be valid }
  574. valid:=is_dynamic_array(left.resulttype.def) or
  575. is_ansistring(left.resulttype.def) or
  576. is_widestring(left.resulttype.def);
  577. set_varstate(left,vs_used,valid);
  578. set_varstate(right,vs_used,true);
  579. if codegenerror then
  580. exit;
  581. { maybe type conversion for the index value, but
  582. do not convert enums,booleans,char }
  583. if (right.resulttype.def.deftype<>enumdef) and
  584. not(is_char(right.resulttype.def)) and
  585. not(is_boolean(right.resulttype.def)) then
  586. begin
  587. inserttypeconv(right,s32inttype);
  588. end;
  589. case left.resulttype.def.deftype of
  590. arraydef :
  591. begin
  592. { check type of the index value }
  593. if (compare_defs(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,right.nodetype)=te_incompatible) then
  594. IncompatibleTypes(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def);
  595. resulttype:=tarraydef(left.resulttype.def).elementtype;
  596. end;
  597. pointerdef :
  598. begin
  599. { are we accessing a pointer[], then convert the pointer to
  600. an array first, in FPC this is allowed for all pointers in
  601. delphi/tp7 it's only allowed for pchars }
  602. if (m_fpc in aktmodeswitches) or
  603. is_pchar(left.resulttype.def) or
  604. is_pwidechar(left.resulttype.def) then
  605. begin
  606. { convert pointer to array }
  607. htype.setdef(tarraydef.create_from_pointer(tpointerdef(left.resulttype.def).pointertype));
  608. inserttypeconv(left,htype);
  609. resulttype:=tarraydef(htype.def).elementtype;
  610. end
  611. else
  612. CGMessage(type_e_array_required);
  613. end;
  614. stringdef :
  615. begin
  616. { indexed access to 0 element is only allowed for shortstrings }
  617. if (right.nodetype=ordconstn) and
  618. (tordconstnode(right).value=0) and
  619. not(is_shortstring(left.resulttype.def)) then
  620. CGMessage(cg_e_can_access_element_zero);
  621. case tstringdef(left.resulttype.def).string_typ of
  622. st_widestring :
  623. resulttype:=cwidechartype;
  624. {$ifdef ansistring_bits}
  625. st_ansistring16,st_ansistring32,st_ansistring64 :
  626. {$else}
  627. st_ansistring :
  628. {$endif}
  629. resulttype:=cchartype;
  630. st_longstring :
  631. resulttype:=cchartype;
  632. st_shortstring :
  633. resulttype:=cchartype;
  634. end;
  635. end;
  636. variantdef :
  637. resulttype:=cvarianttype;
  638. else
  639. CGMessage(type_e_array_required);
  640. end;
  641. end;
  642. procedure Tvecnode.mark_write;
  643. begin
  644. include(flags,nf_write);
  645. end;
  646. function tvecnode.pass_1 : tnode;
  647. {$ifdef consteval}
  648. var
  649. tcsym : ttypedconstsym;
  650. {$endif}
  651. begin
  652. result:=nil;
  653. firstpass(left);
  654. firstpass(right);
  655. if codegenerror then
  656. exit;
  657. if (nf_callunique in flags) and
  658. (is_ansistring(left.resulttype.def) or
  659. is_widestring(left.resulttype.def)) then
  660. begin
  661. left := ctypeconvnode.create_internal(ccallnode.createintern('fpc_'+tstringdef(left.resulttype.def).stringtypname+'_unique',
  662. ccallparanode.create(
  663. ctypeconvnode.create_internal(left,voidpointertype),nil)),
  664. left.resulttype);
  665. firstpass(left);
  666. { double resulttype passes somwhere else may cause this to be }
  667. { reset though :/ }
  668. exclude(flags,nf_callunique);
  669. end;
  670. { the register calculation is easy if a const index is used }
  671. if right.nodetype=ordconstn then
  672. begin
  673. {$ifdef consteval}
  674. { constant evaluation }
  675. if (left.nodetype=loadn) and
  676. (left.symtableentry.typ=typedconstsym) then
  677. begin
  678. tcsym:=ttypedconstsym(left.symtableentry);
  679. if tcsym.defintion^.typ=stringdef then
  680. begin
  681. end;
  682. end;
  683. {$endif}
  684. registersint:=left.registersint;
  685. { for ansi/wide strings, we need at least one register }
  686. if is_ansistring(left.resulttype.def) or
  687. is_widestring(left.resulttype.def) or
  688. { ... as well as for dynamic arrays }
  689. is_dynamic_array(left.resulttype.def) then
  690. registersint:=max(registersint,1);
  691. end
  692. else
  693. begin
  694. { this rules are suboptimal, but they should give }
  695. { good results }
  696. registersint:=max(left.registersint,right.registersint);
  697. { for ansi/wide strings, we need at least one register }
  698. if is_ansistring(left.resulttype.def) or
  699. is_widestring(left.resulttype.def) or
  700. { ... as well as for dynamic arrays }
  701. is_dynamic_array(left.resulttype.def) then
  702. registersint:=max(registersint,1);
  703. { need we an extra register when doing the restore ? }
  704. if (left.registersint<=right.registersint) and
  705. { only if the node needs less than 3 registers }
  706. { two for the right node and one for the }
  707. { left address }
  708. (registersint<3) then
  709. inc(registersint);
  710. { need we an extra register for the index ? }
  711. if (right.expectloc<>LOC_REGISTER)
  712. { only if the right node doesn't need a register }
  713. and (right.registersint<1) then
  714. inc(registersint);
  715. { not correct, but what works better ?
  716. if left.registersint>0 then
  717. registersint:=max(registersint,2)
  718. else
  719. min. one register
  720. registersint:=max(registersint,1);
  721. }
  722. end;
  723. registersfpu:=max(left.registersfpu,right.registersfpu);
  724. {$ifdef SUPPORT_MMX}
  725. registersmmx:=max(left.registersmmx,right.registersmmx);
  726. {$endif SUPPORT_MMX}
  727. if left.expectloc=LOC_CREFERENCE then
  728. expectloc:=LOC_CREFERENCE
  729. else
  730. expectloc:=LOC_REFERENCE;
  731. end;
  732. {*****************************************************************************
  733. TWITHNODE
  734. *****************************************************************************}
  735. constructor twithnode.create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
  736. begin
  737. inherited create(withn,l);
  738. withrefnode:=r;
  739. withsymtable:=symtable;
  740. tablecount:=count;
  741. set_file_line(l);
  742. end;
  743. destructor twithnode.destroy;
  744. var
  745. hsymt,
  746. symt : tsymtable;
  747. i : longint;
  748. begin
  749. symt:=withsymtable;
  750. for i:=1 to tablecount do
  751. begin
  752. if assigned(symt) then
  753. begin
  754. hsymt:=symt.next;
  755. symt.free;
  756. symt:=hsymt;
  757. end;
  758. end;
  759. inherited destroy;
  760. end;
  761. constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  762. begin
  763. inherited ppuload(t,ppufile);
  764. internalerror(200208192);
  765. end;
  766. procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
  767. begin
  768. inherited ppuwrite(ppufile);
  769. internalerror(200208193);
  770. end;
  771. function twithnode.getcopy : tnode;
  772. var
  773. p : twithnode;
  774. begin
  775. p:=twithnode(inherited getcopy);
  776. p.withsymtable:=withsymtable;
  777. p.tablecount:=tablecount;
  778. if assigned(p.withrefnode) then
  779. p.withrefnode:=withrefnode.getcopy
  780. else
  781. p.withrefnode:=nil;
  782. result:=p;
  783. end;
  784. function twithnode.det_resulttype:tnode;
  785. begin
  786. result:=nil;
  787. resulttype:=voidtype;
  788. resulttypepass(withrefnode);
  789. //unset_varstate(withrefnode);
  790. set_varstate(withrefnode,vs_used,true);
  791. if codegenerror then
  792. exit;
  793. if (withrefnode.nodetype=vecn) and
  794. (nf_memseg in withrefnode.flags) then
  795. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  796. if assigned(left) then
  797. resulttypepass(left);
  798. end;
  799. function twithnode.pass_1 : tnode;
  800. begin
  801. result:=nil;
  802. expectloc:=LOC_VOID;
  803. if assigned(left) then
  804. begin
  805. firstpass(left);
  806. registersint:=left.registersint;
  807. registersfpu:=left.registersfpu;
  808. {$ifdef SUPPORT_MMX}
  809. registersmmx:=left.registersmmx;
  810. {$endif SUPPORT_MMX}
  811. end;
  812. if assigned(withrefnode) then
  813. begin
  814. firstpass(withrefnode);
  815. if withrefnode.registersint > registersint then
  816. registersint:=withrefnode.registersint;
  817. if withrefnode.registersfpu > registersfpu then
  818. registersint:=withrefnode.registersfpu;
  819. {$ifdef SUPPORT_MMX}
  820. if withrefnode.registersmmx > registersmmx then
  821. registersmmx:=withrefnode.registersmmx;
  822. {$endif SUPPORT_MMX}
  823. end;
  824. end;
  825. function twithnode.docompare(p: tnode): boolean;
  826. begin
  827. docompare :=
  828. inherited docompare(p) and
  829. (withsymtable = twithnode(p).withsymtable) and
  830. (tablecount = twithnode(p).tablecount) and
  831. (withrefnode.isequal(twithnode(p).withrefnode));
  832. end;
  833. begin
  834. cloadvmtaddrnode := tloadvmtaddrnode;
  835. caddrnode := taddrnode;
  836. cderefnode := tderefnode;
  837. csubscriptnode := tsubscriptnode;
  838. cvecnode := tvecnode;
  839. cwithnode := twithnode;
  840. end.
  841. {
  842. $Log$
  843. Revision 1.91 2004-11-29 17:32:56 peter
  844. * prevent some IEs with delphi methodpointers
  845. Revision 1.90 2004/11/26 22:33:24 peter
  846. * don't allow @method in tp procvar mode
  847. Revision 1.89 2004/11/15 23:35:31 peter
  848. * tparaitem removed, use tparavarsym instead
  849. * parameter order is now calculated from paranr value in tparavarsym
  850. Revision 1.88 2004/11/08 22:09:59 peter
  851. * tvarsym splitted
  852. Revision 1.87 2004/11/02 12:55:16 peter
  853. * nf_internal flag for internal inserted typeconvs. This will
  854. supress the generation of warning/hints
  855. Revision 1.86 2004/09/26 17:45:30 peter
  856. * simple regvar support, not yet finished
  857. Revision 1.85 2004/06/20 08:55:29 florian
  858. * logs truncated
  859. Revision 1.84 2004/06/16 20:07:09 florian
  860. * dwarf branch merged
  861. Revision 1.83 2004/04/29 19:56:37 daniel
  862. * Prepare compiler infrastructure for multiple ansistring types
  863. Revision 1.82.2.1 2004/04/28 19:55:51 peter
  864. * new warning for ordinal-pointer when size is different
  865. * fixed some cg_e_ messages to the correct section type_e_ or parser_e_
  866. Revision 1.82 2004/03/29 14:42:52 peter
  867. * variant array support
  868. Revision 1.81 2004/03/18 16:19:03 peter
  869. * fixed operator overload allowing for pointer-string
  870. * replaced some type_e_mismatch with more informational messages
  871. }