nld.pas 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Type checking and register allocation for load/assignment nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit nld;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. {$ifdef state_tracking}
  23. nstate,
  24. {$endif}
  25. symconst,symbase,symtype,symsym,symdef;
  26. type
  27. tloadnode = class(tunarynode)
  28. protected
  29. procdef : tprocdef;
  30. procdefderef : tderef;
  31. public
  32. symtableentry : tsym;
  33. symtableentryderef : tderef;
  34. symtable : TSymtable;
  35. constructor create(v : tsym;st : TSymtable);virtual;
  36. constructor create_procvar(v : tsym;d:tprocdef;st : TSymtable);virtual;
  37. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  38. procedure ppuwrite(ppufile:tcompilerppufile);override;
  39. procedure buildderefimpl;override;
  40. procedure derefimpl;override;
  41. procedure set_mp(p:tnode);
  42. function is_addr_param_load:boolean;
  43. function dogetcopy : tnode;override;
  44. function pass_1 : tnode;override;
  45. function pass_typecheck:tnode;override;
  46. procedure mark_write;override;
  47. function docompare(p: tnode): boolean; override;
  48. procedure printnodedata(var t:text);override;
  49. procedure setprocdef(p : tprocdef);
  50. end;
  51. tloadnodeclass = class of tloadnode;
  52. { different assignment types }
  53. tassigntype = (at_normal,at_plus,at_minus,at_star,at_slash);
  54. tassignmentnode = class(tbinarynode)
  55. assigntype : tassigntype;
  56. constructor create(l,r : tnode);virtual;
  57. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  58. procedure ppuwrite(ppufile:tcompilerppufile);override;
  59. function dogetcopy : tnode;override;
  60. function pass_1 : tnode;override;
  61. function pass_typecheck:tnode;override;
  62. {$ifdef state_tracking}
  63. function track_state_pass(exec_known:boolean):boolean;override;
  64. {$endif state_tracking}
  65. function docompare(p: tnode): boolean; override;
  66. end;
  67. tassignmentnodeclass = class of tassignmentnode;
  68. tarrayconstructorrangenode = class(tbinarynode)
  69. constructor create(l,r : tnode);virtual;
  70. function pass_1 : tnode;override;
  71. function pass_typecheck:tnode;override;
  72. end;
  73. tarrayconstructorrangenodeclass = class of tarrayconstructorrangenode;
  74. tarrayconstructornode = class(tbinarynode)
  75. constructor create(l,r : tnode);virtual;
  76. function dogetcopy : tnode;override;
  77. function pass_1 : tnode;override;
  78. function pass_typecheck:tnode;override;
  79. function docompare(p: tnode): boolean; override;
  80. procedure force_type(def:tdef);
  81. procedure insert_typeconvs;
  82. end;
  83. tarrayconstructornodeclass = class of tarrayconstructornode;
  84. ttypenode = class(tnode)
  85. allowed : boolean;
  86. typedef : tdef;
  87. typedefderef : tderef;
  88. constructor create(def:tdef);virtual;
  89. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  90. procedure ppuwrite(ppufile:tcompilerppufile);override;
  91. procedure buildderefimpl;override;
  92. procedure derefimpl;override;
  93. function pass_1 : tnode;override;
  94. function pass_typecheck:tnode;override;
  95. function dogetcopy : tnode;override;
  96. function docompare(p: tnode): boolean; override;
  97. end;
  98. ttypenodeclass = class of ttypenode;
  99. trttinode = class(tnode)
  100. l1,l2 : longint;
  101. rttitype : trttitype;
  102. rttidef : tstoreddef;
  103. rttidefderef : tderef;
  104. constructor create(def:tstoreddef;rt:trttitype);virtual;
  105. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  106. procedure ppuwrite(ppufile:tcompilerppufile);override;
  107. procedure buildderefimpl;override;
  108. procedure derefimpl;override;
  109. function dogetcopy : tnode;override;
  110. function pass_1 : tnode;override;
  111. function pass_typecheck:tnode;override;
  112. function docompare(p: tnode): boolean; override;
  113. end;
  114. trttinodeclass = class of trttinode;
  115. var
  116. cloadnode : tloadnodeclass;
  117. cassignmentnode : tassignmentnodeclass;
  118. carrayconstructorrangenode : tarrayconstructorrangenodeclass;
  119. carrayconstructornode : tarrayconstructornodeclass;
  120. ctypenode : ttypenodeclass;
  121. crttinode : trttinodeclass;
  122. { Current assignment node }
  123. aktassignmentnode : tassignmentnode;
  124. implementation
  125. uses
  126. cutils,verbose,globtype,globals,systems,
  127. symnot,
  128. defutil,defcmp,
  129. htypechk,pass_1,procinfo,paramgr,
  130. ncon,ninl,ncnv,nmem,ncal,nutils,nbas,
  131. cgobj,cgbase
  132. ;
  133. {*****************************************************************************
  134. TLOADNODE
  135. *****************************************************************************}
  136. constructor tloadnode.create(v : tsym;st : TSymtable);
  137. begin
  138. inherited create(loadn,nil);
  139. if not assigned(v) then
  140. internalerror(200108121);
  141. symtableentry:=v;
  142. symtable:=st;
  143. procdef:=nil;
  144. end;
  145. constructor tloadnode.create_procvar(v : tsym;d:tprocdef;st : TSymtable);
  146. begin
  147. inherited create(loadn,nil);
  148. if not assigned(v) then
  149. internalerror(200108121);
  150. symtableentry:=v;
  151. symtable:=st;
  152. procdef:=d;
  153. end;
  154. constructor tloadnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  155. begin
  156. inherited ppuload(t,ppufile);
  157. ppufile.getderef(symtableentryderef);
  158. symtable:=nil;
  159. ppufile.getderef(procdefderef);
  160. end;
  161. procedure tloadnode.ppuwrite(ppufile:tcompilerppufile);
  162. begin
  163. inherited ppuwrite(ppufile);
  164. ppufile.putderef(symtableentryderef);
  165. ppufile.putderef(procdefderef);
  166. end;
  167. procedure tloadnode.buildderefimpl;
  168. begin
  169. inherited buildderefimpl;
  170. symtableentryderef.build(symtableentry);
  171. procdefderef.build(procdef);
  172. end;
  173. procedure tloadnode.derefimpl;
  174. begin
  175. inherited derefimpl;
  176. symtableentry:=tsym(symtableentryderef.resolve);
  177. symtable:=symtableentry.owner;
  178. procdef:=tprocdef(procdefderef.resolve);
  179. end;
  180. procedure tloadnode.set_mp(p:tnode);
  181. begin
  182. { typen nodes should not be set }
  183. if p.nodetype=typen then
  184. internalerror(200301042);
  185. left:=p;
  186. end;
  187. function tloadnode.dogetcopy : tnode;
  188. var
  189. n : tloadnode;
  190. begin
  191. n:=tloadnode(inherited dogetcopy);
  192. n.symtable:=symtable;
  193. n.symtableentry:=symtableentry;
  194. n.procdef:=procdef;
  195. result:=n;
  196. end;
  197. function tloadnode.is_addr_param_load:boolean;
  198. begin
  199. result:=(symtable.symtabletype=parasymtable) and
  200. (symtableentry.typ=paravarsym) and
  201. not(vo_has_local_copy in tparavarsym(symtableentry).varoptions) and
  202. not(nf_load_self_pointer in flags) and
  203. paramanager.push_addr_param(tparavarsym(symtableentry).varspez,tparavarsym(symtableentry).vardef,tprocdef(symtable.defowner).proccalloption);
  204. end;
  205. function tloadnode.pass_typecheck:tnode;
  206. begin
  207. result:=nil;
  208. case symtableentry.typ of
  209. absolutevarsym :
  210. resultdef:=tabsolutevarsym(symtableentry).vardef;
  211. constsym:
  212. begin
  213. if tconstsym(symtableentry).consttyp=constresourcestring then
  214. resultdef:=cansistringtype
  215. else
  216. internalerror(22799);
  217. end;
  218. staticvarsym :
  219. begin
  220. tabstractvarsym(symtableentry).IncRefCountBy(1);
  221. { static variables referenced in procedures or from finalization,
  222. variable needs to be in memory.
  223. It is too hard and the benefit is too small to detect whether a
  224. variable is only used in the finalization to add support for it (PFV) }
  225. if assigned(current_procinfo) and
  226. (symtable.symtabletype=staticsymtable) and
  227. (
  228. (symtable.symtablelevel<>current_procinfo.procdef.localst.symtablelevel) or
  229. (current_procinfo.procdef.proctypeoption=potype_unitfinalize)
  230. ) then
  231. make_not_regable(self,vr_none);
  232. resultdef:=tabstractvarsym(symtableentry).vardef;
  233. end;
  234. paravarsym,
  235. localvarsym :
  236. begin
  237. tabstractvarsym(symtableentry).IncRefCountBy(1);
  238. { Nested variable? The we need to load the framepointer of
  239. the parent procedure }
  240. if assigned(current_procinfo) and
  241. (symtable.symtabletype in [localsymtable,parasymtable]) and
  242. (symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel) then
  243. begin
  244. if assigned(left) then
  245. internalerror(200309289);
  246. left:=cloadparentfpnode.create(tprocdef(symtable.defowner));
  247. { we can't inline the referenced parent procedure }
  248. exclude(tprocdef(symtable.defowner).procoptions,po_inline);
  249. { reference in nested procedures, variable needs to be in memory }
  250. make_not_regable(self,vr_none);
  251. end;
  252. { fix self type which is declared as voidpointer in the
  253. definition }
  254. if vo_is_self in tabstractvarsym(symtableentry).varoptions then
  255. begin
  256. resultdef:=tprocdef(symtableentry.owner.defowner)._class;
  257. if (po_classmethod in tprocdef(symtableentry.owner.defowner).procoptions) or
  258. (po_staticmethod in tprocdef(symtableentry.owner.defowner).procoptions) then
  259. resultdef:=tclassrefdef.create(resultdef)
  260. else if is_object(resultdef) and
  261. (nf_load_self_pointer in flags) then
  262. resultdef:=tpointerdef.create(resultdef);
  263. end
  264. else if vo_is_vmt in tabstractvarsym(symtableentry).varoptions then
  265. begin
  266. resultdef:=tprocdef(symtableentry.owner.defowner)._class;
  267. resultdef:=tclassrefdef.create(resultdef);
  268. end
  269. else
  270. resultdef:=tabstractvarsym(symtableentry).vardef;
  271. end;
  272. procsym :
  273. begin
  274. { Return the first procdef. In case of overlaoded
  275. procdefs the matching procdef will be choosen
  276. when the expected procvardef is known, see get_information
  277. in htypechk.pas (PFV) }
  278. if not assigned(procdef) then
  279. procdef:=tprocdef(tprocsym(symtableentry).ProcdefList[0])
  280. else if po_kylixlocal in procdef.procoptions then
  281. CGMessage(type_e_cant_take_address_of_local_subroutine);
  282. { the result is a procdef, addrn and proc_to_procvar
  283. typeconvn need this as resultdef so they know
  284. that the address needs to be returned }
  285. resultdef:=procdef;
  286. { process methodpointer }
  287. if assigned(left) then
  288. typecheckpass(left);
  289. end;
  290. labelsym:
  291. resultdef:=voidtype;
  292. else
  293. internalerror(200104141);
  294. end;
  295. end;
  296. procedure Tloadnode.mark_write;
  297. begin
  298. include(flags,nf_write);
  299. end;
  300. function tloadnode.pass_1 : tnode;
  301. begin
  302. result:=nil;
  303. expectloc:=LOC_REFERENCE;
  304. registersint:=0;
  305. registersfpu:=0;
  306. {$ifdef SUPPORT_MMX}
  307. registersmmx:=0;
  308. {$endif SUPPORT_MMX}
  309. if (cs_create_pic in current_settings.moduleswitches) and
  310. not(symtableentry.typ in [paravarsym,localvarsym]) then
  311. include(current_procinfo.flags,pi_needs_got);
  312. case symtableentry.typ of
  313. absolutevarsym :
  314. ;
  315. constsym:
  316. begin
  317. if tconstsym(symtableentry).consttyp=constresourcestring then
  318. expectloc:=LOC_CREFERENCE;
  319. end;
  320. staticvarsym,
  321. localvarsym,
  322. paravarsym :
  323. begin
  324. if assigned(left) then
  325. firstpass(left);
  326. if not is_addr_param_load and
  327. tabstractvarsym(symtableentry).is_regvar(is_addr_param_load) then
  328. expectloc:=tvarregable2tcgloc[tabstractvarsym(symtableentry).varregable]
  329. else
  330. if (tabstractvarsym(symtableentry).varspez=vs_const) then
  331. expectloc:=LOC_CREFERENCE;
  332. { we need a register for call by reference parameters }
  333. if paramanager.push_addr_param(tabstractvarsym(symtableentry).varspez,tabstractvarsym(symtableentry).vardef,pocall_default) then
  334. registersint:=1;
  335. if ([vo_is_thread_var,vo_is_dll_var]*tabstractvarsym(symtableentry).varoptions)<>[] then
  336. registersint:=1;
  337. if (target_info.system=system_powerpc_darwin) and
  338. ([vo_is_dll_var,vo_is_external] * tabstractvarsym(symtableentry).varoptions <> []) then
  339. include(current_procinfo.flags,pi_needs_got);
  340. { call to get address of threadvar }
  341. if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
  342. include(current_procinfo.flags,pi_do_call);
  343. if nf_write in flags then
  344. Tabstractvarsym(symtableentry).trigger_notifications(vn_onwrite)
  345. else
  346. Tabstractvarsym(symtableentry).trigger_notifications(vn_onread);
  347. { count variable references }
  348. if cg.t_times>1 then
  349. tabstractvarsym(symtableentry).IncRefCountBy(cg.t_times-1);
  350. end;
  351. procsym :
  352. begin
  353. { method pointer ? }
  354. if assigned(left) then
  355. begin
  356. expectloc:=LOC_CREFERENCE;
  357. firstpass(left);
  358. registersint:=max(registersint,left.registersint);
  359. registersfpu:=max(registersfpu,left.registersfpu);
  360. {$ifdef SUPPORT_MMX}
  361. registersmmx:=max(registersmmx,left.registersmmx);
  362. {$endif SUPPORT_MMX}
  363. end;
  364. end;
  365. labelsym :
  366. ;
  367. else
  368. internalerror(200104143);
  369. end;
  370. end;
  371. function tloadnode.docompare(p: tnode): boolean;
  372. begin
  373. docompare :=
  374. inherited docompare(p) and
  375. (symtableentry = tloadnode(p).symtableentry) and
  376. (procdef = tloadnode(p).procdef) and
  377. (symtable = tloadnode(p).symtable);
  378. end;
  379. procedure tloadnode.printnodedata(var t:text);
  380. begin
  381. inherited printnodedata(t);
  382. write(t,printnodeindention,'symbol = ',symtableentry.name);
  383. if symtableentry.typ=procsym then
  384. write(t,printnodeindention,'procdef = ',procdef.mangledname);
  385. writeln(t,'');
  386. end;
  387. procedure tloadnode.setprocdef(p : tprocdef);
  388. begin
  389. procdef:=p;
  390. resultdef:=p;
  391. if po_local in p.procoptions then
  392. CGMessage(type_e_cant_take_address_of_local_subroutine);
  393. end;
  394. {*****************************************************************************
  395. TASSIGNMENTNODE
  396. *****************************************************************************}
  397. constructor tassignmentnode.create(l,r : tnode);
  398. begin
  399. inherited create(assignn,l,r);
  400. l.mark_write;
  401. assigntype:=at_normal;
  402. end;
  403. constructor tassignmentnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  404. begin
  405. inherited ppuload(t,ppufile);
  406. assigntype:=tassigntype(ppufile.getbyte);
  407. end;
  408. procedure tassignmentnode.ppuwrite(ppufile:tcompilerppufile);
  409. begin
  410. inherited ppuwrite(ppufile);
  411. ppufile.putbyte(byte(assigntype));
  412. end;
  413. function tassignmentnode.dogetcopy : tnode;
  414. var
  415. n : tassignmentnode;
  416. begin
  417. n:=tassignmentnode(inherited dogetcopy);
  418. n.assigntype:=assigntype;
  419. result:=n;
  420. end;
  421. function tassignmentnode.pass_typecheck:tnode;
  422. var
  423. hp : tnode;
  424. useshelper : boolean;
  425. begin
  426. result:=nil;
  427. resultdef:=voidtype;
  428. { must be made unique }
  429. set_unique(left);
  430. typecheckpass(left);
  431. typecheckpass(right);
  432. set_varstate(right,vs_read,[vsf_must_be_valid]);
  433. set_varstate(left,vs_written,[]);
  434. if codegenerror then
  435. exit;
  436. { tp procvar support, when we don't expect a procvar
  437. then we need to call the procvar }
  438. if (left.resultdef.typ<>procvardef) then
  439. maybe_call_procvar(right,true);
  440. { assignments to formaldefs and open arrays aren't allowed }
  441. if (left.resultdef.typ=formaldef) or
  442. is_open_array(left.resultdef) then
  443. CGMessage(type_e_assignment_not_allowed);
  444. { test if node can be assigned, properties are allowed }
  445. valid_for_assignment(left,true);
  446. { assigning nil to a dynamic array clears the array }
  447. if is_dynamic_array(left.resultdef) and
  448. (right.nodetype=niln) then
  449. begin
  450. hp:=ccallparanode.create(caddrnode.create_internal
  451. (crttinode.create(tstoreddef(left.resultdef),initrtti)),
  452. ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil));
  453. result := ccallnode.createintern('fpc_dynarray_clear',hp);
  454. left:=nil;
  455. exit;
  456. end;
  457. { shortstring helpers can do the conversion directly,
  458. so treat them separatly }
  459. if (is_shortstring(left.resultdef)) then
  460. begin
  461. { insert typeconv, except for chars that are handled in
  462. secondpass and except for ansi/wide string that can
  463. be converted immediatly }
  464. if not(is_char(right.resultdef) or
  465. (right.resultdef.typ=stringdef)) then
  466. inserttypeconv(right,left.resultdef);
  467. if right.resultdef.typ=stringdef then
  468. begin
  469. useshelper:=true;
  470. { convert constant strings to shortstrings. But
  471. skip empty constant strings, that will be handled
  472. in secondpass }
  473. if (right.nodetype=stringconstn) then
  474. begin
  475. { verify if range fits within shortstring }
  476. { just emit a warning, delphi gives an }
  477. { error, only if the type definition of }
  478. { of the string is less < 255 characters }
  479. if not is_open_string(left.resultdef) and
  480. (tstringconstnode(right).len > tstringdef(left.resultdef).len) then
  481. cgmessage(type_w_string_too_long);
  482. inserttypeconv(right,left.resultdef);
  483. if (right.nodetype=stringconstn) and
  484. (tstringconstnode(right).len=0) then
  485. useshelper:=false;
  486. end;
  487. { rest is done in pass 1 (JM) }
  488. if useshelper then
  489. exit;
  490. end
  491. end
  492. else
  493. begin
  494. { check if the assignment may cause a range check error }
  495. check_ranges(fileinfo,right,left.resultdef);
  496. inserttypeconv(right,left.resultdef);
  497. end;
  498. { call helpers for interface }
  499. if is_interfacecom(left.resultdef) then
  500. begin
  501. { Normal interface assignments are handled by the generic refcount incr/decr }
  502. if not right.resultdef.is_related(left.resultdef) then
  503. begin
  504. { remove property flag to avoid errors, see comments for }
  505. { tf_winlikewidestring assignments below }
  506. exclude(left.flags,nf_isproperty);
  507. hp:=
  508. ccallparanode.create(
  509. cguidconstnode.create(tobjectdef(left.resultdef).iidguid^),
  510. ccallparanode.create(
  511. ctypeconvnode.create_internal(right,voidpointertype),
  512. ccallparanode.create(
  513. ctypeconvnode.create_internal(left,voidpointertype),
  514. nil)));
  515. result:=ccallnode.createintern('fpc_intf_assign_by_iid',hp);
  516. left:=nil;
  517. right:=nil;
  518. exit;
  519. end;
  520. end
  521. { call helpers for variant, they can contain non ref. counted types like
  522. vararrays which must be really copied }
  523. else if left.resultdef.typ=variantdef then
  524. begin
  525. hp:=ccallparanode.create(ctypeconvnode.create_internal(
  526. caddrnode.create_internal(right),voidpointertype),
  527. ccallparanode.create(ctypeconvnode.create_internal(
  528. caddrnode.create_internal(left),voidpointertype),
  529. nil));
  530. result:=ccallnode.createintern('fpc_variant_copy',hp);
  531. left:=nil;
  532. right:=nil;
  533. exit;
  534. end
  535. { call helpers for composite types containing automated types }
  536. else if (left.resultdef.needs_inittable) and
  537. (left.resultdef.typ in [arraydef,objectdef,recorddef]) then
  538. begin
  539. hp:=ccallparanode.create(caddrnode.create_internal(
  540. crttinode.create(tstoreddef(left.resultdef),initrtti)),
  541. ccallparanode.create(ctypeconvnode.create_internal(
  542. caddrnode.create_internal(left),voidpointertype),
  543. ccallparanode.create(ctypeconvnode.create_internal(
  544. caddrnode.create_internal(right),voidpointertype),
  545. nil)));
  546. result:=ccallnode.createintern('fpc_copy',hp);
  547. left:=nil;
  548. right:=nil;
  549. exit;
  550. end
  551. { call helpers for windows widestrings, they aren't ref. counted }
  552. else if (tf_winlikewidestring in target_info.flags) and is_widestring(left.resultdef) then
  553. begin
  554. hp:=ccallparanode.create(ctypeconvnode.create_internal(right,voidpointertype),
  555. ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),
  556. nil));
  557. result:=ccallnode.createintern('fpc_widestr_assign',hp);
  558. left:=nil;
  559. right:=nil;
  560. exit;
  561. end;
  562. { check if local proc/func is assigned to procvar }
  563. if right.resultdef.typ=procvardef then
  564. test_local_to_procvar(tprocvardef(right.resultdef),left.resultdef);
  565. end;
  566. function tassignmentnode.pass_1 : tnode;
  567. var
  568. hp: tnode;
  569. oldassignmentnode : tassignmentnode;
  570. begin
  571. result:=nil;
  572. expectloc:=LOC_VOID;
  573. firstpass(left);
  574. { Optimize the reuse of the destination of the assingment in left.
  575. Allow the use of the left inside the tree generated on the right.
  576. This is especially usefull for string routines where the destination
  577. is pushed as a parameter. Using the final destination of left directly
  578. save a temp allocation and copy of data (PFV) }
  579. oldassignmentnode:=aktassignmentnode;
  580. if right.nodetype=addn then
  581. aktassignmentnode:=self
  582. else
  583. aktassignmentnode:=nil;
  584. firstpass(right);
  585. aktassignmentnode:=oldassignmentnode;
  586. if nf_assign_done_in_right in flags then
  587. begin
  588. result:=right;
  589. right:=nil;
  590. exit;
  591. end;
  592. if codegenerror then
  593. exit;
  594. if (cs_opt_level1 in current_settings.optimizerswitches) and
  595. (right.nodetype = calln) and
  596. (right.resultdef=left.resultdef) and
  597. { left must be a temp, since otherwise as soon as you modify the }
  598. { result, the current left node is modified and that one may }
  599. { still be an argument to the function or even accessed in the }
  600. { function }
  601. (
  602. (
  603. (left.nodetype = temprefn) and
  604. paramanager.ret_in_param(right.resultdef,tcallnode(right).procdefinition.proccalloption)
  605. ) or
  606. { there's special support for ansi/widestrings in the callnode }
  607. is_ansistring(right.resultdef) or
  608. is_widestring(right.resultdef)
  609. ) then
  610. begin
  611. make_not_regable(left,vr_addr);
  612. tcallnode(right).funcretnode := left;
  613. result := right;
  614. left := nil;
  615. right := nil;
  616. exit;
  617. end;
  618. { assignment to refcounted variable -> inc/decref }
  619. if (not is_class(left.resultdef) and
  620. left.resultdef.needs_inittable) then
  621. include(current_procinfo.flags,pi_do_call);
  622. if (is_shortstring(left.resultdef)) then
  623. begin
  624. if right.resultdef.typ=stringdef then
  625. begin
  626. if (right.nodetype<>stringconstn) or
  627. (tstringconstnode(right).len<>0) then
  628. begin
  629. hp:=ccallparanode.create
  630. (right,
  631. ccallparanode.create(cinlinenode.create
  632. (in_high_x,false,left.getcopy),nil));
  633. result:=ccallnode.createinternreturn('fpc_'+tstringdef(right.resultdef).stringtypname+'_to_shortstr',hp,left);
  634. firstpass(result);
  635. left:=nil;
  636. right:=nil;
  637. exit;
  638. end;
  639. end;
  640. end;
  641. registersint:=left.registersint+right.registersint;
  642. registersfpu:=max(left.registersfpu,right.registersfpu);
  643. {$ifdef SUPPORT_MMX}
  644. registersmmx:=max(left.registersmmx,right.registersmmx);
  645. {$endif SUPPORT_MMX}
  646. end;
  647. function tassignmentnode.docompare(p: tnode): boolean;
  648. begin
  649. docompare :=
  650. inherited docompare(p) and
  651. (assigntype = tassignmentnode(p).assigntype);
  652. end;
  653. {$ifdef state_tracking}
  654. function Tassignmentnode.track_state_pass(exec_known:boolean):boolean;
  655. var se:Tstate_entry;
  656. begin
  657. track_state_pass:=false;
  658. if exec_known then
  659. begin
  660. track_state_pass:=right.track_state_pass(exec_known);
  661. {Force a new resultdef pass.}
  662. right.resultdef:=nil;
  663. do_typecheckpass(right);
  664. typecheckpass(right);
  665. aktstate.store_fact(left.getcopy,right.getcopy);
  666. end
  667. else
  668. aktstate.delete_fact(left);
  669. end;
  670. {$endif}
  671. {*****************************************************************************
  672. TARRAYCONSTRUCTORRANGENODE
  673. *****************************************************************************}
  674. constructor tarrayconstructorrangenode.create(l,r : tnode);
  675. begin
  676. inherited create(arrayconstructorrangen,l,r);
  677. end;
  678. function tarrayconstructorrangenode.pass_typecheck:tnode;
  679. begin
  680. result:=nil;
  681. typecheckpass(left);
  682. typecheckpass(right);
  683. set_varstate(left,vs_read,[vsf_must_be_valid]);
  684. set_varstate(right,vs_read,[vsf_must_be_valid]);
  685. if codegenerror then
  686. exit;
  687. resultdef:=left.resultdef;
  688. end;
  689. function tarrayconstructorrangenode.pass_1 : tnode;
  690. begin
  691. firstpass(left);
  692. firstpass(right);
  693. expectloc:=LOC_CREFERENCE;
  694. calcregisters(self,0,0,0);
  695. result:=nil;
  696. end;
  697. {****************************************************************************
  698. TARRAYCONSTRUCTORNODE
  699. *****************************************************************************}
  700. constructor tarrayconstructornode.create(l,r : tnode);
  701. begin
  702. inherited create(arrayconstructorn,l,r);
  703. end;
  704. function tarrayconstructornode.dogetcopy : tnode;
  705. var
  706. n : tarrayconstructornode;
  707. begin
  708. n:=tarrayconstructornode(inherited dogetcopy);
  709. result:=n;
  710. end;
  711. function tarrayconstructornode.pass_typecheck:tnode;
  712. var
  713. hdef : tdef;
  714. hp : tarrayconstructornode;
  715. len : longint;
  716. varia : boolean;
  717. eq : tequaltype;
  718. hnodetype : tnodetype;
  719. begin
  720. result:=nil;
  721. { are we allowing array constructor? Then convert it to a set.
  722. Do this only if we didn't convert the arrayconstructor yet. This
  723. is needed for the cases where the resultdef is forced for a second
  724. run }
  725. if (not allow_array_constructor) then
  726. begin
  727. hp:=tarrayconstructornode(getcopy);
  728. arrayconstructor_to_set(tnode(hp));
  729. result:=hp;
  730. exit;
  731. end;
  732. { only pass left tree, right tree contains next construct if any }
  733. hdef:=nil;
  734. hnodetype:=errorn;
  735. len:=0;
  736. varia:=false;
  737. if assigned(left) then
  738. begin
  739. hp:=self;
  740. while assigned(hp) do
  741. begin
  742. typecheckpass(hp.left);
  743. set_varstate(hp.left,vs_read,[vsf_must_be_valid]);
  744. if (hdef=nil) then
  745. begin
  746. hdef:=hp.left.resultdef;
  747. hnodetype:=hp.left.nodetype;
  748. end
  749. else
  750. begin
  751. { If we got a niln we don't know the type yet and need to take the
  752. type of the next array element.
  753. This is to handle things like [nil,tclass,tclass], see also tw8371 (PFV) }
  754. if hnodetype=niln then
  755. begin
  756. eq:=compare_defs(hp.left.resultdef,hdef,hnodetype);
  757. if eq>te_incompatible then
  758. begin
  759. hdef:=hp.left.resultdef;
  760. hnodetype:=hp.left.nodetype;
  761. end;
  762. end
  763. else
  764. eq:=compare_defs(hdef,hp.left.resultdef,hp.left.nodetype);
  765. if (not varia) and (eq<te_equal) then
  766. begin
  767. { If both are integers we need to take the type that can hold both
  768. defs }
  769. if is_integer(hdef) and is_integer(hp.left.resultdef) then
  770. begin
  771. if is_in_limit(hdef,hp.left.resultdef) then
  772. hdef:=hp.left.resultdef;
  773. end
  774. else
  775. if (nf_novariaallowed in flags) then
  776. varia:=true;
  777. end;
  778. end;
  779. inc(len);
  780. hp:=tarrayconstructornode(hp.right);
  781. end;
  782. end;
  783. { Set the type of empty or varia arrays to void. Also
  784. do this if the type is array of const/open array
  785. because those can't be used with setelementdef }
  786. if not assigned(hdef) or
  787. varia or
  788. is_array_of_const(hdef) or
  789. is_open_array(hdef) then
  790. hdef:=voidtype;
  791. resultdef:=tarraydef.create(0,len-1,s32inttype);
  792. tarraydef(resultdef).elementdef:=hdef;
  793. include(tarraydef(resultdef).arrayoptions,ado_IsConstructor);
  794. if varia then
  795. include(tarraydef(resultdef).arrayoptions,ado_IsVariant);
  796. end;
  797. procedure tarrayconstructornode.force_type(def:tdef);
  798. var
  799. hp : tarrayconstructornode;
  800. begin
  801. tarraydef(resultdef).elementdef:=def;
  802. include(tarraydef(resultdef).arrayoptions,ado_IsConstructor);
  803. exclude(tarraydef(resultdef).arrayoptions,ado_IsVariant);
  804. if assigned(left) then
  805. begin
  806. hp:=self;
  807. while assigned(hp) do
  808. begin
  809. inserttypeconv(hp.left,def);
  810. hp:=tarrayconstructornode(hp.right);
  811. end;
  812. end;
  813. end;
  814. procedure tarrayconstructornode.insert_typeconvs;
  815. var
  816. hp : tarrayconstructornode;
  817. dovariant : boolean;
  818. begin
  819. dovariant:=(nf_forcevaria in flags) or (ado_isvariant in tarraydef(resultdef).arrayoptions);
  820. { only pass left tree, right tree contains next construct if any }
  821. if assigned(left) then
  822. begin
  823. hp:=self;
  824. while assigned(hp) do
  825. begin
  826. typecheckpass(hp.left);
  827. { Insert typeconvs for array of const }
  828. if dovariant then
  829. { at this time C varargs are no longer an arrayconstructornode }
  830. insert_varargstypeconv(hp.left,false);
  831. hp:=tarrayconstructornode(hp.right);
  832. end;
  833. end;
  834. end;
  835. function tarrayconstructornode.pass_1 : tnode;
  836. var
  837. hp : tarrayconstructornode;
  838. do_variant:boolean;
  839. begin
  840. do_variant:=(nf_forcevaria in flags) or (ado_isvariant in tarraydef(resultdef).arrayoptions);
  841. result:=nil;
  842. { Insert required type convs, this must be
  843. done in pass 1, because the call must be
  844. typecheckpassed already }
  845. if assigned(left) then
  846. begin
  847. insert_typeconvs;
  848. { call firstpass for all nodes }
  849. hp:=self;
  850. while assigned(hp) do
  851. begin
  852. if hp.left<>nil then
  853. begin
  854. {This check is pessimistic; a call will happen depending
  855. on the location in which the elements will be found in
  856. pass 2.}
  857. if not do_variant then
  858. include(current_procinfo.flags,pi_do_call);
  859. firstpass(hp.left);
  860. end;
  861. hp:=tarrayconstructornode(hp.right);
  862. end;
  863. end;
  864. expectloc:=LOC_CREFERENCE;
  865. calcregisters(self,0,0,0);
  866. end;
  867. function tarrayconstructornode.docompare(p: tnode): boolean;
  868. begin
  869. docompare:=inherited docompare(p);
  870. end;
  871. {*****************************************************************************
  872. TTYPENODE
  873. *****************************************************************************}
  874. constructor ttypenode.create(def:tdef);
  875. begin
  876. inherited create(typen);
  877. typedef:=def;
  878. allowed:=false;
  879. end;
  880. constructor ttypenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  881. begin
  882. inherited ppuload(t,ppufile);
  883. ppufile.getderef(typedefderef);
  884. allowed:=boolean(ppufile.getbyte);
  885. end;
  886. procedure ttypenode.ppuwrite(ppufile:tcompilerppufile);
  887. begin
  888. inherited ppuwrite(ppufile);
  889. ppufile.putderef(typedefderef);
  890. ppufile.putbyte(byte(allowed));
  891. end;
  892. procedure ttypenode.buildderefimpl;
  893. begin
  894. inherited buildderefimpl;
  895. typedefderef.build(typedef);
  896. end;
  897. procedure ttypenode.derefimpl;
  898. begin
  899. inherited derefimpl;
  900. typedef:=tdef(typedefderef.resolve);
  901. end;
  902. function ttypenode.pass_typecheck:tnode;
  903. begin
  904. result:=nil;
  905. resultdef:=typedef;
  906. { check if it's valid }
  907. if typedef.typ = errordef then
  908. CGMessage(parser_e_illegal_expression);
  909. end;
  910. function ttypenode.pass_1 : tnode;
  911. begin
  912. result:=nil;
  913. expectloc:=LOC_VOID;
  914. { a typenode can't generate code, so we give here
  915. an error. Else it'll be an abstract error in pass_generate_code.
  916. Only when the allowed flag is set we don't generate
  917. an error }
  918. if not allowed then
  919. Message(parser_e_no_type_not_allowed_here);
  920. end;
  921. function ttypenode.dogetcopy : tnode;
  922. var
  923. n : ttypenode;
  924. begin
  925. n:=ttypenode(inherited dogetcopy);
  926. n.allowed:=allowed;
  927. n.typedef:=typedef;
  928. result:=n;
  929. end;
  930. function ttypenode.docompare(p: tnode): boolean;
  931. begin
  932. docompare :=
  933. inherited docompare(p);
  934. end;
  935. {*****************************************************************************
  936. TRTTINODE
  937. *****************************************************************************}
  938. constructor trttinode.create(def:tstoreddef;rt:trttitype);
  939. begin
  940. inherited create(rttin);
  941. rttidef:=def;
  942. rttitype:=rt;
  943. end;
  944. constructor trttinode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  945. begin
  946. inherited ppuload(t,ppufile);
  947. ppufile.getderef(rttidefderef);
  948. rttitype:=trttitype(ppufile.getbyte);
  949. end;
  950. procedure trttinode.ppuwrite(ppufile:tcompilerppufile);
  951. begin
  952. inherited ppuwrite(ppufile);
  953. ppufile.putderef(rttidefderef);
  954. ppufile.putbyte(byte(rttitype));
  955. end;
  956. procedure trttinode.buildderefimpl;
  957. begin
  958. inherited buildderefimpl;
  959. rttidefderef.build(rttidef);
  960. end;
  961. procedure trttinode.derefimpl;
  962. begin
  963. inherited derefimpl;
  964. rttidef:=tstoreddef(rttidefderef.resolve);
  965. end;
  966. function trttinode.dogetcopy : tnode;
  967. var
  968. n : trttinode;
  969. begin
  970. n:=trttinode(inherited dogetcopy);
  971. n.rttidef:=rttidef;
  972. n.rttitype:=rttitype;
  973. result:=n;
  974. end;
  975. function trttinode.pass_typecheck:tnode;
  976. begin
  977. { rtti information will be returned as a void pointer }
  978. result:=nil;
  979. resultdef:=voidpointertype;
  980. end;
  981. function trttinode.pass_1 : tnode;
  982. begin
  983. result:=nil;
  984. expectloc:=LOC_CREFERENCE;
  985. end;
  986. function trttinode.docompare(p: tnode): boolean;
  987. begin
  988. docompare :=
  989. inherited docompare(p) and
  990. (rttidef = trttinode(p).rttidef) and
  991. (rttitype = trttinode(p).rttitype);
  992. end;
  993. begin
  994. cloadnode:=tloadnode;
  995. cassignmentnode:=tassignmentnode;
  996. carrayconstructorrangenode:=tarrayconstructorrangenode;
  997. carrayconstructornode:=tarrayconstructornode;
  998. ctypenode:=ttypenode;
  999. crttinode:=trttinode;
  1000. end.