nld.pas 41 KB

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