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