2
0

nmem.pas 37 KB

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