nmem.pas 30 KB

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