nmem.pas 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097
  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. end;
  70. tderefnodeclass = class of tderefnode;
  71. tsubscriptnode = class(tunarynode)
  72. vs : tvarsym;
  73. constructor create(varsym : tsym;l : tnode);virtual;
  74. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  75. procedure ppuwrite(ppufile:tcompilerppufile);override;
  76. procedure derefimpl;override;
  77. function getcopy : tnode;override;
  78. function pass_1 : tnode;override;
  79. function docompare(p: tnode): boolean; override;
  80. function det_resulttype:tnode;override;
  81. end;
  82. tsubscriptnodeclass = class of tsubscriptnode;
  83. tvecnode = class(tbinarynode)
  84. constructor create(l,r : tnode);virtual;
  85. function pass_1 : tnode;override;
  86. function det_resulttype:tnode;override;
  87. end;
  88. tvecnodeclass = class of tvecnode;
  89. tselfnode = class(tnode)
  90. classdef : tdef; { objectdef or classrefdef }
  91. constructor create(_class : tdef);virtual;
  92. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  93. procedure ppuwrite(ppufile:tcompilerppufile);override;
  94. procedure derefimpl;override;
  95. function pass_1 : tnode;override;
  96. function det_resulttype:tnode;override;
  97. end;
  98. tselfnodeclass = class of tselfnode;
  99. twithnode = class(tbinarynode)
  100. withsymtable : twithsymtable;
  101. tablecount : longint;
  102. withreference : treference;
  103. constructor create(symtable : twithsymtable;l,r : tnode;count : longint);virtual;
  104. destructor destroy;override;
  105. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  106. procedure ppuwrite(ppufile:tcompilerppufile);override;
  107. function getcopy : tnode;override;
  108. function pass_1 : tnode;override;
  109. function docompare(p: tnode): boolean; override;
  110. function det_resulttype:tnode;override;
  111. end;
  112. twithnodeclass = class of twithnode;
  113. var
  114. cloadvmtnode : tloadvmtnodeclass;
  115. chnewnode : thnewnodeclass;
  116. chdisposenode : thdisposenodeclass;
  117. caddrnode : taddrnodeclass;
  118. cdoubleaddrnode : tdoubleaddrnodeclass;
  119. cderefnode : tderefnodeclass;
  120. csubscriptnode : tsubscriptnodeclass;
  121. cvecnode : tvecnodeclass;
  122. cselfnode : tselfnodeclass;
  123. cwithnode : twithnodeclass;
  124. implementation
  125. uses
  126. globtype,systems,
  127. cutils,verbose,globals,
  128. symconst,symbase,defbase,
  129. nbas,
  130. htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase
  131. ;
  132. {*****************************************************************************
  133. TLOADVMTNODE
  134. *****************************************************************************}
  135. constructor tloadvmtnode.create(l : tnode);
  136. begin
  137. inherited create(loadvmtn,l);
  138. end;
  139. function tloadvmtnode.det_resulttype:tnode;
  140. begin
  141. result:=nil;
  142. resulttypepass(left);
  143. if codegenerror then
  144. exit;
  145. resulttype.setdef(tclassrefdef.create(left.resulttype));
  146. end;
  147. function tloadvmtnode.pass_1 : tnode;
  148. begin
  149. result:=nil;
  150. registers32:=1;
  151. location.loc:=LOC_REGISTER;
  152. end;
  153. {*****************************************************************************
  154. THNEWNODE
  155. *****************************************************************************}
  156. constructor thnewnode.create(t:ttype);
  157. begin
  158. inherited create(hnewn);
  159. objtype:=t;
  160. end;
  161. constructor thnewnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  162. begin
  163. inherited ppuload(t,ppufile);
  164. ppufile.gettype(objtype);
  165. end;
  166. procedure thnewnode.ppuwrite(ppufile:tcompilerppufile);
  167. begin
  168. inherited ppuwrite(ppufile);
  169. ppufile.puttype(objtype);
  170. end;
  171. procedure thnewnode.derefimpl;
  172. begin
  173. inherited derefimpl;
  174. objtype.resolve;
  175. end;
  176. function thnewnode.det_resulttype:tnode;
  177. begin
  178. result:=nil;
  179. if objtype.def.deftype<>objectdef then
  180. Message(parser_e_pointer_to_class_expected);
  181. resulttype:=objtype;
  182. end;
  183. function thnewnode.pass_1 : tnode;
  184. begin
  185. result:=nil;
  186. end;
  187. {*****************************************************************************
  188. THDISPOSENODE
  189. *****************************************************************************}
  190. constructor thdisposenode.create(l : tnode);
  191. begin
  192. inherited create(hdisposen,l);
  193. end;
  194. function thdisposenode.det_resulttype:tnode;
  195. begin
  196. result:=nil;
  197. resulttypepass(left);
  198. if codegenerror then
  199. exit;
  200. if (left.resulttype.def.deftype<>pointerdef) then
  201. CGMessage1(type_e_pointer_type_expected,left.resulttype.def.typename);
  202. resulttype:=tpointerdef(left.resulttype.def).pointertype;
  203. end;
  204. function thdisposenode.pass_1 : tnode;
  205. begin
  206. result:=nil;
  207. firstpass(left);
  208. if codegenerror then
  209. exit;
  210. registers32:=left.registers32;
  211. registersfpu:=left.registersfpu;
  212. {$ifdef SUPPORT_MMX}
  213. registersmmx:=left.registersmmx;
  214. {$endif SUPPORT_MMX}
  215. if registers32<1 then
  216. registers32:=1;
  217. {
  218. if left.location.loc<>LOC_REFERENCE then
  219. CGMessage(cg_e_illegal_expression);
  220. }
  221. if left.location.loc=LOC_CREGISTER then
  222. inc(registers32);
  223. location.loc:=LOC_REFERENCE;
  224. end;
  225. {*****************************************************************************
  226. TADDRNODE
  227. *****************************************************************************}
  228. constructor taddrnode.create(l : tnode);
  229. begin
  230. inherited create(addrn,l);
  231. getprocvardef:=nil;
  232. end;
  233. constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  234. begin
  235. inherited ppuload(t,ppufile);
  236. getprocvardef:=tprocvardef(ppufile.getderef);
  237. end;
  238. procedure taddrnode.ppuwrite(ppufile:tcompilerppufile);
  239. begin
  240. inherited ppuwrite(ppufile);
  241. ppufile.putderef(getprocvardef);
  242. end;
  243. procedure taddrnode.derefimpl;
  244. begin
  245. inherited derefimpl;
  246. resolvedef(pointer(getprocvardef));
  247. end;
  248. function taddrnode.getcopy : tnode;
  249. var
  250. p : taddrnode;
  251. begin
  252. p:=taddrnode(inherited getcopy);
  253. p.getprocvardef:=getprocvardef;
  254. getcopy:=p;
  255. end;
  256. function taddrnode.det_resulttype:tnode;
  257. var
  258. hp : tnode;
  259. hp2 : TParaItem;
  260. hp3 : tabstractprocdef;
  261. begin
  262. result:=nil;
  263. resulttypepass(left);
  264. if codegenerror then
  265. exit;
  266. { don't allow constants }
  267. if is_constnode(left) then
  268. begin
  269. aktfilepos:=left.fileinfo;
  270. CGMessage(type_e_no_addr_of_constant);
  271. exit;
  272. end;
  273. { tp @procvar support (type of @procvar is a void pointer)
  274. Note: we need to leave the addrn in the tree,
  275. else we can't see the difference between @procvar and procvar.
  276. we set the procvarload flag so a secondpass does nothing for
  277. this node (PFV) }
  278. if (m_tp_procvar in aktmodeswitches) then
  279. begin
  280. case left.nodetype of
  281. calln :
  282. begin
  283. { a load of a procvar can't have parameters }
  284. if assigned(tcallnode(left).left) then
  285. CGMessage(cg_e_illegal_expression);
  286. { is it a procvar? }
  287. hp:=tcallnode(left).right;
  288. if assigned(hp) then
  289. begin
  290. { remove calln node }
  291. tcallnode(left).right:=nil;
  292. left.free;
  293. left:=hp;
  294. include(flags,nf_procvarload);
  295. end;
  296. end;
  297. loadn,
  298. subscriptn,
  299. typeconvn,
  300. vecn,
  301. derefn :
  302. begin
  303. if left.resulttype.def.deftype=procvardef then
  304. include(flags,nf_procvarload);
  305. end;
  306. end;
  307. if nf_procvarload in flags then
  308. begin
  309. resulttype:=voidpointertype;
  310. exit;
  311. end;
  312. end;
  313. { proc 2 procvar ? }
  314. if left.nodetype=calln then
  315. { if it were a valid construct, the addr node would already have }
  316. { been removed in the parser. This happens for (in FPC mode) }
  317. { procvar1 := @procvar2(parameters); }
  318. CGMessage(cg_e_illegal_expression)
  319. else
  320. if (left.nodetype=loadn) and (tloadnode(left).symtableentry.typ=procsym) then
  321. begin
  322. { the address is already available when loading a procedure of object }
  323. if assigned(tloadnode(left).left) then
  324. include(flags,nf_procvarload);
  325. { result is a procedure variable }
  326. { No, to be TP compatible, you must return a voidpointer to
  327. the procedure that is stored in the procvar.}
  328. if not(m_tp_procvar in aktmodeswitches) then
  329. begin
  330. if assigned(getprocvardef) then
  331. hp3:=getprocvardef
  332. else
  333. hp3:=tabstractprocdef(tprocsym(tloadnode(left).symtableentry).first_procdef);
  334. { create procvardef }
  335. resulttype.setdef(tprocvardef.create);
  336. tprocvardef(resulttype.def).proctypeoption:=hp3.proctypeoption;
  337. tprocvardef(resulttype.def).proccalloption:=hp3.proccalloption;
  338. tprocvardef(resulttype.def).procoptions:=hp3.procoptions;
  339. tprocvardef(resulttype.def).rettype:=hp3.rettype;
  340. tprocvardef(resulttype.def).symtablelevel:=hp3.symtablelevel;
  341. { method ? then set the methodpointer flag }
  342. if (hp3.owner.symtabletype=objectsymtable) then
  343. include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
  344. { we need to process the parameters reverse so they are inserted
  345. in the correct right2left order (PFV) }
  346. hp2:=TParaItem(hp3.Para.last);
  347. while assigned(hp2) do
  348. begin
  349. tprocvardef(resulttype.def).concatpara(hp2.paratype,hp2.parasym,hp2.paratyp,hp2.defaultvalue);
  350. hp2:=TParaItem(hp2.previous);
  351. end;
  352. end
  353. else
  354. resulttype:=voidpointertype;
  355. end
  356. else
  357. begin
  358. { what are we getting the address from an absolute sym? }
  359. hp:=left;
  360. while assigned(hp) and (hp.nodetype in [vecn,derefn,subscriptn]) do
  361. hp:=tunarynode(hp).left;
  362. if assigned(hp) and (hp.nodetype=loadn) and
  363. ((tloadnode(hp).symtableentry.typ=absolutesym) and
  364. tabsolutesym(tloadnode(hp).symtableentry).absseg) then
  365. begin
  366. if not(cs_typed_addresses in aktlocalswitches) then
  367. resulttype:=voidfarpointertype
  368. else
  369. resulttype.setdef(tpointerdef.createfar(left.resulttype));
  370. end
  371. else
  372. begin
  373. if not(cs_typed_addresses in aktlocalswitches) then
  374. resulttype:=voidpointertype
  375. else
  376. resulttype.setdef(tpointerdef.create(left.resulttype));
  377. end;
  378. end;
  379. { this is like the function addr }
  380. inc(parsing_para_level);
  381. set_varstate(left,false);
  382. dec(parsing_para_level);
  383. end;
  384. function taddrnode.pass_1 : tnode;
  385. begin
  386. result:=nil;
  387. firstpass(left);
  388. if codegenerror then
  389. exit;
  390. make_not_regable(left);
  391. if nf_procvarload in flags then
  392. begin
  393. registers32:=left.registers32;
  394. registersfpu:=left.registersfpu;
  395. {$ifdef SUPPORT_MMX}
  396. registersmmx:=left.registersmmx;
  397. {$endif SUPPORT_MMX}
  398. if registers32<1 then
  399. registers32:=1;
  400. location.loc:=left.location.loc;
  401. exit;
  402. end;
  403. { we should allow loc_mem for @string }
  404. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  405. begin
  406. aktfilepos:=left.fileinfo;
  407. CGMessage(cg_e_illegal_expression);
  408. end;
  409. registers32:=left.registers32;
  410. registersfpu:=left.registersfpu;
  411. {$ifdef SUPPORT_MMX}
  412. registersmmx:=left.registersmmx;
  413. {$endif SUPPORT_MMX}
  414. if registers32<1 then
  415. registers32:=1;
  416. { is this right for object of methods ?? }
  417. location.loc:=LOC_REGISTER;
  418. end;
  419. {*****************************************************************************
  420. TDOUBLEADDRNODE
  421. *****************************************************************************}
  422. constructor tdoubleaddrnode.create(l : tnode);
  423. begin
  424. inherited create(doubleaddrn,l);
  425. end;
  426. function tdoubleaddrnode.det_resulttype:tnode;
  427. begin
  428. result:=nil;
  429. resulttypepass(left);
  430. if codegenerror then
  431. exit;
  432. inc(parsing_para_level);
  433. set_varstate(left,false);
  434. dec(parsing_para_level);
  435. if (left.resulttype.def.deftype)<>procvardef then
  436. CGMessage(cg_e_illegal_expression);
  437. resulttype:=voidpointertype;
  438. end;
  439. function tdoubleaddrnode.pass_1 : tnode;
  440. begin
  441. result:=nil;
  442. make_not_regable(left);
  443. firstpass(left);
  444. if codegenerror then
  445. exit;
  446. if (left.location.loc<>LOC_REFERENCE) then
  447. CGMessage(cg_e_illegal_expression);
  448. registers32:=left.registers32;
  449. registersfpu:=left.registersfpu;
  450. {$ifdef SUPPORT_MMX}
  451. registersmmx:=left.registersmmx;
  452. {$endif SUPPORT_MMX}
  453. if registers32<1 then
  454. registers32:=1;
  455. location.loc:=LOC_REGISTER;
  456. end;
  457. {*****************************************************************************
  458. TDEREFNODE
  459. *****************************************************************************}
  460. constructor tderefnode.create(l : tnode);
  461. begin
  462. inherited create(derefn,l);
  463. end;
  464. function tderefnode.det_resulttype:tnode;
  465. begin
  466. result:=nil;
  467. resulttypepass(left);
  468. set_varstate(left,true);
  469. if codegenerror then
  470. exit;
  471. if left.resulttype.def.deftype=pointerdef then
  472. resulttype:=tpointerdef(left.resulttype.def).pointertype
  473. else
  474. CGMessage(cg_e_invalid_qualifier);
  475. end;
  476. function tderefnode.pass_1 : tnode;
  477. begin
  478. result:=nil;
  479. firstpass(left);
  480. if codegenerror then
  481. exit;
  482. registers32:=max(left.registers32,1);
  483. registersfpu:=left.registersfpu;
  484. {$ifdef SUPPORT_MMX}
  485. registersmmx:=left.registersmmx;
  486. {$endif SUPPORT_MMX}
  487. location.loc:=LOC_REFERENCE;
  488. end;
  489. {*****************************************************************************
  490. TSUBSCRIPTNODE
  491. *****************************************************************************}
  492. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  493. begin
  494. inherited create(subscriptn,l);
  495. { vs should be changed to tsym! }
  496. vs:=tvarsym(varsym);
  497. end;
  498. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  499. begin
  500. inherited ppuload(t,ppufile);
  501. vs:=tvarsym(ppufile.getderef);
  502. end;
  503. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  504. begin
  505. inherited ppuwrite(ppufile);
  506. ppufile.putderef(vs);
  507. end;
  508. procedure tsubscriptnode.derefimpl;
  509. begin
  510. inherited derefimpl;
  511. resolvesym(pointer(vs));
  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_CREFERENCE) and
  548. (left.location.loc<>LOC_REFERENCE) then
  549. CGMessage(cg_e_illegal_expression);
  550. location.loc:=left.location.loc;
  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_CREFERENCE;
  699. end;
  700. {*****************************************************************************
  701. TSELFNODE
  702. *****************************************************************************}
  703. constructor tselfnode.create(_class : tdef);
  704. begin
  705. inherited create(selfn);
  706. classdef:=_class;
  707. end;
  708. constructor tselfnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  709. begin
  710. inherited ppuload(t,ppufile);
  711. classdef:=tdef(ppufile.getderef);
  712. end;
  713. procedure tselfnode.ppuwrite(ppufile:tcompilerppufile);
  714. begin
  715. inherited ppuwrite(ppufile);
  716. ppufile.putderef(classdef);
  717. end;
  718. procedure tselfnode.derefimpl;
  719. begin
  720. inherited derefimpl;
  721. resolvedef(pointer(classdef));
  722. end;
  723. function tselfnode.det_resulttype:tnode;
  724. begin
  725. result:=nil;
  726. resulttype.setdef(classdef);
  727. end;
  728. function tselfnode.pass_1 : tnode;
  729. begin
  730. result:=nil;
  731. if (resulttype.def.deftype=classrefdef) or
  732. is_class(resulttype.def) then
  733. location.loc:=LOC_CREGISTER
  734. else
  735. location.loc:=LOC_REFERENCE;
  736. end;
  737. {*****************************************************************************
  738. TWITHNODE
  739. *****************************************************************************}
  740. constructor twithnode.create(symtable : twithsymtable;l,r : tnode;count : longint);
  741. begin
  742. inherited create(withn,l,r);
  743. withsymtable:=symtable;
  744. tablecount:=count;
  745. FillChar(withreference,sizeof(withreference),0);
  746. set_file_line(l);
  747. end;
  748. destructor twithnode.destroy;
  749. var
  750. hsymt,
  751. symt : tsymtable;
  752. i : longint;
  753. begin
  754. symt:=withsymtable;
  755. for i:=1 to tablecount do
  756. begin
  757. if assigned(symt) then
  758. begin
  759. hsymt:=symt.next;
  760. symt.free;
  761. symt:=hsymt;
  762. end;
  763. end;
  764. inherited destroy;
  765. end;
  766. constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  767. begin
  768. inherited ppuload(t,ppufile);
  769. internalerror(200208192);
  770. end;
  771. procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
  772. begin
  773. inherited ppuwrite(ppufile);
  774. internalerror(200208193);
  775. end;
  776. function twithnode.getcopy : tnode;
  777. var
  778. p : twithnode;
  779. begin
  780. p:=twithnode(inherited getcopy);
  781. p.withsymtable:=withsymtable;
  782. p.tablecount:=tablecount;
  783. p.withreference:=withreference;
  784. result:=p;
  785. end;
  786. function twithnode.det_resulttype:tnode;
  787. var
  788. symtable : tsymtable;
  789. i : longint;
  790. begin
  791. result:=nil;
  792. resulttype:=voidtype;
  793. if assigned(left) and assigned(right) then
  794. begin
  795. resulttypepass(left);
  796. unset_varstate(left);
  797. set_varstate(left,true);
  798. if codegenerror then
  799. exit;
  800. symtable:=withsymtable;
  801. for i:=1 to tablecount do
  802. begin
  803. if (left.nodetype=loadn) and
  804. (tloadnode(left).symtable=aktprocdef.localst) then
  805. twithsymtable(symtable).direct_with:=true;
  806. twithsymtable(symtable).withnode:=self;
  807. symtable:=symtable.next;
  808. end;
  809. resulttypepass(right);
  810. if codegenerror then
  811. exit;
  812. end;
  813. resulttype:=voidtype;
  814. end;
  815. function twithnode.pass_1 : tnode;
  816. begin
  817. result:=nil;
  818. if assigned(left) and assigned(right) then
  819. begin
  820. firstpass(left);
  821. firstpass(right);
  822. if codegenerror then
  823. exit;
  824. left_right_max;
  825. end
  826. else
  827. begin
  828. { optimization }
  829. result:=nil;
  830. end;
  831. end;
  832. function twithnode.docompare(p: tnode): boolean;
  833. begin
  834. docompare :=
  835. inherited docompare(p) and
  836. (withsymtable = twithnode(p).withsymtable) and
  837. (tablecount = twithnode(p).tablecount);
  838. end;
  839. begin
  840. cloadvmtnode := tloadvmtnode;
  841. chnewnode := thnewnode;
  842. chdisposenode := thdisposenode;
  843. caddrnode := taddrnode;
  844. cdoubleaddrnode := tdoubleaddrnode;
  845. cderefnode := tderefnode;
  846. csubscriptnode := tsubscriptnode;
  847. cvecnode := tvecnode;
  848. cselfnode := tselfnode;
  849. cwithnode := twithnode;
  850. end.
  851. {
  852. $Log$
  853. Revision 1.36 2002-08-19 19:36:43 peter
  854. * More fixes for cross unit inlining, all tnodes are now implemented
  855. * Moved pocall_internconst to po_internconst because it is not a
  856. calling type at all and it conflicted when inlining of these small
  857. functions was requested
  858. Revision 1.35 2002/07/23 09:51:23 daniel
  859. * Tried to make Tprocsym.defs protected. I didn't succeed but the cleanups
  860. are worth comitting.
  861. Revision 1.34 2002/07/20 11:57:54 florian
  862. * types.pas renamed to defbase.pas because D6 contains a types
  863. unit so this would conflicts if D6 programms are compiled
  864. + Willamette/SSE2 instructions to assembler added
  865. Revision 1.33 2002/05/18 13:34:10 peter
  866. * readded missing revisions
  867. Revision 1.32 2002/05/16 19:46:39 carl
  868. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  869. + try to fix temp allocation (still in ifdef)
  870. + generic constructor calls
  871. + start of tassembler / tmodulebase class cleanup
  872. Revision 1.30 2002/05/12 16:53:07 peter
  873. * moved entry and exitcode to ncgutil and cgobj
  874. * foreach gets extra argument for passing local data to the
  875. iterator function
  876. * -CR checks also class typecasts at runtime by changing them
  877. into as
  878. * fixed compiler to cycle with the -CR option
  879. * fixed stabs with elf writer, finally the global variables can
  880. be watched
  881. * removed a lot of routines from cga unit and replaced them by
  882. calls to cgobj
  883. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  884. u32bit then the other is typecasted also to u32bit without giving
  885. a rangecheck warning/error.
  886. * fixed pascal calling method with reversing also the high tree in
  887. the parast, detected by tcalcst3 test
  888. Revision 1.29 2002/04/21 19:02:04 peter
  889. * removed newn and disposen nodes, the code is now directly
  890. inlined from pexpr
  891. * -an option that will write the secondpass nodes to the .s file, this
  892. requires EXTDEBUG define to actually write the info
  893. * fixed various internal errors and crashes due recent code changes
  894. Revision 1.28 2002/04/20 21:32:23 carl
  895. + generic FPC_CHECKPOINTER
  896. + first parameter offset in stack now portable
  897. * rename some constants
  898. + move some cpu stuff to other units
  899. - remove unused constents
  900. * fix stacksize for some targets
  901. * fix generic size problems which depend now on EXTEND_SIZE constant
  902. Revision 1.27 2002/04/02 17:11:29 peter
  903. * tlocation,treference update
  904. * LOC_CONSTANT added for better constant handling
  905. * secondadd splitted in multiple routines
  906. * location_force_reg added for loading a location to a register
  907. of a specified size
  908. * secondassignment parses now first the right and then the left node
  909. (this is compatible with Kylix). This saves a lot of push/pop especially
  910. with string operations
  911. * adapted some routines to use the new cg methods
  912. Revision 1.26 2002/04/01 20:57:13 jonas
  913. * fixed web bug 1907
  914. * fixed some other procvar related bugs (all related to accepting procvar
  915. constructs with either too many or too little parameters)
  916. (both merged, includes second typo fix of pexpr.pas)
  917. }