nmem.pas 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  1. {
  2. $Id$
  3. Copyright (c) 2000 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 defines.inc}
  20. interface
  21. uses
  22. node,
  23. symtype,symdef,symsym,symtable,
  24. cpubase;
  25. type
  26. tloadvmtnode = class(tunarynode)
  27. constructor create(l : tnode);virtual;
  28. function pass_1 : tnode;override;
  29. function det_resulttype:tnode;override;
  30. end;
  31. tloadvmtnodeclass = class of tloadvmtnode;
  32. thnewnode = class(tnode)
  33. constructor create;virtual;
  34. function pass_1 : tnode;override;
  35. function det_resulttype:tnode;override;
  36. end;
  37. thnewnodeclass = class of thnewnode;
  38. tnewnode = class(tunarynode)
  39. constructor create(l : tnode);virtual;
  40. function pass_1 : tnode;override;
  41. function det_resulttype:tnode;override;
  42. end;
  43. tnewnodeclass = class of tnewnode;
  44. thdisposenode = class(tunarynode)
  45. constructor create(l : tnode);virtual;
  46. function pass_1 : tnode;override;
  47. function det_resulttype:tnode;override;
  48. end;
  49. thdisposenodeclass = class of thdisposenode;
  50. tsimplenewdisposenode = class(tunarynode)
  51. constructor create(n : tnodetype;l : tnode);
  52. function pass_1 : tnode;override;
  53. function det_resulttype:tnode;override;
  54. end;
  55. tsimplenewdisposenodeclass = class of tsimplenewdisposenode;
  56. taddrnode = class(tunarynode)
  57. getprocvardef : tprocvardef;
  58. constructor create(l : tnode);virtual;
  59. function pass_1 : tnode;override;
  60. function det_resulttype:tnode;override;
  61. end;
  62. taddrnodeclass = class of taddrnode;
  63. tdoubleaddrnode = class(tunarynode)
  64. constructor create(l : tnode);virtual;
  65. function pass_1 : tnode;override;
  66. function det_resulttype:tnode;override;
  67. end;
  68. tdoubleaddrnodeclass = class of tdoubleaddrnode;
  69. tderefnode = class(tunarynode)
  70. constructor create(l : tnode);virtual;
  71. function pass_1 : tnode;override;
  72. function det_resulttype:tnode;override;
  73. end;
  74. tderefnodeclass = class of tderefnode;
  75. tsubscriptnode = class(tunarynode)
  76. vs : tvarsym;
  77. constructor create(varsym : tsym;l : tnode);virtual;
  78. function getcopy : tnode;override;
  79. function pass_1 : tnode;override;
  80. function docompare(p: tnode): boolean; override;
  81. function det_resulttype:tnode;override;
  82. end;
  83. tsubscriptnodeclass = class of tsubscriptnode;
  84. tvecnode = class(tbinarynode)
  85. constructor create(l,r : tnode);virtual;
  86. function pass_1 : tnode;override;
  87. function det_resulttype:tnode;override;
  88. end;
  89. tvecnodeclass = class of tvecnode;
  90. tselfnode = class(tnode)
  91. classdef : tobjectdef;
  92. constructor create(_class : tobjectdef);virtual;
  93. function pass_1 : tnode;override;
  94. function det_resulttype:tnode;override;
  95. end;
  96. tselfnodeclass = class of tselfnode;
  97. twithnode = class(tbinarynode)
  98. withsymtable : twithsymtable;
  99. tablecount : longint;
  100. withreference : preference;
  101. constructor create(symtable : twithsymtable;l,r : tnode;count : longint);virtual;
  102. destructor destroy;override;
  103. function getcopy : tnode;override;
  104. function pass_1 : tnode;override;
  105. function docompare(p: tnode): boolean; override;
  106. function det_resulttype:tnode;override;
  107. end;
  108. twithnodeclass = class of twithnode;
  109. var
  110. cloadvmtnode : tloadvmtnodeclass;
  111. chnewnode : thnewnodeclass;
  112. cnewnode : tnewnodeclass;
  113. chdisposenode : thdisposenodeclass;
  114. csimplenewdisposenode : tsimplenewdisposenodeclass;
  115. caddrnode : taddrnodeclass;
  116. cdoubleaddrnode : tdoubleaddrnodeclass;
  117. cderefnode : tderefnodeclass;
  118. csubscriptnode : tsubscriptnodeclass;
  119. cvecnode : tvecnodeclass;
  120. cselfnode : tselfnodeclass;
  121. cwithnode : twithnodeclass;
  122. implementation
  123. uses
  124. globtype,systems,
  125. cutils,verbose,globals,
  126. symconst,symbase,types,
  127. htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase
  128. ;
  129. {*****************************************************************************
  130. TLOADVMTNODE
  131. *****************************************************************************}
  132. constructor tloadvmtnode.create(l : tnode);
  133. begin
  134. inherited create(loadvmtn,l);
  135. end;
  136. function tloadvmtnode.det_resulttype:tnode;
  137. begin
  138. result:=nil;
  139. resulttypepass(left);
  140. if codegenerror then
  141. exit;
  142. resulttype.setdef(tclassrefdef.create(left.resulttype));
  143. end;
  144. function tloadvmtnode.pass_1 : tnode;
  145. begin
  146. result:=nil;
  147. registers32:=1;
  148. location.loc:=LOC_REGISTER;
  149. end;
  150. {*****************************************************************************
  151. THNEWNODE
  152. *****************************************************************************}
  153. constructor thnewnode.create;
  154. begin
  155. inherited create(hnewn);
  156. end;
  157. function thnewnode.det_resulttype:tnode;
  158. begin
  159. result:=nil;
  160. resulttype:=voidtype;
  161. end;
  162. function thnewnode.pass_1 : tnode;
  163. begin
  164. result:=nil;
  165. end;
  166. {*****************************************************************************
  167. TNEWNODE
  168. *****************************************************************************}
  169. constructor tnewnode.create(l : tnode);
  170. begin
  171. inherited create(newn,l);
  172. end;
  173. function tnewnode.det_resulttype:tnode;
  174. begin
  175. result:=nil;
  176. if assigned(left) then
  177. resulttypepass(left);
  178. resulttype:=voidtype;
  179. end;
  180. function tnewnode.pass_1 : tnode;
  181. begin
  182. result:=nil;
  183. if assigned(left) then
  184. begin
  185. firstpass(left);
  186. if codegenerror then
  187. exit;
  188. registers32:=left.registers32;
  189. registersfpu:=left.registersfpu;
  190. {$ifdef SUPPORT_MMX}
  191. registersmmx:=left.registersmmx;
  192. {$endif SUPPORT_MMX}
  193. location.loc:=LOC_REGISTER
  194. end
  195. else
  196. location.loc:=LOC_REFERENCE;
  197. procinfo^.flags:=procinfo^.flags or pi_do_call;
  198. end;
  199. {*****************************************************************************
  200. THDISPOSENODE
  201. *****************************************************************************}
  202. constructor thdisposenode.create(l : tnode);
  203. begin
  204. inherited create(hdisposen,l);
  205. end;
  206. function thdisposenode.det_resulttype:tnode;
  207. begin
  208. result:=nil;
  209. resulttypepass(left);
  210. if codegenerror then
  211. exit;
  212. resulttype:=tpointerdef(left.resulttype.def).pointertype;
  213. end;
  214. function thdisposenode.pass_1 : tnode;
  215. begin
  216. result:=nil;
  217. firstpass(left);
  218. if codegenerror then
  219. exit;
  220. registers32:=left.registers32;
  221. registersfpu:=left.registersfpu;
  222. {$ifdef SUPPORT_MMX}
  223. registersmmx:=left.registersmmx;
  224. {$endif SUPPORT_MMX}
  225. if registers32<1 then
  226. registers32:=1;
  227. {
  228. if left.location.loc<>LOC_REFERENCE then
  229. CGMessage(cg_e_illegal_expression);
  230. }
  231. if left.location.loc=LOC_CREGISTER then
  232. inc(registers32);
  233. location.loc:=LOC_REFERENCE;
  234. end;
  235. {*****************************************************************************
  236. TSIMPLENEWDISPOSENODE
  237. *****************************************************************************}
  238. constructor tsimplenewdisposenode.create(n : tnodetype;l : tnode);
  239. begin
  240. inherited create(n,l);
  241. end;
  242. function tsimplenewdisposenode.det_resulttype:tnode;
  243. begin
  244. result:=nil;
  245. resulttypepass(left);
  246. if codegenerror then
  247. exit;
  248. if (left.resulttype.def.deftype<>pointerdef) then
  249. CGMessage1(type_e_pointer_type_expected,left.resulttype.def.typename);
  250. resulttype:=voidtype;
  251. end;
  252. function tsimplenewdisposenode.pass_1 : tnode;
  253. begin
  254. result:=nil;
  255. { this cannot be in a register !! }
  256. make_not_regable(left);
  257. firstpass(left);
  258. if codegenerror then
  259. exit;
  260. if (left.location.loc<>LOC_REFERENCE) {and
  261. (left.location.loc<>LOC_CREGISTER)} then
  262. CGMessage(cg_e_illegal_expression);
  263. registers32:=left.registers32;
  264. registersfpu:=left.registersfpu;
  265. {$ifdef SUPPORT_MMX}
  266. registersmmx:=left.registersmmx;
  267. {$endif SUPPORT_MMX}
  268. procinfo^.flags:=procinfo^.flags or pi_do_call;
  269. end;
  270. {*****************************************************************************
  271. TADDRNODE
  272. *****************************************************************************}
  273. constructor taddrnode.create(l : tnode);
  274. begin
  275. inherited create(addrn,l);
  276. end;
  277. function taddrnode.det_resulttype:tnode;
  278. var
  279. hp : tnode;
  280. hp2 : TParaItem;
  281. hp3 : tabstractprocdef;
  282. begin
  283. result:=nil;
  284. resulttypepass(left);
  285. if codegenerror then
  286. exit;
  287. { don't allow constants }
  288. if is_constnode(left) then
  289. begin
  290. aktfilepos:=left.fileinfo;
  291. CGMessage(type_e_no_addr_of_constant);
  292. exit;
  293. end;
  294. { tp @procvar support (type of @procvar is a void pointer)
  295. Note: we need to leave the addrn in the tree,
  296. else we can't see the difference between @procvar and procvar.
  297. we set the procvarload flag so a secondpass does nothing for
  298. this node (PFV) }
  299. if (m_tp_procvar in aktmodeswitches) then
  300. begin
  301. case left.nodetype of
  302. calln :
  303. begin
  304. { is it a procvar? }
  305. hp:=tcallnode(left).right;
  306. if assigned(hp) then
  307. begin
  308. { remove calln node }
  309. tcallnode(left).right:=nil;
  310. left.free;
  311. left:=hp;
  312. include(flags,nf_procvarload);
  313. end;
  314. end;
  315. loadn,
  316. subscriptn,
  317. typeconvn,
  318. vecn,
  319. derefn :
  320. begin
  321. if left.resulttype.def.deftype=procvardef then
  322. include(flags,nf_procvarload);
  323. end;
  324. end;
  325. if nf_procvarload in flags then
  326. begin
  327. resulttype:=voidpointertype;
  328. exit;
  329. end;
  330. end;
  331. { proc 2 procvar ? }
  332. if left.nodetype=calln then
  333. internalerror(200103253)
  334. else
  335. if (left.nodetype=loadn) and (tloadnode(left).symtableentry.typ=procsym) then
  336. begin
  337. { the address is already available when loading a procedure of object }
  338. if assigned(tloadnode(left).left) then
  339. include(flags,nf_procvarload);
  340. { result is a procedure variable }
  341. { No, to be TP compatible, you must return a voidpointer to
  342. the procedure that is stored in the procvar.}
  343. if not(m_tp_procvar in aktmodeswitches) then
  344. begin
  345. if assigned(getprocvardef) then
  346. hp3:=getprocvardef
  347. else
  348. hp3:=tabstractprocdef(tprocsym(tloadnode(left).symtableentry).defs^.def);
  349. { create procvardef }
  350. resulttype.setdef(tprocvardef.create);
  351. tprocvardef(resulttype.def).proctypeoption:=hp3.proctypeoption;
  352. tprocvardef(resulttype.def).proccalloption:=hp3.proccalloption;
  353. tprocvardef(resulttype.def).procoptions:=hp3.procoptions;
  354. tprocvardef(resulttype.def).rettype:=hp3.rettype;
  355. tprocvardef(resulttype.def).symtablelevel:=hp3.symtablelevel;
  356. { method ? then set the methodpointer flag }
  357. if (hp3.owner.symtabletype=objectsymtable) then
  358. include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
  359. { we need to process the parameters reverse so they are inserted
  360. in the correct right2left order (PFV) }
  361. hp2:=TParaItem(hp3.Para.last);
  362. while assigned(hp2) do
  363. begin
  364. tprocvardef(resulttype.def).concatpara(hp2.paratype,hp2.paratyp,hp2.defaultvalue);
  365. hp2:=TParaItem(hp2.previous);
  366. end;
  367. end
  368. else
  369. resulttype:=voidpointertype;
  370. end
  371. else
  372. begin
  373. { what are we getting the address from an absolute sym? }
  374. hp:=left;
  375. while assigned(hp) and (hp.nodetype in [vecn,derefn,subscriptn]) do
  376. hp:=tunarynode(hp).left;
  377. if assigned(hp) and (hp.nodetype=loadn) and
  378. ((tloadnode(hp).symtableentry.typ=absolutesym) and
  379. tabsolutesym(tloadnode(hp).symtableentry).absseg) then
  380. begin
  381. if not(cs_typed_addresses in aktlocalswitches) then
  382. resulttype:=voidfarpointertype
  383. else
  384. resulttype.setdef(tpointerdef.createfar(left.resulttype));
  385. end
  386. else
  387. begin
  388. if not(cs_typed_addresses in aktlocalswitches) then
  389. resulttype:=voidpointertype
  390. else
  391. resulttype.setdef(tpointerdef.create(left.resulttype));
  392. end;
  393. end;
  394. { this is like the function addr }
  395. inc(parsing_para_level);
  396. set_varstate(left,false);
  397. dec(parsing_para_level);
  398. end;
  399. function taddrnode.pass_1 : tnode;
  400. begin
  401. result:=nil;
  402. firstpass(left);
  403. if codegenerror then
  404. exit;
  405. make_not_regable(left);
  406. if nf_procvarload in flags then
  407. begin
  408. registers32:=left.registers32;
  409. registersfpu:=left.registersfpu;
  410. {$ifdef SUPPORT_MMX}
  411. registersmmx:=left.registersmmx;
  412. {$endif SUPPORT_MMX}
  413. if registers32<1 then
  414. registers32:=1;
  415. location.loc:=left.location.loc;
  416. exit;
  417. end;
  418. { we should allow loc_mem for @string }
  419. if not(left.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  420. begin
  421. aktfilepos:=left.fileinfo;
  422. CGMessage(cg_e_illegal_expression);
  423. end;
  424. registers32:=left.registers32;
  425. registersfpu:=left.registersfpu;
  426. {$ifdef SUPPORT_MMX}
  427. registersmmx:=left.registersmmx;
  428. {$endif SUPPORT_MMX}
  429. if registers32<1 then
  430. registers32:=1;
  431. { is this right for object of methods ?? }
  432. location.loc:=LOC_REGISTER;
  433. end;
  434. {*****************************************************************************
  435. TDOUBLEADDRNODE
  436. *****************************************************************************}
  437. constructor tdoubleaddrnode.create(l : tnode);
  438. begin
  439. inherited create(doubleaddrn,l);
  440. end;
  441. function tdoubleaddrnode.det_resulttype:tnode;
  442. begin
  443. result:=nil;
  444. resulttypepass(left);
  445. if codegenerror then
  446. exit;
  447. inc(parsing_para_level);
  448. set_varstate(left,false);
  449. dec(parsing_para_level);
  450. if (left.resulttype.def.deftype)<>procvardef then
  451. CGMessage(cg_e_illegal_expression);
  452. resulttype:=voidpointertype;
  453. end;
  454. function tdoubleaddrnode.pass_1 : tnode;
  455. begin
  456. result:=nil;
  457. make_not_regable(left);
  458. firstpass(left);
  459. if codegenerror then
  460. exit;
  461. if (left.location.loc<>LOC_REFERENCE) then
  462. CGMessage(cg_e_illegal_expression);
  463. registers32:=left.registers32;
  464. registersfpu:=left.registersfpu;
  465. {$ifdef SUPPORT_MMX}
  466. registersmmx:=left.registersmmx;
  467. {$endif SUPPORT_MMX}
  468. if registers32<1 then
  469. registers32:=1;
  470. location.loc:=LOC_REGISTER;
  471. end;
  472. {*****************************************************************************
  473. TDEREFNODE
  474. *****************************************************************************}
  475. constructor tderefnode.create(l : tnode);
  476. begin
  477. inherited create(derefn,l);
  478. end;
  479. function tderefnode.det_resulttype:tnode;
  480. begin
  481. result:=nil;
  482. resulttypepass(left);
  483. set_varstate(left,true);
  484. if codegenerror then
  485. exit;
  486. if left.resulttype.def.deftype=pointerdef then
  487. resulttype:=tpointerdef(left.resulttype.def).pointertype
  488. else
  489. CGMessage(cg_e_invalid_qualifier);
  490. end;
  491. function tderefnode.pass_1 : tnode;
  492. begin
  493. result:=nil;
  494. firstpass(left);
  495. if codegenerror then
  496. exit;
  497. registers32:=max(left.registers32,1);
  498. registersfpu:=left.registersfpu;
  499. {$ifdef SUPPORT_MMX}
  500. registersmmx:=left.registersmmx;
  501. {$endif SUPPORT_MMX}
  502. location.loc:=LOC_REFERENCE;
  503. end;
  504. {*****************************************************************************
  505. TSUBSCRIPTNODE
  506. *****************************************************************************}
  507. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  508. begin
  509. inherited create(subscriptn,l);
  510. { vs should be changed to tsym! }
  511. vs:=tvarsym(varsym);
  512. end;
  513. function tsubscriptnode.getcopy : tnode;
  514. var
  515. p : tsubscriptnode;
  516. begin
  517. p:=tsubscriptnode(inherited getcopy);
  518. p.vs:=vs;
  519. getcopy:=p;
  520. end;
  521. function tsubscriptnode.det_resulttype:tnode;
  522. begin
  523. result:=nil;
  524. resulttypepass(left);
  525. resulttype:=vs.vartype;
  526. end;
  527. function tsubscriptnode.pass_1 : tnode;
  528. begin
  529. result:=nil;
  530. firstpass(left);
  531. if codegenerror then
  532. exit;
  533. registers32:=left.registers32;
  534. registersfpu:=left.registersfpu;
  535. {$ifdef SUPPORT_MMX}
  536. registersmmx:=left.registersmmx;
  537. {$endif SUPPORT_MMX}
  538. { classes must be dereferenced implicit }
  539. if is_class_or_interface(left.resulttype.def) then
  540. begin
  541. if registers32=0 then
  542. registers32:=1;
  543. location.loc:=LOC_REFERENCE;
  544. end
  545. else
  546. begin
  547. if (left.location.loc<>LOC_MEM) and
  548. (left.location.loc<>LOC_REFERENCE) then
  549. CGMessage(cg_e_illegal_expression);
  550. set_location(location,left.location);
  551. end;
  552. end;
  553. function tsubscriptnode.docompare(p: tnode): boolean;
  554. begin
  555. docompare :=
  556. inherited docompare(p) and
  557. (vs = tsubscriptnode(p).vs);
  558. end;
  559. {*****************************************************************************
  560. TVECNODE
  561. *****************************************************************************}
  562. constructor tvecnode.create(l,r : tnode);
  563. begin
  564. inherited create(vecn,l,r);
  565. end;
  566. function tvecnode.det_resulttype:tnode;
  567. var
  568. htype : ttype;
  569. ct : tconverttype;
  570. begin
  571. result:=nil;
  572. resulttypepass(left);
  573. resulttypepass(right);
  574. if codegenerror then
  575. exit;
  576. { range check only for arrays }
  577. if (left.resulttype.def.deftype=arraydef) then
  578. begin
  579. if (isconvertable(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,
  580. ct,ordconstn,false)=0) and
  581. not(is_equal(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def)) then
  582. CGMessage(type_e_mismatch);
  583. end;
  584. { Never convert a boolean or a char !}
  585. { maybe type conversion }
  586. if (right.resulttype.def.deftype<>enumdef) and
  587. not(is_char(right.resulttype.def)) and
  588. not(is_boolean(right.resulttype.def)) then
  589. begin
  590. inserttypeconv(right,s32bittype);
  591. end;
  592. { are we accessing a pointer[], then convert the pointer to
  593. an array first, in FPC this is allowed for all pointers in
  594. delphi/tp7 it's only allowed for pchars }
  595. if (left.resulttype.def.deftype=pointerdef) and
  596. ((m_fpc in aktmodeswitches) or
  597. is_pchar(left.resulttype.def) or
  598. is_pwidechar(left.resulttype.def)) then
  599. begin
  600. { convert pointer to array }
  601. htype.setdef(tarraydef.create(0,$7fffffff,s32bittype));
  602. tarraydef(htype.def).elementtype:=tpointerdef(left.resulttype.def).pointertype;
  603. inserttypeconv(left,htype);
  604. resulttype:=tarraydef(htype.def).elementtype;
  605. end;
  606. { determine return type }
  607. if not assigned(resulttype.def) then
  608. if left.resulttype.def.deftype=arraydef then
  609. resulttype:=tarraydef(left.resulttype.def).elementtype
  610. else if left.resulttype.def.deftype=stringdef then
  611. begin
  612. { indexed access to strings }
  613. case tstringdef(left.resulttype.def).string_typ of
  614. st_widestring :
  615. resulttype:=cwidechartype;
  616. st_ansistring :
  617. resulttype:=cchartype;
  618. st_longstring :
  619. resulttype:=cchartype;
  620. st_shortstring :
  621. resulttype:=cchartype;
  622. end;
  623. end
  624. else
  625. CGMessage(type_e_array_required);
  626. end;
  627. function tvecnode.pass_1 : tnode;
  628. {$ifdef consteval}
  629. var
  630. tcsym : ttypedconstsym;
  631. {$endif}
  632. begin
  633. result:=nil;
  634. firstpass(left);
  635. firstpass(right);
  636. if codegenerror then
  637. exit;
  638. { the register calculation is easy if a const index is used }
  639. if right.nodetype=ordconstn then
  640. begin
  641. {$ifdef consteval}
  642. { constant evaluation }
  643. if (left.nodetype=loadn) and
  644. (left.symtableentry.typ=typedconstsym) then
  645. begin
  646. tcsym:=ttypedconstsym(left.symtableentry);
  647. if tcsym.defintion^.typ=stringdef then
  648. begin
  649. end;
  650. end;
  651. {$endif}
  652. registers32:=left.registers32;
  653. { for ansi/wide strings, we need at least one register }
  654. if is_ansistring(left.resulttype.def) or
  655. is_widestring(left.resulttype.def) or
  656. { ... as well as for dynamic arrays }
  657. is_dynamic_array(left.resulttype.def) then
  658. registers32:=max(registers32,1);
  659. end
  660. else
  661. begin
  662. { this rules are suboptimal, but they should give }
  663. { good results }
  664. registers32:=max(left.registers32,right.registers32);
  665. { for ansi/wide strings, we need at least one register }
  666. if is_ansistring(left.resulttype.def) or
  667. is_widestring(left.resulttype.def) or
  668. { ... as well as for dynamic arrays }
  669. is_dynamic_array(left.resulttype.def) then
  670. registers32:=max(registers32,1);
  671. { need we an extra register when doing the restore ? }
  672. if (left.registers32<=right.registers32) and
  673. { only if the node needs less than 3 registers }
  674. { two for the right node and one for the }
  675. { left address }
  676. (registers32<3) then
  677. inc(registers32);
  678. { need we an extra register for the index ? }
  679. if (right.location.loc<>LOC_REGISTER)
  680. { only if the right node doesn't need a register }
  681. and (right.registers32<1) then
  682. inc(registers32);
  683. { not correct, but what works better ?
  684. if left.registers32>0 then
  685. registers32:=max(registers32,2)
  686. else
  687. min. one register
  688. registers32:=max(registers32,1);
  689. }
  690. end;
  691. registersfpu:=max(left.registersfpu,right.registersfpu);
  692. {$ifdef SUPPORT_MMX}
  693. registersmmx:=max(left.registersmmx,right.registersmmx);
  694. {$endif SUPPORT_MMX}
  695. if left.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
  696. location.loc:=LOC_REFERENCE
  697. else
  698. location.loc:=LOC_MEM;
  699. end;
  700. {*****************************************************************************
  701. TSELFNODE
  702. *****************************************************************************}
  703. constructor tselfnode.create(_class : tobjectdef);
  704. begin
  705. inherited create(selfn);
  706. classdef:=_class;
  707. end;
  708. function tselfnode.det_resulttype:tnode;
  709. begin
  710. result:=nil;
  711. resulttype.setdef(classdef);
  712. end;
  713. function tselfnode.pass_1 : tnode;
  714. begin
  715. result:=nil;
  716. if (resulttype.def.deftype=classrefdef) or
  717. is_class(resulttype.def) then
  718. location.loc:=LOC_CREGISTER
  719. else
  720. location.loc:=LOC_REFERENCE;
  721. end;
  722. {*****************************************************************************
  723. TWITHNODE
  724. *****************************************************************************}
  725. constructor twithnode.create(symtable : twithsymtable;l,r : tnode;count : longint);
  726. begin
  727. inherited create(withn,l,r);
  728. withsymtable:=symtable;
  729. tablecount:=count;
  730. withreference:=nil;
  731. set_file_line(l);
  732. end;
  733. destructor twithnode.destroy;
  734. var
  735. symt : tsymtable;
  736. i : longint;
  737. begin
  738. symt:=withsymtable;
  739. for i:=1 to tablecount do
  740. begin
  741. if assigned(symt) then
  742. begin
  743. withsymtable:=twithsymtable(symt.next);
  744. symt.free;
  745. end;
  746. symt:=withsymtable;
  747. end;
  748. inherited destroy;
  749. end;
  750. function twithnode.getcopy : tnode;
  751. var
  752. p : twithnode;
  753. begin
  754. p:=twithnode(inherited getcopy);
  755. p.withsymtable:=withsymtable;
  756. p.tablecount:=tablecount;
  757. p.withreference:=withreference;
  758. result:=p;
  759. end;
  760. function twithnode.det_resulttype:tnode;
  761. var
  762. symtable : twithsymtable;
  763. i : longint;
  764. begin
  765. result:=nil;
  766. resulttype:=voidtype;
  767. if assigned(left) and assigned(right) then
  768. begin
  769. resulttypepass(left);
  770. unset_varstate(left);
  771. set_varstate(left,true);
  772. if codegenerror then
  773. exit;
  774. symtable:=withsymtable;
  775. for i:=1 to tablecount do
  776. begin
  777. if (left.nodetype=loadn) and
  778. (tloadnode(left).symtable=aktprocdef.localst) then
  779. symtable.direct_with:=true;
  780. symtable.withnode:=self;
  781. symtable:=twithsymtable(symtable.next);
  782. end;
  783. resulttypepass(right);
  784. if codegenerror then
  785. exit;
  786. end;
  787. resulttype:=voidtype;
  788. end;
  789. function twithnode.pass_1 : tnode;
  790. begin
  791. result:=nil;
  792. if assigned(left) and assigned(right) then
  793. begin
  794. firstpass(left);
  795. firstpass(right);
  796. if codegenerror then
  797. exit;
  798. left_right_max;
  799. end
  800. else
  801. begin
  802. { optimization }
  803. result:=nil;
  804. end;
  805. end;
  806. function twithnode.docompare(p: tnode): boolean;
  807. begin
  808. docompare :=
  809. inherited docompare(p) and
  810. (withsymtable = twithnode(p).withsymtable) and
  811. (tablecount = twithnode(p).tablecount);
  812. end;
  813. begin
  814. cloadvmtnode := tloadvmtnode;
  815. chnewnode := thnewnode;
  816. cnewnode := tnewnode;
  817. chdisposenode := thdisposenode;
  818. csimplenewdisposenode := tsimplenewdisposenode;
  819. caddrnode := taddrnode;
  820. cdoubleaddrnode := tdoubleaddrnode;
  821. cderefnode := tderefnode;
  822. csubscriptnode := tsubscriptnode;
  823. cvecnode := tvecnode;
  824. cselfnode := tselfnode;
  825. cwithnode := twithnode;
  826. end.
  827. {
  828. $Log$
  829. Revision 1.23 2001-11-02 22:58:02 peter
  830. * procsym definition rewrite
  831. Revision 1.22 2001/10/28 17:22:25 peter
  832. * allow assignment of overloaded procedures to procvars when we know
  833. which procedure to take
  834. Revision 1.20 2001/09/02 21:12:07 peter
  835. * move class of definitions into type section for delphi
  836. Revision 1.19 2001/08/26 13:36:42 florian
  837. * some cg reorganisation
  838. * some PPC updates
  839. Revision 1.18 2001/04/13 22:15:21 peter
  840. * removed wrongly placed set_varstate in subscriptnode
  841. Revision 1.17 2001/04/13 01:22:10 peter
  842. * symtable change to classes
  843. * range check generation and errors fixed, make cycle DEBUG=1 works
  844. * memory leaks fixed
  845. Revision 1.16 2001/04/02 21:20:31 peter
  846. * resulttype rewrite
  847. Revision 1.15 2001/03/23 00:16:07 florian
  848. + some stuff to compile FreeCLX added
  849. Revision 1.14 2000/12/31 11:14:11 jonas
  850. + implemented/fixed docompare() mathods for all nodes (not tested)
  851. + nopt.pas, nadd.pas, i386/n386opt.pas: optimized nodes for adding strings
  852. and constant strings/chars together
  853. * n386add.pas: don't copy temp strings (of size 256) to another temp string
  854. when adding
  855. Revision 1.13 2000/12/25 00:07:26 peter
  856. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  857. tlinkedlist objects)
  858. Revision 1.12 2000/12/05 15:19:50 jonas
  859. * fixed webbug 1268 ("merged")
  860. Revision 1.11 2000/11/29 00:30:34 florian
  861. * unused units removed from uses clause
  862. * some changes for widestrings
  863. Revision 1.10 2000/11/04 14:25:20 florian
  864. + merged Attila's changes for interfaces, not tested yet
  865. Revision 1.9 2000/10/31 22:02:49 peter
  866. * symtable splitted, no real code changes
  867. Revision 1.8 2000/10/21 18:16:11 florian
  868. * a lot of changes:
  869. - basic dyn. array support
  870. - basic C++ support
  871. - some work for interfaces done
  872. ....
  873. Revision 1.7 2000/10/14 21:52:55 peter
  874. * fixed memory leaks
  875. Revision 1.6 2000/10/14 10:14:51 peter
  876. * moehrendorf oct 2000 rewrite
  877. Revision 1.5 2000/10/01 19:48:24 peter
  878. * lot of compile updates for cg11
  879. Revision 1.4 2000/09/28 19:49:52 florian
  880. *** empty log message ***
  881. Revision 1.3 2000/09/25 15:37:14 florian
  882. * more fixes
  883. Revision 1.2 2000/09/25 15:05:25 florian
  884. * some updates
  885. Revision 1.1 2000/09/25 09:58:22 florian
  886. * first revision for testing purpose
  887. }