nld.pas 39 KB

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