nmem.pas 35 KB

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