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. { the address is already available when loading a procedure of object }
  327. if assigned(tloadnode(left).left) then
  328. include(flags,nf_procvarload);
  329. { result is a procedure variable }
  330. { No, to be TP compatible, you must return a voidpointer to
  331. the procedure that is stored in the procvar.}
  332. if not(m_tp_procvar in aktmodeswitches) then
  333. begin
  334. if assigned(getprocvardef) and
  335. (tprocsym(tloadnode(left).symtableentry).procdef_count>1) then
  336. begin
  337. hp3:=tprocsym(tloadnode(left).symtableentry).search_procdef_byprocvardef(getprocvardef);
  338. if not assigned(hp3) then
  339. begin
  340. IncompatibleTypes(tprocsym(tloadnode(left).symtableentry).first_procdef,getprocvardef);
  341. exit;
  342. end;
  343. end
  344. else
  345. hp3:=tabstractprocdef(tprocsym(tloadnode(left).symtableentry).first_procdef);
  346. { create procvardef }
  347. resulttype.setdef(tprocvardef.create(hp3.parast.symtablelevel));
  348. tprocvardef(resulttype.def).proctypeoption:=hp3.proctypeoption;
  349. tprocvardef(resulttype.def).proccalloption:=hp3.proccalloption;
  350. tprocvardef(resulttype.def).procoptions:=hp3.procoptions;
  351. tprocvardef(resulttype.def).rettype:=hp3.rettype;
  352. { method ? then set the methodpointer flag }
  353. if (hp3.owner.symtabletype=objectsymtable) then
  354. include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
  355. { only need the address of the method? this is needed
  356. for @tobject.create }
  357. if not assigned(tloadnode(left).left) then
  358. include(tprocvardef(resulttype.def).procoptions,po_addressonly);
  359. { Add parameters use only references, we don't need to keep the
  360. parast. We use the parast from the original function to calculate
  361. our parameter data and reset it afterwards }
  362. hp3.parast.foreach_static(@copyparasym,tprocvardef(resulttype.def).parast);
  363. tprocvardef(resulttype.def).calcparas;
  364. end
  365. else
  366. begin
  367. if assigned(tloadnode(left).left) then
  368. CGMessage(parser_e_illegal_expression)
  369. else
  370. resulttype:=voidpointertype;
  371. end;
  372. end
  373. else
  374. begin
  375. { what are we getting the address from an absolute sym? }
  376. hp:=left;
  377. while assigned(hp) and (hp.nodetype in [vecn,derefn,subscriptn]) do
  378. hp:=tunarynode(hp).left;
  379. {$ifdef i386}
  380. if assigned(hp) and
  381. (hp.nodetype=loadn) and
  382. ((tloadnode(hp).symtableentry.typ=absolutevarsym) and
  383. tabsolutevarsym(tloadnode(hp).symtableentry).absseg) then
  384. begin
  385. if not(nf_typedaddr in flags) then
  386. resulttype:=voidfarpointertype
  387. else
  388. resulttype.setdef(tpointerdef.createfar(left.resulttype));
  389. end
  390. else
  391. {$endif i386}
  392. begin
  393. if not(nf_typedaddr in flags) then
  394. resulttype:=voidpointertype
  395. else
  396. resulttype.setdef(tpointerdef.create(left.resulttype));
  397. end;
  398. end;
  399. { this is like the function addr }
  400. inc(parsing_para_level);
  401. set_varstate(left,vs_used,false);
  402. dec(parsing_para_level);
  403. end;
  404. function taddrnode.pass_1 : tnode;
  405. begin
  406. result:=nil;
  407. firstpass(left);
  408. if codegenerror then
  409. exit;
  410. if nf_procvarload in flags then
  411. begin
  412. registersint:=left.registersint;
  413. registersfpu:=left.registersfpu;
  414. {$ifdef SUPPORT_MMX}
  415. registersmmx:=left.registersmmx;
  416. {$endif SUPPORT_MMX}
  417. if registersint<1 then
  418. registersint:=1;
  419. expectloc:=left.expectloc;
  420. exit;
  421. end;
  422. { we should allow loc_mem for @string }
  423. if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  424. begin
  425. aktfilepos:=left.fileinfo;
  426. CGMessage(parser_e_illegal_expression);
  427. end;
  428. registersint:=left.registersint;
  429. registersfpu:=left.registersfpu;
  430. {$ifdef SUPPORT_MMX}
  431. registersmmx:=left.registersmmx;
  432. {$endif SUPPORT_MMX}
  433. if registersint<1 then
  434. registersint:=1;
  435. { is this right for object of methods ?? }
  436. expectloc:=LOC_REGISTER;
  437. end;
  438. {*****************************************************************************
  439. TDEREFNODE
  440. *****************************************************************************}
  441. constructor tderefnode.create(l : tnode);
  442. begin
  443. inherited create(derefn,l);
  444. end;
  445. function tderefnode.det_resulttype:tnode;
  446. begin
  447. result:=nil;
  448. resulttypepass(left);
  449. set_varstate(left,vs_used,true);
  450. if codegenerror then
  451. exit;
  452. { tp procvar support }
  453. maybe_call_procvar(left,true);
  454. if left.resulttype.def.deftype=pointerdef then
  455. resulttype:=tpointerdef(left.resulttype.def).pointertype
  456. else
  457. CGMessage(parser_e_invalid_qualifier);
  458. end;
  459. procedure Tderefnode.mark_write;
  460. begin
  461. include(flags,nf_write);
  462. end;
  463. function tderefnode.pass_1 : tnode;
  464. begin
  465. result:=nil;
  466. firstpass(left);
  467. if codegenerror then
  468. exit;
  469. registersint:=max(left.registersint,1);
  470. registersfpu:=left.registersfpu;
  471. {$ifdef SUPPORT_MMX}
  472. registersmmx:=left.registersmmx;
  473. {$endif SUPPORT_MMX}
  474. expectloc:=LOC_REFERENCE;
  475. end;
  476. {*****************************************************************************
  477. TSUBSCRIPTNODE
  478. *****************************************************************************}
  479. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  480. begin
  481. inherited create(subscriptn,l);
  482. { vs should be changed to tsym! }
  483. vs:=tfieldvarsym(varsym);
  484. end;
  485. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  486. begin
  487. inherited ppuload(t,ppufile);
  488. ppufile.getderef(vsderef);
  489. end;
  490. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  491. begin
  492. inherited ppuwrite(ppufile);
  493. ppufile.putderef(vsderef);
  494. end;
  495. procedure tsubscriptnode.buildderefimpl;
  496. begin
  497. inherited buildderefimpl;
  498. vsderef.build(vs);
  499. end;
  500. procedure tsubscriptnode.derefimpl;
  501. begin
  502. inherited derefimpl;
  503. vs:=tfieldvarsym(vsderef.resolve);
  504. end;
  505. function tsubscriptnode.getcopy : tnode;
  506. var
  507. p : tsubscriptnode;
  508. begin
  509. p:=tsubscriptnode(inherited getcopy);
  510. p.vs:=vs;
  511. getcopy:=p;
  512. end;
  513. function tsubscriptnode.det_resulttype:tnode;
  514. begin
  515. result:=nil;
  516. resulttypepass(left);
  517. { tp procvar support }
  518. maybe_call_procvar(left,true);
  519. resulttype:=vs.vartype;
  520. end;
  521. procedure Tsubscriptnode.mark_write;
  522. begin
  523. include(flags,nf_write);
  524. end;
  525. function tsubscriptnode.pass_1 : tnode;
  526. begin
  527. result:=nil;
  528. firstpass(left);
  529. if codegenerror then
  530. exit;
  531. registersint:=left.registersint;
  532. registersfpu:=left.registersfpu;
  533. {$ifdef SUPPORT_MMX}
  534. registersmmx:=left.registersmmx;
  535. {$endif SUPPORT_MMX}
  536. { classes must be dereferenced implicit }
  537. if is_class_or_interface(left.resulttype.def) then
  538. begin
  539. if registersint=0 then
  540. registersint:=1;
  541. expectloc:=LOC_REFERENCE;
  542. end
  543. else
  544. begin
  545. if (left.expectloc<>LOC_CREFERENCE) and
  546. (left.expectloc<>LOC_REFERENCE) then
  547. CGMessage(parser_e_illegal_expression);
  548. expectloc:=left.expectloc;
  549. end;
  550. end;
  551. function tsubscriptnode.docompare(p: tnode): boolean;
  552. begin
  553. docompare :=
  554. inherited docompare(p) and
  555. (vs = tsubscriptnode(p).vs);
  556. end;
  557. {*****************************************************************************
  558. TVECNODE
  559. *****************************************************************************}
  560. constructor tvecnode.create(l,r : tnode);
  561. begin
  562. inherited create(vecn,l,r);
  563. end;
  564. function tvecnode.det_resulttype:tnode;
  565. var
  566. htype : ttype;
  567. valid : boolean;
  568. begin
  569. result:=nil;
  570. resulttypepass(left);
  571. resulttypepass(right);
  572. { In p[1] p is always valid, it is not possible to
  573. declared a shortstring or normal array that has
  574. undefined number of elements. Dynamic array and
  575. ansi/widestring needs to be valid }
  576. valid:=is_dynamic_array(left.resulttype.def) or
  577. is_ansistring(left.resulttype.def) or
  578. is_widestring(left.resulttype.def);
  579. set_varstate(left,vs_used,valid);
  580. set_varstate(right,vs_used,true);
  581. if codegenerror then
  582. exit;
  583. { maybe type conversion for the index value, but
  584. do not convert enums,booleans,char }
  585. if (right.resulttype.def.deftype<>enumdef) and
  586. not(is_char(right.resulttype.def)) and
  587. not(is_boolean(right.resulttype.def)) then
  588. begin
  589. inserttypeconv(right,s32inttype);
  590. end;
  591. case left.resulttype.def.deftype of
  592. arraydef :
  593. begin
  594. { check type of the index value }
  595. if (compare_defs(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,right.nodetype)=te_incompatible) then
  596. IncompatibleTypes(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def);
  597. resulttype:=tarraydef(left.resulttype.def).elementtype;
  598. end;
  599. pointerdef :
  600. begin
  601. { are we accessing a pointer[], then convert the pointer to
  602. an array first, in FPC this is allowed for all pointers in
  603. delphi/tp7 it's only allowed for pchars }
  604. if (m_fpc in aktmodeswitches) or
  605. is_pchar(left.resulttype.def) or
  606. is_pwidechar(left.resulttype.def) then
  607. begin
  608. { convert pointer to array }
  609. htype.setdef(tarraydef.create_from_pointer(tpointerdef(left.resulttype.def).pointertype));
  610. inserttypeconv(left,htype);
  611. resulttype:=tarraydef(htype.def).elementtype;
  612. end
  613. else
  614. CGMessage(type_e_array_required);
  615. end;
  616. stringdef :
  617. begin
  618. { indexed access to 0 element is only allowed for shortstrings }
  619. if (right.nodetype=ordconstn) and
  620. (tordconstnode(right).value=0) and
  621. not(is_shortstring(left.resulttype.def)) then
  622. CGMessage(cg_e_can_access_element_zero);
  623. case tstringdef(left.resulttype.def).string_typ of
  624. st_widestring :
  625. resulttype:=cwidechartype;
  626. {$ifdef ansistring_bits}
  627. st_ansistring16,st_ansistring32,st_ansistring64 :
  628. {$else}
  629. st_ansistring :
  630. {$endif}
  631. resulttype:=cchartype;
  632. st_longstring :
  633. resulttype:=cchartype;
  634. st_shortstring :
  635. resulttype:=cchartype;
  636. end;
  637. end;
  638. variantdef :
  639. resulttype:=cvarianttype;
  640. else
  641. CGMessage(type_e_array_required);
  642. end;
  643. end;
  644. procedure Tvecnode.mark_write;
  645. begin
  646. include(flags,nf_write);
  647. end;
  648. function tvecnode.pass_1 : tnode;
  649. {$ifdef consteval}
  650. var
  651. tcsym : ttypedconstsym;
  652. {$endif}
  653. begin
  654. result:=nil;
  655. firstpass(left);
  656. firstpass(right);
  657. if codegenerror then
  658. exit;
  659. if (nf_callunique in flags) and
  660. (is_ansistring(left.resulttype.def) or
  661. is_widestring(left.resulttype.def)) then
  662. begin
  663. left := ctypeconvnode.create_internal(ccallnode.createintern('fpc_'+tstringdef(left.resulttype.def).stringtypname+'_unique',
  664. ccallparanode.create(
  665. ctypeconvnode.create_internal(left,voidpointertype),nil)),
  666. left.resulttype);
  667. firstpass(left);
  668. { double resulttype passes somwhere else may cause this to be }
  669. { reset though :/ }
  670. exclude(flags,nf_callunique);
  671. end;
  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. registersint:=left.registersint;
  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. registersint:=max(registersint,1);
  693. end
  694. else
  695. begin
  696. { this rules are suboptimal, but they should give }
  697. { good results }
  698. registersint:=max(left.registersint,right.registersint);
  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. registersint:=max(registersint,1);
  705. { need we an extra register when doing the restore ? }
  706. if (left.registersint<=right.registersint) 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. (registersint<3) then
  711. inc(registersint);
  712. { need we an extra register for the index ? }
  713. if (right.expectloc<>LOC_REGISTER)
  714. { only if the right node doesn't need a register }
  715. and (right.registersint<1) then
  716. inc(registersint);
  717. { not correct, but what works better ?
  718. if left.registersint>0 then
  719. registersint:=max(registersint,2)
  720. else
  721. min. one register
  722. registersint:=max(registersint,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.expectloc=LOC_CREFERENCE then
  730. expectloc:=LOC_CREFERENCE
  731. else
  732. expectloc:=LOC_REFERENCE;
  733. end;
  734. {*****************************************************************************
  735. TWITHNODE
  736. *****************************************************************************}
  737. constructor twithnode.create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
  738. begin
  739. inherited create(withn,l);
  740. withrefnode:=r;
  741. withsymtable:=symtable;
  742. tablecount:=count;
  743. set_file_line(l);
  744. end;
  745. destructor twithnode.destroy;
  746. var
  747. hsymt,
  748. symt : tsymtable;
  749. i : longint;
  750. begin
  751. symt:=withsymtable;
  752. for i:=1 to tablecount do
  753. begin
  754. if assigned(symt) then
  755. begin
  756. hsymt:=symt.next;
  757. symt.free;
  758. symt:=hsymt;
  759. end;
  760. end;
  761. inherited destroy;
  762. end;
  763. constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  764. begin
  765. inherited ppuload(t,ppufile);
  766. internalerror(200208192);
  767. end;
  768. procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
  769. begin
  770. inherited ppuwrite(ppufile);
  771. internalerror(200208193);
  772. end;
  773. function twithnode.getcopy : tnode;
  774. var
  775. p : twithnode;
  776. begin
  777. p:=twithnode(inherited getcopy);
  778. p.withsymtable:=withsymtable;
  779. p.tablecount:=tablecount;
  780. if assigned(p.withrefnode) then
  781. p.withrefnode:=withrefnode.getcopy
  782. else
  783. p.withrefnode:=nil;
  784. result:=p;
  785. end;
  786. function twithnode.det_resulttype:tnode;
  787. begin
  788. result:=nil;
  789. resulttype:=voidtype;
  790. resulttypepass(withrefnode);
  791. //unset_varstate(withrefnode);
  792. set_varstate(withrefnode,vs_used,true);
  793. if codegenerror then
  794. exit;
  795. if (withrefnode.nodetype=vecn) and
  796. (nf_memseg in withrefnode.flags) then
  797. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  798. if assigned(left) then
  799. resulttypepass(left);
  800. end;
  801. function twithnode.pass_1 : tnode;
  802. begin
  803. result:=nil;
  804. expectloc:=LOC_VOID;
  805. if assigned(left) then
  806. begin
  807. firstpass(left);
  808. registersint:=left.registersint;
  809. registersfpu:=left.registersfpu;
  810. {$ifdef SUPPORT_MMX}
  811. registersmmx:=left.registersmmx;
  812. {$endif SUPPORT_MMX}
  813. end;
  814. if assigned(withrefnode) then
  815. begin
  816. firstpass(withrefnode);
  817. if withrefnode.registersint > registersint then
  818. registersint:=withrefnode.registersint;
  819. if withrefnode.registersfpu > registersfpu then
  820. registersint:=withrefnode.registersfpu;
  821. {$ifdef SUPPORT_MMX}
  822. if withrefnode.registersmmx > registersmmx then
  823. registersmmx:=withrefnode.registersmmx;
  824. {$endif SUPPORT_MMX}
  825. end;
  826. end;
  827. function twithnode.docompare(p: tnode): boolean;
  828. begin
  829. docompare :=
  830. inherited docompare(p) and
  831. (withsymtable = twithnode(p).withsymtable) and
  832. (tablecount = twithnode(p).tablecount) and
  833. (withrefnode.isequal(twithnode(p).withrefnode));
  834. end;
  835. begin
  836. cloadvmtaddrnode := tloadvmtaddrnode;
  837. caddrnode := taddrnode;
  838. cderefnode := tderefnode;
  839. csubscriptnode := tsubscriptnode;
  840. cvecnode := tvecnode;
  841. cwithnode := twithnode;
  842. end.
  843. {
  844. $Log$
  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. }