nld.pas 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl
  4. Type checking and register allocation for load/assignment 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 nld;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,
  23. {$ifdef state_tracking}
  24. nstate,
  25. {$endif}
  26. symconst,symbase,symtype,symsym,symdef;
  27. type
  28. tloadnode = class(tunarynode)
  29. symtableentry : tsym;
  30. symtable : tsymtable;
  31. procdeflist : tprocdef;
  32. constructor create(v : tsym;st : tsymtable);virtual;
  33. constructor create_procvar(v : tsym;d:tprocdef;st : tsymtable);virtual;
  34. procedure set_mp(p:tnode);
  35. function getcopy : tnode;override;
  36. function pass_1 : tnode;override;
  37. function det_resulttype:tnode;override;
  38. function docompare(p: tnode): boolean; override;
  39. {$ifdef extdebug}
  40. procedure dowrite;override;
  41. {$endif}
  42. end;
  43. tloadnodeclass = class of tloadnode;
  44. { different assignment types }
  45. tassigntype = (at_normal,at_plus,at_minus,at_star,at_slash);
  46. tassignmentnode = class(tbinarynode)
  47. assigntype : tassigntype;
  48. constructor create(l,r : tnode);virtual;
  49. function getcopy : tnode;override;
  50. function pass_1 : tnode;override;
  51. function det_resulttype:tnode;override;
  52. {$ifdef state_tracking}
  53. function track_state_pass(exec_known:boolean):boolean;override;
  54. {$endif state_tracking}
  55. function docompare(p: tnode): boolean; override;
  56. end;
  57. tassignmentnodeclass = class of tassignmentnode;
  58. tfuncretnode = class(tnode)
  59. funcretsym : tfuncretsym;
  60. constructor create(v:tsym);virtual;
  61. function getcopy : tnode;override;
  62. function pass_1 : tnode;override;
  63. function det_resulttype:tnode;override;
  64. function docompare(p: tnode): boolean; override;
  65. end;
  66. tfuncretnodeclass = class of tfuncretnode;
  67. tarrayconstructorrangenode = class(tbinarynode)
  68. constructor create(l,r : tnode);virtual;
  69. function pass_1 : tnode;override;
  70. function det_resulttype:tnode;override;
  71. end;
  72. tarrayconstructorrangenodeclass = class of tarrayconstructorrangenode;
  73. tarrayconstructornode = class(tbinarynode)
  74. constructor create(l,r : tnode);virtual;
  75. function getcopy : tnode;override;
  76. function pass_1 : tnode;override;
  77. function det_resulttype:tnode;override;
  78. function docompare(p: tnode): boolean; override;
  79. procedure force_type(tt:ttype);
  80. end;
  81. tarrayconstructornodeclass = class of tarrayconstructornode;
  82. ttypenode = class(tnode)
  83. allowed : boolean;
  84. restype : ttype;
  85. constructor create(t : ttype);virtual;
  86. function pass_1 : tnode;override;
  87. function det_resulttype:tnode;override;
  88. function docompare(p: tnode): boolean; override;
  89. end;
  90. ttypenodeclass = class of ttypenode;
  91. trttinode = class(tnode)
  92. l1,l2 : longint;
  93. rttitype : trttitype;
  94. rttidef : tstoreddef;
  95. constructor create(def:tstoreddef;rt:trttitype);virtual;
  96. function getcopy : tnode;override;
  97. function pass_1 : tnode;override;
  98. procedure pass_2;override;
  99. function det_resulttype:tnode;override;
  100. function docompare(p: tnode): boolean; override;
  101. end;
  102. trttinodeclass = class of trttinode;
  103. var
  104. cloadnode : tloadnodeclass;
  105. cassignmentnode : tassignmentnodeclass;
  106. cfuncretnode : tfuncretnodeclass;
  107. carrayconstructorrangenode : tarrayconstructorrangenodeclass;
  108. carrayconstructornode : tarrayconstructornodeclass;
  109. ctypenode : ttypenodeclass;
  110. crttinode : trttinodeclass;
  111. implementation
  112. uses
  113. cutils,verbose,globtype,globals,systems,
  114. symtable,paramgr,defbase,
  115. htypechk,pass_1,
  116. ncon,ninl,ncnv,nmem,ncal,cpubase,rgobj,cginfo,cgbase
  117. ;
  118. {*****************************************************************************
  119. TLOADNODE
  120. *****************************************************************************}
  121. constructor tloadnode.create(v : tsym;st : tsymtable);
  122. begin
  123. inherited create(loadn,nil);
  124. if not assigned(v) then
  125. internalerror(200108121);
  126. symtableentry:=v;
  127. symtable:=st;
  128. procdeflist:=nil;
  129. end;
  130. constructor tloadnode.create_procvar(v : tsym;d:tprocdef;st : tsymtable);
  131. begin
  132. inherited create(loadn,nil);
  133. if not assigned(v) then
  134. internalerror(200108121);
  135. symtableentry:=v;
  136. symtable:=st;
  137. procdeflist:=d;
  138. end;
  139. procedure tloadnode.set_mp(p:tnode);
  140. begin
  141. left:=p;
  142. end;
  143. function tloadnode.getcopy : tnode;
  144. var
  145. n : tloadnode;
  146. begin
  147. n:=tloadnode(inherited getcopy);
  148. n.symtable:=symtable;
  149. n.symtableentry:=symtableentry;
  150. result:=n;
  151. end;
  152. function tloadnode.det_resulttype:tnode;
  153. var
  154. p1 : tnode;
  155. p : pprocinfo;
  156. begin
  157. result:=nil;
  158. { optimize simple with loadings }
  159. if (symtable.symtabletype=withsymtable) and
  160. (twithsymtable(symtable).direct_with) and
  161. (symtableentry.typ=varsym) then
  162. begin
  163. p1:=tnode(twithsymtable(symtable).withrefnode).getcopy;
  164. p1:=csubscriptnode.create(tvarsym(symtableentry),p1);
  165. left:=nil;
  166. result:=p1;
  167. exit;
  168. end;
  169. { handle first absolute as it will replace the symtableentry }
  170. if symtableentry.typ=absolutesym then
  171. begin
  172. { force the resulttype to the type of the absolute }
  173. resulttype:=tabsolutesym(symtableentry).vartype;
  174. { replace the symtableentry when it points to a var, else
  175. we are finished }
  176. if tabsolutesym(symtableentry).abstyp=tovar then
  177. begin
  178. symtableentry:=tabsolutesym(symtableentry).ref;
  179. symtable:=symtableentry.owner;
  180. include(flags,nf_absolute);
  181. end
  182. else
  183. exit;
  184. end;
  185. case symtableentry.typ of
  186. funcretsym :
  187. begin
  188. { find the main funcret for the function }
  189. p:=procinfo;
  190. while assigned(p) do
  191. begin
  192. if assigned(p^.procdef.funcretsym) and
  193. ((tfuncretsym(symtableentry)=p^.procdef.resultfuncretsym) or
  194. (tfuncretsym(symtableentry)=p^.procdef.funcretsym)) then
  195. begin
  196. symtableentry:=p^.procdef.funcretsym;
  197. break;
  198. end;
  199. p:=p^.parent;
  200. end;
  201. { generate funcretnode }
  202. p1:=cfuncretnode.create(symtableentry);
  203. resulttypepass(p1);
  204. { if it's refered as absolute then we need to have the
  205. type of the absolute instead of the function return,
  206. the function return is then also assigned }
  207. if nf_absolute in flags then
  208. begin
  209. tfuncretsym(symtableentry).funcretstate:=vs_assigned;
  210. p1.resulttype:=resulttype;
  211. end;
  212. left:=nil;
  213. result:=p1;
  214. end;
  215. constsym:
  216. begin
  217. if tconstsym(symtableentry).consttyp=constresourcestring then
  218. resulttype:=cansistringtype
  219. else
  220. internalerror(22799);
  221. end;
  222. varsym :
  223. begin
  224. { if it's refered by absolute then it's used }
  225. if nf_absolute in flags then
  226. tvarsym(symtableentry).varstate:=vs_used
  227. else
  228. resulttype:=tvarsym(symtableentry).vartype;
  229. end;
  230. typedconstsym :
  231. if not(nf_absolute in flags) then
  232. resulttype:=ttypedconstsym(symtableentry).typedconsttype;
  233. procsym :
  234. begin
  235. if not assigned(procdeflist) then
  236. begin
  237. if assigned(tprocsym(symtableentry).defs^.next) then
  238. CGMessage(parser_e_no_overloaded_procvars);
  239. resulttype.setdef(tprocsym(symtableentry).defs^.def);
  240. end
  241. else
  242. resulttype.setdef(procdeflist);
  243. if (m_tp_procvar in aktmodeswitches) then
  244. begin
  245. if assigned(left) then
  246. begin
  247. if left.nodetype=typen then
  248. begin
  249. { we need to return only a voidpointer,
  250. so no need to keep the typen }
  251. left.free;
  252. left:=nil;
  253. end;
  254. end
  255. else
  256. begin
  257. { if the owner of the procsym is a object, }
  258. { left must be set, if left isn't set }
  259. { it can be only self }
  260. if (tprocsym(symtableentry).owner.symtabletype=objectsymtable) then
  261. left:=cselfnode.create(tobjectdef(symtableentry.owner.defowner));
  262. end;
  263. end;
  264. { process methodpointer }
  265. if assigned(left) then
  266. begin
  267. resulttypepass(left);
  268. { turn on the allowed flag, the secondpass
  269. will handle the typen itself }
  270. if left.nodetype=typen then
  271. ttypenode(left).allowed:=true;
  272. end;
  273. end;
  274. else
  275. internalerror(200104141);
  276. end;
  277. end;
  278. function tloadnode.pass_1 : tnode;
  279. begin
  280. result:=nil;
  281. location.loc:=LOC_REFERENCE;
  282. registers32:=0;
  283. registersfpu:=0;
  284. {$ifdef SUPPORT_MMX}
  285. registersmmx:=0;
  286. {$endif SUPPORT_MMX}
  287. case symtableentry.typ of
  288. absolutesym :
  289. ;
  290. funcretsym :
  291. internalerror(200104142);
  292. constsym:
  293. begin
  294. if tconstsym(symtableentry).consttyp=constresourcestring then
  295. begin
  296. { we use ansistrings so no fast exit here }
  297. if assigned(procinfo) then
  298. procinfo^.no_fast_exit:=true;
  299. location.loc:=LOC_CREFERENCE;
  300. end;
  301. end;
  302. varsym :
  303. begin
  304. if (symtable.symtabletype in [parasymtable,localsymtable]) and
  305. (lexlevel>symtable.symtablelevel) then
  306. begin
  307. { if the variable is in an other stackframe then we need
  308. a register to dereference }
  309. if (symtable.symtablelevel)>0 then
  310. begin
  311. registers32:=1;
  312. { further, the variable can't be put into a register }
  313. tvarsym(symtableentry).varoptions:=
  314. tvarsym(symtableentry).varoptions-[vo_fpuregable,vo_regable];
  315. end;
  316. end;
  317. if (tvarsym(symtableentry).varspez=vs_const) then
  318. location.loc:=LOC_CREFERENCE;
  319. { we need a register for call by reference parameters }
  320. if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  321. ((tvarsym(symtableentry).varspez=vs_const) and
  322. paramanager.push_addr_param(tvarsym(symtableentry).vartype.def)) or
  323. { call by value open arrays are also indirect addressed }
  324. is_open_array(tvarsym(symtableentry).vartype.def) then
  325. registers32:=1;
  326. if symtable.symtabletype=withsymtable then
  327. inc(registers32);
  328. if ([vo_is_thread_var,vo_is_dll_var]*tvarsym(symtableentry).varoptions)<>[] then
  329. registers32:=1;
  330. { count variable references }
  331. { this will create problem with local var set by
  332. under_procedures
  333. if (assigned(tvarsym(symtableentry).owner) and assigned(aktprocsym)
  334. and ((tvarsym(symtableentry).owner = aktprocdef.localst)
  335. or (tvarsym(symtableentry).owner = aktprocdef.localst))) then }
  336. if rg.t_times<1 then
  337. inc(tvarsym(symtableentry).refs)
  338. else
  339. inc(tvarsym(symtableentry).refs,rg.t_times);
  340. end;
  341. typedconstsym :
  342. ;
  343. procsym :
  344. begin
  345. { method pointer ? }
  346. if assigned(left) then
  347. begin
  348. firstpass(left);
  349. registers32:=max(registers32,left.registers32);
  350. registersfpu:=max(registersfpu,left.registersfpu);
  351. {$ifdef SUPPORT_MMX}
  352. registersmmx:=max(registersmmx,left.registersmmx);
  353. {$endif SUPPORT_MMX}
  354. end;
  355. end;
  356. else
  357. internalerror(200104143);
  358. end;
  359. end;
  360. function tloadnode.docompare(p: tnode): boolean;
  361. begin
  362. docompare :=
  363. inherited docompare(p) and
  364. (symtableentry = tloadnode(p).symtableentry) and
  365. (symtable = tloadnode(p).symtable);
  366. end;
  367. {$ifdef extdebug}
  368. procedure Tloadnode.dowrite;
  369. begin
  370. inherited dowrite;
  371. write('[',symtableentry.name,']');
  372. end;
  373. {$endif}
  374. {*****************************************************************************
  375. TASSIGNMENTNODE
  376. *****************************************************************************}
  377. constructor tassignmentnode.create(l,r : tnode);
  378. begin
  379. inherited create(assignn,l,r);
  380. assigntype:=at_normal;
  381. end;
  382. function tassignmentnode.getcopy : tnode;
  383. var
  384. n : tassignmentnode;
  385. begin
  386. n:=tassignmentnode(inherited getcopy);
  387. n.assigntype:=assigntype;
  388. getcopy:=n;
  389. end;
  390. function tassignmentnode.det_resulttype:tnode;
  391. var
  392. hp : tnode;
  393. useshelper : boolean;
  394. begin
  395. result:=nil;
  396. resulttype:=voidtype;
  397. { must be made unique }
  398. if assigned(left) then
  399. begin
  400. set_unique(left);
  401. { set we the function result? }
  402. set_funcret_is_valid(left);
  403. end;
  404. resulttypepass(left);
  405. resulttypepass(right);
  406. set_varstate(left,false);
  407. set_varstate(right,true);
  408. if codegenerror then
  409. exit;
  410. { assignments to open arrays aren't allowed }
  411. if is_open_array(left.resulttype.def) then
  412. CGMessage(type_e_mismatch);
  413. { test if node can be assigned, properties are allowed }
  414. valid_for_assignment(left);
  415. { assigning nil to a dynamic array clears the array }
  416. if is_dynamic_array(left.resulttype.def) and
  417. (right.nodetype=niln) then
  418. begin
  419. hp:=ccallparanode.create(caddrnode.create
  420. (crttinode.create(tstoreddef(left.resulttype.def),initrtti)),
  421. ccallparanode.create(ctypeconvnode.create_explicit(left,voidpointertype),nil));
  422. result := ccallnode.createintern('fpc_dynarray_clear',hp);
  423. left:=nil;
  424. exit;
  425. end;
  426. { shortstring helpers can do the conversion directly,
  427. so treat them separatly }
  428. if (is_shortstring(left.resulttype.def)) then
  429. begin
  430. { test for s:=s+anything ... }
  431. { the problem is for
  432. s:=s+s+s;
  433. this is broken here !! }
  434. {$ifdef newoptimizations2}
  435. { the above is fixed now, but still problem with s := s + f(); if }
  436. { f modifies s (bad programming, so only enable if uncertain }
  437. { optimizations are on) (JM) }
  438. if (cs_UncertainOpts in aktglobalswitches) then
  439. begin
  440. hp := right;
  441. while hp.treetype=addn do
  442. hp:=hp.left;
  443. if equal_trees(left,hp) and
  444. not multiple_uses(left,right) then
  445. begin
  446. concat_string:=true;
  447. hp:=right;
  448. while hp.treetype=addn do
  449. begin
  450. hp.use_strconcat:=true;
  451. hp:=hp.left;
  452. end;
  453. end;
  454. end;
  455. {$endif newoptimizations2}
  456. { insert typeconv, except for chars that are handled in
  457. secondpass and except for ansi/wide string that can
  458. be converted immediatly }
  459. if not(is_char(right.resulttype.def) or
  460. (right.resulttype.def.deftype=stringdef)) then
  461. inserttypeconv(right,left.resulttype);
  462. if right.resulttype.def.deftype=stringdef then
  463. begin
  464. useshelper:=true;
  465. { convert constant strings to shortstrings. But
  466. skip empty constant strings, that will be handled
  467. in secondpass }
  468. if (right.nodetype=stringconstn) then
  469. begin
  470. inserttypeconv(right,left.resulttype);
  471. if (tstringconstnode(right).len=0) then
  472. useshelper:=false;
  473. end;
  474. if useshelper then
  475. begin
  476. hp:=ccallparanode.create
  477. (right,
  478. ccallparanode.create(cinlinenode.create
  479. (in_high_x,false,left.getcopy),nil));
  480. result:=ccallnode.createinternreturn('fpc_'+tstringdef(right.resulttype.def).stringtypname+'_to_shortstr',hp,left);
  481. left:=nil;
  482. right:=nil;
  483. exit;
  484. end;
  485. end;
  486. end
  487. else
  488. inserttypeconv(right,left.resulttype);
  489. { call helpers for interface }
  490. if is_interfacecom(left.resulttype.def) then
  491. begin
  492. hp:=ccallparanode.create(ctypeconvnode.create_explicit
  493. (right,voidpointertype),
  494. ccallparanode.create(ctypeconvnode.create_explicit
  495. (left,voidpointertype),nil));
  496. result:=ccallnode.createintern('fpc_intf_assign',hp);
  497. left:=nil;
  498. right:=nil;
  499. exit;
  500. end;
  501. { check if local proc/func is assigned to procvar }
  502. if right.resulttype.def.deftype=procvardef then
  503. test_local_to_procvar(tprocvardef(right.resulttype.def),left.resulttype.def);
  504. end;
  505. function tassignmentnode.pass_1 : tnode;
  506. begin
  507. result:=nil;
  508. firstpass(left);
  509. firstpass(right);
  510. if codegenerror then
  511. exit;
  512. registers32:=left.registers32+right.registers32;
  513. registersfpu:=max(left.registersfpu,right.registersfpu);
  514. {$ifdef SUPPORT_MMX}
  515. registersmmx:=max(left.registersmmx,right.registersmmx);
  516. {$endif SUPPORT_MMX}
  517. end;
  518. function tassignmentnode.docompare(p: tnode): boolean;
  519. begin
  520. docompare :=
  521. inherited docompare(p) and
  522. (assigntype = tassignmentnode(p).assigntype);
  523. end;
  524. {$ifdef state_tracking}
  525. function Tassignmentnode.track_state_pass(exec_known:boolean):boolean;
  526. var se:Tstate_entry;
  527. begin
  528. track_state_pass:=false;
  529. if exec_known then
  530. begin
  531. track_state_pass:=right.track_state_pass(exec_known);
  532. {Force a new resulttype pass.}
  533. right.resulttype.def:=nil;
  534. do_resulttypepass(right);
  535. resulttypepass(right);
  536. aktstate.store_fact(left.getcopy,right.getcopy);
  537. end
  538. else
  539. aktstate.delete_fact(left);
  540. end;
  541. {$endif}
  542. {*****************************************************************************
  543. TFUNCRETNODE
  544. *****************************************************************************}
  545. constructor tfuncretnode.create(v:tsym);
  546. begin
  547. inherited create(funcretn);
  548. funcretsym:=tfuncretsym(v);
  549. end;
  550. function tfuncretnode.getcopy : tnode;
  551. var
  552. n : tfuncretnode;
  553. begin
  554. n:=tfuncretnode(inherited getcopy);
  555. n.funcretsym:=funcretsym;
  556. getcopy:=n;
  557. end;
  558. function tfuncretnode.det_resulttype:tnode;
  559. begin
  560. result:=nil;
  561. resulttype:=funcretsym.returntype;
  562. end;
  563. function tfuncretnode.pass_1 : tnode;
  564. begin
  565. result:=nil;
  566. location.loc:=LOC_REFERENCE;
  567. if paramanager.ret_in_param(resulttype.def) or
  568. (lexlevel<>funcretsym.owner.symtablelevel) then
  569. registers32:=1;
  570. end;
  571. function tfuncretnode.docompare(p: tnode): boolean;
  572. begin
  573. docompare :=
  574. inherited docompare(p) and
  575. (funcretsym = tfuncretnode(p).funcretsym);
  576. end;
  577. {*****************************************************************************
  578. TARRAYCONSTRUCTORRANGENODE
  579. *****************************************************************************}
  580. constructor tarrayconstructorrangenode.create(l,r : tnode);
  581. begin
  582. inherited create(arrayconstructorrangen,l,r);
  583. end;
  584. function tarrayconstructorrangenode.det_resulttype:tnode;
  585. begin
  586. result:=nil;
  587. resulttypepass(left);
  588. resulttypepass(right);
  589. set_varstate(left,true);
  590. set_varstate(right,true);
  591. if codegenerror then
  592. exit;
  593. resulttype:=left.resulttype;
  594. end;
  595. function tarrayconstructorrangenode.pass_1 : tnode;
  596. begin
  597. firstpass(left);
  598. firstpass(right);
  599. location.loc := LOC_CREFERENCE;
  600. calcregisters(self,0,0,0);
  601. result:=nil;
  602. end;
  603. {****************************************************************************
  604. TARRAYCONSTRUCTORNODE
  605. *****************************************************************************}
  606. constructor tarrayconstructornode.create(l,r : tnode);
  607. begin
  608. inherited create(arrayconstructorn,l,r);
  609. end;
  610. function tarrayconstructornode.getcopy : tnode;
  611. var
  612. n : tarrayconstructornode;
  613. begin
  614. n:=tarrayconstructornode(inherited getcopy);
  615. result:=n;
  616. end;
  617. function tarrayconstructornode.det_resulttype:tnode;
  618. var
  619. htype : ttype;
  620. hp : tarrayconstructornode;
  621. len : longint;
  622. varia : boolean;
  623. begin
  624. result:=nil;
  625. { are we allowing array constructor? Then convert it to a set }
  626. if not allow_array_constructor then
  627. begin
  628. hp:=tarrayconstructornode(getcopy);
  629. arrayconstructor_to_set(hp);
  630. result:=hp;
  631. exit;
  632. end;
  633. { only pass left tree, right tree contains next construct if any }
  634. htype.reset;
  635. len:=0;
  636. varia:=false;
  637. if assigned(left) then
  638. begin
  639. hp:=self;
  640. while assigned(hp) do
  641. begin
  642. resulttypepass(hp.left);
  643. set_varstate(hp.left,true);
  644. if (htype.def=nil) then
  645. htype:=hp.left.resulttype
  646. else
  647. begin
  648. if ((nf_novariaallowed in flags) or (not varia)) and
  649. (not is_equal(htype.def,hp.left.resulttype.def)) then
  650. begin
  651. varia:=true;
  652. end;
  653. end;
  654. inc(len);
  655. hp:=tarrayconstructornode(hp.right);
  656. end;
  657. end;
  658. if not assigned(htype.def) then
  659. htype:=voidtype;
  660. resulttype.setdef(tarraydef.create(0,len-1,s32bittype));
  661. tarraydef(resulttype.def).elementtype:=htype;
  662. tarraydef(resulttype.def).IsConstructor:=true;
  663. tarraydef(resulttype.def).IsVariant:=varia;
  664. end;
  665. procedure tarrayconstructornode.force_type(tt:ttype);
  666. var
  667. hp : tarrayconstructornode;
  668. begin
  669. tarraydef(resulttype.def).elementtype:=tt;
  670. tarraydef(resulttype.def).IsConstructor:=true;
  671. tarraydef(resulttype.def).IsVariant:=false;
  672. if assigned(left) then
  673. begin
  674. hp:=self;
  675. while assigned(hp) do
  676. begin
  677. inserttypeconv(hp.left,tt);
  678. hp:=tarrayconstructornode(hp.right);
  679. end;
  680. end;
  681. end;
  682. function tarrayconstructornode.pass_1 : tnode;
  683. var
  684. thp,
  685. chp,
  686. hp : tarrayconstructornode;
  687. dovariant : boolean;
  688. htype : ttype;
  689. orgflags : tnodeflagset;
  690. begin
  691. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  692. result:=nil;
  693. { only pass left tree, right tree contains next construct if any }
  694. if assigned(left) then
  695. begin
  696. hp:=self;
  697. while assigned(hp) do
  698. begin
  699. firstpass(hp.left);
  700. { Insert typeconvs for array of const }
  701. if dovariant then
  702. begin
  703. case hp.left.resulttype.def.deftype of
  704. enumdef :
  705. begin
  706. hp.left:=ctypeconvnode.create(hp.left,s32bittype);
  707. firstpass(hp.left);
  708. end;
  709. orddef :
  710. begin
  711. if is_integer(hp.left.resulttype.def) and
  712. not(is_64bitint(hp.left.resulttype.def)) then
  713. begin
  714. hp.left:=ctypeconvnode.create(hp.left,s32bittype);
  715. firstpass(hp.left);
  716. end;
  717. end;
  718. floatdef :
  719. begin
  720. hp.left:=ctypeconvnode.create(hp.left,pbestrealtype^);
  721. firstpass(hp.left);
  722. end;
  723. stringdef :
  724. begin
  725. if nf_cargs in flags then
  726. begin
  727. hp.left:=ctypeconvnode.create(hp.left,charpointertype);
  728. firstpass(hp.left);
  729. end;
  730. end;
  731. procvardef :
  732. begin
  733. hp.left:=ctypeconvnode.create(hp.left,voidpointertype);
  734. firstpass(hp.left);
  735. end;
  736. pointerdef,
  737. classrefdef,
  738. objectdef : ;
  739. else
  740. CGMessagePos1(hp.left.fileinfo,type_e_wrong_type_in_array_constructor,hp.left.resulttype.def.typename);
  741. end;
  742. end;
  743. hp:=tarrayconstructornode(hp.right);
  744. end;
  745. { swap the tree for cargs }
  746. if (nf_cargs in flags) and (not(nf_cargswap in flags)) then
  747. begin
  748. chp:=nil;
  749. { save resulttype }
  750. htype:=resulttype;
  751. { we need a copy here, because self is destroyed }
  752. { by firstpass later }
  753. hp:=tarrayconstructornode(getcopy);
  754. { we also need a copy of the nf_ forcevaria flag to restore }
  755. { later) (JM) }
  756. orgflags := flags * [nf_forcevaria];
  757. while assigned(hp) do
  758. begin
  759. thp:=tarrayconstructornode(hp.right);
  760. hp.right:=chp;
  761. chp:=hp;
  762. hp:=thp;
  763. end;
  764. chp.flags := chp.flags+orgflags;
  765. include(chp.flags,nf_cargswap);
  766. chp.location.loc:=LOC_CREFERENCE;
  767. calcregisters(chp,0,0,0);
  768. chp.resulttype:=htype;
  769. result:=chp;
  770. exit;
  771. end;
  772. end;
  773. { C Arguments are pushed on the stack and
  774. are not accesible after the push }
  775. if not(nf_cargs in flags) then
  776. location.loc:=LOC_CREFERENCE
  777. else
  778. location.loc:=LOC_INVALID;
  779. calcregisters(self,0,0,0);
  780. end;
  781. function tarrayconstructornode.docompare(p: tnode): boolean;
  782. begin
  783. docompare :=
  784. inherited docompare(p);
  785. end;
  786. {*****************************************************************************
  787. TTYPENODE
  788. *****************************************************************************}
  789. constructor ttypenode.create(t : ttype);
  790. begin
  791. inherited create(typen);
  792. restype:=t;
  793. allowed:=false;
  794. end;
  795. function ttypenode.det_resulttype:tnode;
  796. begin
  797. result:=nil;
  798. resulttype:=restype;
  799. { check if it's valid }
  800. if restype.def.deftype = errordef then
  801. CGMessage(cg_e_illegal_expression);
  802. end;
  803. function ttypenode.pass_1 : tnode;
  804. begin
  805. result:=nil;
  806. { a typenode can't generate code, so we give here
  807. an error. Else it'll be an abstract error in pass_2.
  808. Only when the allowed flag is set we don't generate
  809. an error }
  810. if not allowed then
  811. Message(parser_e_no_type_not_allowed_here);
  812. end;
  813. function ttypenode.docompare(p: tnode): boolean;
  814. begin
  815. docompare :=
  816. inherited docompare(p);
  817. end;
  818. {*****************************************************************************
  819. TRTTINODE
  820. *****************************************************************************}
  821. constructor trttinode.create(def:tstoreddef;rt:trttitype);
  822. begin
  823. inherited create(rttin);
  824. rttidef:=def;
  825. rttitype:=rt;
  826. end;
  827. function trttinode.getcopy : tnode;
  828. var
  829. n : trttinode;
  830. begin
  831. n:=trttinode(inherited getcopy);
  832. n.rttidef:=rttidef;
  833. n.rttitype:=rttitype;
  834. result:=n;
  835. end;
  836. function trttinode.det_resulttype:tnode;
  837. begin
  838. { rtti information will be returned as a void pointer }
  839. result:=nil;
  840. resulttype:=voidpointertype;
  841. end;
  842. function trttinode.pass_1 : tnode;
  843. begin
  844. result:=nil;
  845. location.loc:=LOC_CREFERENCE;
  846. end;
  847. function trttinode.docompare(p: tnode): boolean;
  848. begin
  849. docompare :=
  850. inherited docompare(p) and
  851. (rttidef = trttinode(p).rttidef) and
  852. (rttitype = trttinode(p).rttitype);
  853. end;
  854. procedure trttinode.pass_2;
  855. begin
  856. location_reset(location,LOC_CREFERENCE,OS_NO);
  857. location.reference.symbol:=rttidef.get_rtti_label(rttitype);
  858. end;
  859. begin
  860. cloadnode:=tloadnode;
  861. cassignmentnode:=tassignmentnode;
  862. cfuncretnode:=tfuncretnode;
  863. carrayconstructorrangenode:=tarrayconstructorrangenode;
  864. carrayconstructornode:=tarrayconstructornode;
  865. ctypenode:=ttypenode;
  866. crttinode:=trttinode;
  867. end.
  868. {
  869. $Log$
  870. Revision 1.49 2002-07-20 11:57:54 florian
  871. * types.pas renamed to defbase.pas because D6 contains a types
  872. unit so this would conflicts if D6 programms are compiled
  873. + Willamette/SSE2 instructions to assembler added
  874. Revision 1.48 2002/07/20 07:44:37 daniel
  875. * Forgot to add a {$ifdef extdebug}
  876. Revision 1.47 2002/07/19 12:55:27 daniel
  877. * Further developed state tracking in whilerepeatn
  878. Revision 1.46 2002/07/19 11:41:36 daniel
  879. * State tracker work
  880. * The whilen and repeatn are now completely unified into whilerepeatn. This
  881. allows the state tracker to change while nodes automatically into
  882. repeat nodes.
  883. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  884. 'not(a>b)' is optimized into 'a<=b'.
  885. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  886. by removing the notn and later switchting the true and falselabels. The
  887. same is done with 'repeat until not a'.
  888. Revision 1.45 2002/07/15 18:03:15 florian
  889. * readded removed changes
  890. Revision 1.43 2002/07/11 14:41:28 florian
  891. * start of the new generic parameter handling
  892. Revision 1.44 2002/07/14 18:00:44 daniel
  893. + Added the beginning of a state tracker. This will track the values of
  894. variables through procedures and optimize things away.
  895. Revision 1.42 2002/05/18 13:34:10 peter
  896. * readded missing revisions
  897. Revision 1.41 2002/05/16 19:46:38 carl
  898. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  899. + try to fix temp allocation (still in ifdef)
  900. + generic constructor calls
  901. + start of tassembler / tmodulebase class cleanup
  902. Revision 1.39 2002/05/12 16:53:07 peter
  903. * moved entry and exitcode to ncgutil and cgobj
  904. * foreach gets extra argument for passing local data to the
  905. iterator function
  906. * -CR checks also class typecasts at runtime by changing them
  907. into as
  908. * fixed compiler to cycle with the -CR option
  909. * fixed stabs with elf writer, finally the global variables can
  910. be watched
  911. * removed a lot of routines from cga unit and replaced them by
  912. calls to cgobj
  913. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  914. u32bit then the other is typecasted also to u32bit without giving
  915. a rangecheck warning/error.
  916. * fixed pascal calling method with reversing also the high tree in
  917. the parast, detected by tcalcst3 test
  918. Revision 1.38 2002/04/25 20:16:39 peter
  919. * moved more routines from cga/n386util
  920. Revision 1.37 2002/04/23 19:16:34 peter
  921. * add pinline unit that inserts compiler supported functions using
  922. one or more statements
  923. * moved finalize and setlength from ninl to pinline
  924. Revision 1.36 2002/04/22 16:30:06 peter
  925. * fixed @methodpointer
  926. Revision 1.35 2002/04/21 19:02:04 peter
  927. * removed newn and disposen nodes, the code is now directly
  928. inlined from pexpr
  929. * -an option that will write the secondpass nodes to the .s file, this
  930. requires EXTDEBUG define to actually write the info
  931. * fixed various internal errors and crashes due recent code changes
  932. Revision 1.34 2002/04/02 17:11:29 peter
  933. * tlocation,treference update
  934. * LOC_CONSTANT added for better constant handling
  935. * secondadd splitted in multiple routines
  936. * location_force_reg added for loading a location to a register
  937. of a specified size
  938. * secondassignment parses now first the right and then the left node
  939. (this is compatible with Kylix). This saves a lot of push/pop especially
  940. with string operations
  941. * adapted some routines to use the new cg methods
  942. Revision 1.33 2002/03/31 20:26:34 jonas
  943. + a_loadfpu_* and a_loadmm_* methods in tcg
  944. * register allocation is now handled by a class and is mostly processor
  945. independent (+rgobj.pas and i386/rgcpu.pas)
  946. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  947. * some small improvements and fixes to the optimizer
  948. * some register allocation fixes
  949. * some fpuvaroffset fixes in the unary minus node
  950. * push/popusedregisters is now called rg.save/restoreusedregisters and
  951. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  952. also better optimizable)
  953. * fixed and optimized register saving/restoring for new/dispose nodes
  954. * LOC_FPU locations now also require their "register" field to be set to
  955. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  956. - list field removed of the tnode class because it's not used currently
  957. and can cause hard-to-find bugs
  958. Revision 1.32 2002/01/19 11:52:32 peter
  959. * dynarr:=nil support added
  960. }