nmem.pas 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Type checking and register allocation for memory related 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 nmem;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. symdef,symsym,symtable,symtype;
  23. type
  24. tloadvmtaddrnode = class(tunarynode)
  25. { unless this is for a call, we have to send the "class" message to
  26. the objctype because the type information only gets initialized
  27. after the first message has been sent -> crash if you pass an
  28. uninitialized type to e.g. class_getInstanceSize() or so. No need
  29. to save to/restore from ppu. }
  30. forcall: boolean;
  31. constructor create(l : tnode);virtual;
  32. function pass_1 : tnode;override;
  33. function pass_typecheck:tnode;override;
  34. function docompare(p: tnode): boolean; override;
  35. function dogetcopy: tnode; override;
  36. end;
  37. tloadvmtaddrnodeclass = class of tloadvmtaddrnode;
  38. tloadparentfpkind = (
  39. { as parameter to a nested routine (current routine's frame) }
  40. lpf_forpara,
  41. { to load a local from a parent routine in the current nested routine
  42. (some parent routine's frame) }
  43. lpf_forload
  44. );
  45. tloadparentfpnode = class(tunarynode)
  46. parentpd : tprocdef;
  47. parentpdderef : tderef;
  48. kind: tloadparentfpkind;
  49. constructor create(pd: tprocdef; fpkind: tloadparentfpkind);virtual;
  50. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  51. procedure ppuwrite(ppufile:tcompilerppufile);override;
  52. procedure buildderefimpl;override;
  53. procedure derefimpl;override;
  54. function pass_1 : tnode;override;
  55. function pass_typecheck:tnode;override;
  56. function docompare(p: tnode): boolean; override;
  57. function dogetcopy : tnode;override;
  58. end;
  59. tloadparentfpnodeclass = class of tloadparentfpnode;
  60. taddrnodeflag = (
  61. { generated by the Ofs() internal function }
  62. anf_ofs,
  63. anf_typedaddr
  64. );
  65. taddrnodeflags = set of taddrnodeflag;
  66. taddrnode = class(tunarynode)
  67. getprocvardef : tprocvardef;
  68. getprocvardefderef : tderef;
  69. addrnodeflags : taddrnodeflags;
  70. constructor create(l : tnode);virtual;
  71. constructor create_internal(l : tnode); virtual;
  72. constructor create_internal_nomark(l : tnode); virtual;
  73. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  74. procedure ppuwrite(ppufile:tcompilerppufile);override;
  75. procedure mark_write;override;
  76. procedure buildderefimpl;override;
  77. procedure derefimpl;override;
  78. procedure printnodeinfo(var t: text); override;
  79. {$ifdef DEBUG_NODE_XML}
  80. procedure XMLPrintNodeInfo(var T: Text); override;
  81. {$endif DEBUG_NODE_XML}
  82. function docompare(p: tnode): boolean; override;
  83. function dogetcopy : tnode;override;
  84. function pass_1 : tnode;override;
  85. function pass_typecheck:tnode;override;
  86. function simplify(forinline : boolean) : tnode; override;
  87. protected
  88. mark_read_written: boolean;
  89. procedure set_labelsym_resultdef; virtual;
  90. function typecheck_non_proc(realsource: tnode; out res: tnode): boolean; virtual;
  91. end;
  92. taddrnodeclass = class of taddrnode;
  93. tderefnode = class(tunarynode)
  94. constructor create(l : tnode);virtual;
  95. function pass_1 : tnode;override;
  96. function pass_typecheck:tnode;override;
  97. procedure mark_write;override;
  98. end;
  99. tderefnodeclass = class of tderefnode;
  100. tsubscriptnode = class(tunarynode)
  101. vs : tfieldvarsym;
  102. vsderef : tderef;
  103. constructor create(varsym : tsym;l : tnode);virtual;
  104. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  105. procedure ppuwrite(ppufile:tcompilerppufile);override;
  106. procedure buildderefimpl;override;
  107. procedure derefimpl;override;
  108. function dogetcopy : tnode;override;
  109. function pass_1 : tnode;override;
  110. function docompare(p: tnode): boolean; override;
  111. function pass_typecheck:tnode;override;
  112. procedure mark_write;override;
  113. procedure printnodedata(var T: Text); override;
  114. {$ifdef DEBUG_NODE_XML}
  115. procedure XMLPrintNodeData(var T: Text); override;
  116. {$endif DEBUG_NODE_XML}
  117. end;
  118. tsubscriptnodeclass = class of tsubscriptnode;
  119. tvecnode = class(tbinarynode)
  120. protected
  121. function first_arraydef: tnode; virtual;
  122. function gen_array_rangecheck: tnode; virtual;
  123. public
  124. constructor create(l,r : tnode);virtual;
  125. function pass_1 : tnode;override;
  126. function pass_typecheck:tnode;override;
  127. function simplify(forinline : boolean) : tnode; override;
  128. procedure mark_write;override;
  129. {$ifdef DEBUG_NODE_XML}
  130. procedure XMLPrintNodeData(var T: Text); override;
  131. {$endif DEBUG_NODE_XML}
  132. end;
  133. tvecnodeclass = class of tvecnode;
  134. var
  135. cloadvmtaddrnode : tloadvmtaddrnodeclass= tloadvmtaddrnode;
  136. caddrnode : taddrnodeclass= taddrnode;
  137. cderefnode : tderefnodeclass= tderefnode;
  138. csubscriptnode : tsubscriptnodeclass= tsubscriptnode;
  139. cvecnode : tvecnodeclass= tvecnode;
  140. cloadparentfpnode : tloadparentfpnodeclass = tloadparentfpnode;
  141. function is_big_untyped_addrnode(p: tnode): boolean;
  142. implementation
  143. uses
  144. globtype,systems,constexp,
  145. cutils,verbose,globals,ppu,
  146. symconst,defutil,defcmp,
  147. nadd,nbas,nflw,nutils,objcutil,
  148. wpobase,
  149. {$ifdef i8086}
  150. cpuinfo,
  151. {$endif i8086}
  152. htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase,procinfo,widestr
  153. ;
  154. {*****************************************************************************
  155. TLOADVMTADDRNODE
  156. *****************************************************************************}
  157. constructor tloadvmtaddrnode.create(l : tnode);
  158. begin
  159. inherited create(loadvmtaddrn,l);
  160. end;
  161. function tloadvmtaddrnode.pass_typecheck:tnode;
  162. var
  163. defaultresultdef : boolean;
  164. begin
  165. result:=nil;
  166. typecheckpass(left);
  167. if codegenerror then
  168. exit;
  169. case left.resultdef.typ of
  170. classrefdef :
  171. resultdef:=left.resultdef;
  172. recorddef,
  173. objectdef:
  174. begin
  175. if (left.resultdef.typ=objectdef) or
  176. ((target_info.system in systems_jvm) and
  177. (left.resultdef.typ=recorddef)) then
  178. begin
  179. { access to the classtype while specializing? }
  180. if tstoreddef(left.resultdef).is_generic then
  181. begin
  182. defaultresultdef:=true;
  183. if assigned(current_structdef) then
  184. begin
  185. if assigned(current_structdef.genericdef) then
  186. if current_structdef.genericdef=left.resultdef then
  187. begin
  188. resultdef:=cclassrefdef.create(current_structdef);
  189. defaultresultdef:=false;
  190. end
  191. else
  192. CGMessage(parser_e_cant_create_generics_of_this_type);
  193. end
  194. else
  195. message(parser_e_cant_create_generics_of_this_type);
  196. if defaultresultdef then
  197. resultdef:=cclassrefdef.create(left.resultdef);
  198. end
  199. else
  200. resultdef:=cclassrefdef.create(left.resultdef);
  201. end
  202. else
  203. CGMessage(parser_e_pointer_to_class_expected);
  204. end
  205. else
  206. CGMessage(parser_e_pointer_to_class_expected);
  207. end;
  208. end;
  209. function tloadvmtaddrnode.docompare(p: tnode): boolean;
  210. begin
  211. result:=inherited docompare(p);
  212. if result then
  213. result:=forcall=tloadvmtaddrnode(p).forcall;
  214. end;
  215. function tloadvmtaddrnode.dogetcopy: tnode;
  216. begin
  217. result:=inherited dogetcopy;
  218. tloadvmtaddrnode(result).forcall:=forcall;
  219. end;
  220. function tloadvmtaddrnode.pass_1 : tnode;
  221. var
  222. vs: tsym;
  223. begin
  224. result:=nil;
  225. expectloc:=LOC_REGISTER;
  226. if left.nodetype<>typen then
  227. begin
  228. if (is_objc_class_or_protocol(left.resultdef) or
  229. is_objcclassref(left.resultdef)) then
  230. begin
  231. { on non-fragile ABI platforms, the ISA pointer may be opaque
  232. and we must call Object_getClass to obtain the real ISA
  233. pointer }
  234. if target_info.system in systems_objc_nfabi then
  235. begin
  236. result:=ccallnode.createinternfromunit('OBJC','OBJECT_GETCLASS',ccallparanode.create(left,nil));
  237. inserttypeconv_explicit(result,resultdef);
  238. end
  239. else
  240. result:=objcloadbasefield(left,'ISA');
  241. end
  242. else
  243. result:=ctypeconvnode.create_internal(load_vmt_for_self_node(left),resultdef);
  244. { reused }
  245. left:=nil;
  246. end
  247. else if not is_objcclass(left.resultdef) and
  248. not is_objcclassref(left.resultdef) then
  249. begin
  250. if not(nf_ignore_for_wpo in flags) and
  251. wpoinfomanager.symbol_live_in_currentproc(left.resultdef) then
  252. begin
  253. { keep track of which classes might be instantiated via a classrefdef }
  254. if (left.resultdef.typ=classrefdef) then
  255. tobjectdef(tclassrefdef(left.resultdef).pointeddef).register_maybe_created_object_type
  256. else if (left.resultdef.typ=objectdef) then
  257. tobjectdef(left.resultdef).register_maybe_created_object_type
  258. end
  259. end
  260. else if is_objcclass(left.resultdef) and
  261. not(forcall) then
  262. begin
  263. { call "class" method (= "classclass" in FPC), because otherwise
  264. we may use the class information before it has been
  265. initialized }
  266. vs:=search_struct_member(tobjectdef(left.resultdef),'CLASSCLASS');
  267. if not assigned(vs) or
  268. (vs.typ<>procsym) then
  269. internalerror(2011080601);
  270. { can't reuse "self", because it will be freed when we return }
  271. result:=ccallnode.create(nil,tprocsym(vs),vs.owner,self.getcopy,[],nil);
  272. end;
  273. end;
  274. {*****************************************************************************
  275. TLOADPARENTFPNODE
  276. *****************************************************************************}
  277. constructor tloadparentfpnode.create(pd: tprocdef; fpkind: tloadparentfpkind);
  278. begin
  279. inherited create(loadparentfpn,nil);
  280. if not assigned(pd) then
  281. internalerror(200309288);
  282. if (pd.parast.symtablelevel>current_procinfo.procdef.parast.symtablelevel) then
  283. internalerror(200309284);
  284. parentpd:=pd;
  285. kind:=fpkind;
  286. end;
  287. constructor tloadparentfpnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  288. begin
  289. inherited ppuload(t,ppufile);
  290. ppufile.getderef(parentpdderef);
  291. kind:=tloadparentfpkind(ppufile.getbyte);
  292. end;
  293. procedure tloadparentfpnode.ppuwrite(ppufile:tcompilerppufile);
  294. begin
  295. inherited ppuwrite(ppufile);
  296. ppufile.putderef(parentpdderef);
  297. ppufile.putbyte(byte(kind));
  298. end;
  299. procedure tloadparentfpnode.buildderefimpl;
  300. begin
  301. inherited buildderefimpl;
  302. parentpdderef.build(parentpd);
  303. end;
  304. procedure tloadparentfpnode.derefimpl;
  305. begin
  306. inherited derefimpl;
  307. parentpd:=tprocdef(parentpdderef.resolve);
  308. end;
  309. function tloadparentfpnode.docompare(p: tnode): boolean;
  310. begin
  311. result:=
  312. inherited docompare(p) and
  313. (tloadparentfpnode(p).parentpd=parentpd) and
  314. (tloadparentfpnode(p).kind=kind);
  315. end;
  316. function tloadparentfpnode.dogetcopy : tnode;
  317. var
  318. p : tloadparentfpnode;
  319. begin
  320. p:=tloadparentfpnode(inherited dogetcopy);
  321. p.parentpd:=parentpd;
  322. p.kind:=kind;
  323. dogetcopy:=p;
  324. end;
  325. function tloadparentfpnode.pass_typecheck:tnode;
  326. begin
  327. result:=nil;
  328. resultdef:=parentfpvoidpointertype;
  329. end;
  330. function tloadparentfpnode.pass_1 : tnode;
  331. begin
  332. result:=nil;
  333. expectloc:=LOC_REGISTER;
  334. end;
  335. {*****************************************************************************
  336. TADDRNODE
  337. *****************************************************************************}
  338. constructor taddrnode.create(l : tnode);
  339. begin
  340. inherited create(addrn,l);
  341. getprocvardef:=nil;
  342. addrnodeflags:=[];
  343. mark_read_written := true;
  344. end;
  345. constructor taddrnode.create_internal(l : tnode);
  346. begin
  347. self.create(l);
  348. include(flags,nf_internal);
  349. end;
  350. constructor taddrnode.create_internal_nomark(l : tnode);
  351. begin
  352. self.create_internal(l);
  353. mark_read_written := false;
  354. end;
  355. constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  356. begin
  357. inherited ppuload(t,ppufile);
  358. ppufile.getderef(getprocvardefderef);
  359. ppufile.getset(tppuset1(addrnodeflags));
  360. end;
  361. procedure taddrnode.ppuwrite(ppufile:tcompilerppufile);
  362. begin
  363. inherited ppuwrite(ppufile);
  364. ppufile.putderef(getprocvardefderef);
  365. ppufile.putset(tppuset1(addrnodeflags));
  366. end;
  367. procedure Taddrnode.mark_write;
  368. begin
  369. {@procvar:=nil is legal in Delphi mode.}
  370. left.mark_write;
  371. end;
  372. procedure taddrnode.buildderefimpl;
  373. begin
  374. inherited buildderefimpl;
  375. getprocvardefderef.build(getprocvardef);
  376. end;
  377. procedure taddrnode.derefimpl;
  378. begin
  379. inherited derefimpl;
  380. getprocvardef:=tprocvardef(getprocvardefderef.resolve);
  381. end;
  382. procedure taddrnode.printnodeinfo(var t: text);
  383. var
  384. first: Boolean;
  385. i: taddrnodeflag;
  386. begin
  387. inherited printnodeinfo(t);
  388. write(t,', addrnodeflags = [');
  389. first:=true;
  390. for i:=low(taddrnodeflag) to high(taddrnodeflag) do
  391. if i in addrnodeflags then
  392. begin
  393. if not first then
  394. write(t,',')
  395. else
  396. first:=false;
  397. write(t,i);
  398. end;
  399. write(t,']');
  400. end;
  401. {$ifdef DEBUG_NODE_XML}
  402. procedure TAddrNode.XMLPrintNodeInfo(var T: Text);
  403. var
  404. First: Boolean;
  405. i: TAddrNodeFlag;
  406. begin
  407. inherited XMLPrintNodeInfo(t);
  408. First := True;
  409. for i := Low(TAddrNodeFlag) to High(TAddrNodeFlag) do
  410. if i in addrnodeflags then
  411. begin
  412. if First then
  413. begin
  414. Write(T, ' addrnodeflags="', i);
  415. First := False;
  416. end
  417. else
  418. Write(T, ',', i);
  419. end;
  420. if not First then
  421. Write(T, '"');
  422. end;
  423. {$endif DEBUG_NODE_XML}
  424. function taddrnode.docompare(p: tnode): boolean;
  425. begin
  426. result:=
  427. inherited docompare(p) and
  428. (taddrnode(p).getprocvardef=getprocvardef) and
  429. (taddrnode(p).addrnodeflags=addrnodeflags);
  430. end;
  431. function taddrnode.dogetcopy : tnode;
  432. var
  433. p : taddrnode;
  434. begin
  435. p:=taddrnode(inherited dogetcopy);
  436. p.getprocvardef:=getprocvardef;
  437. p.addrnodeflags:=addrnodeflags;
  438. dogetcopy:=p;
  439. end;
  440. function taddrnode.pass_typecheck:tnode;
  441. procedure check_mark_read_written;
  442. begin
  443. if mark_read_written then
  444. begin
  445. { This is actually only "read", but treat it nevertheless as
  446. modified due to the possible use of pointers
  447. To avoid false positives regarding "uninitialised"
  448. warnings when using arrays, perform it in two steps }
  449. set_varstate(left,vs_written,[]);
  450. { vsf_must_be_valid so it doesn't get changed into
  451. vsf_referred_not_inited }
  452. set_varstate(left,vs_read,[vsf_must_be_valid]);
  453. end;
  454. end;
  455. var
  456. hp : tnode;
  457. hsym : tfieldvarsym;
  458. isprocvar,need_conv_to_voidptr: boolean;
  459. procpointertype: tdef;
  460. begin
  461. result:=nil;
  462. typecheckpass(left);
  463. if codegenerror then
  464. exit;
  465. make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
  466. { don't allow constants, for internal use we also
  467. allow taking the address of strings and sets }
  468. if is_constnode(left) and
  469. not(
  470. (nf_internal in flags) and
  471. (left.nodetype in [stringconstn,setconstn])
  472. ) then
  473. begin
  474. CGMessagePos(left.fileinfo,type_e_no_addr_of_constant);
  475. exit;
  476. end;
  477. { Handle @proc special, also @procvar in tp-mode needs
  478. special handling }
  479. if (left.resultdef.typ=procdef) or
  480. (
  481. { in case of nf_internal, follow the normal FPC semantics so that
  482. we can easily get the actual address of a procvar }
  483. not(nf_internal in flags) and
  484. (left.resultdef.typ=procvardef) and
  485. ((m_tp_procvar in current_settings.modeswitches) or
  486. (m_mac_procvar in current_settings.modeswitches))
  487. ) then
  488. begin
  489. isprocvar:=(left.resultdef.typ=procvardef);
  490. need_conv_to_voidptr:=
  491. (m_tp_procvar in current_settings.modeswitches) or
  492. (m_mac_procvar in current_settings.modeswitches);
  493. if not isprocvar then
  494. begin
  495. left:=ctypeconvnode.create_proc_to_procvar(left);
  496. if need_conv_to_voidptr then
  497. include(ttypeconvnode(left).convnodeflags,tcnf_proc_2_procvar_2_voidpointer);
  498. if anf_ofs in addrnodeflags then
  499. include(ttypeconvnode(left).convnodeflags,tcnf_proc_2_procvar_get_offset_only);
  500. left.fileinfo:=fileinfo;
  501. typecheckpass(left);
  502. end;
  503. { In tp procvar mode the result is always a voidpointer. Insert
  504. a typeconversion to voidpointer. For methodpointers we need
  505. to load the proc field }
  506. if need_conv_to_voidptr then
  507. begin
  508. if tabstractprocdef(left.resultdef).is_addressonly then
  509. begin
  510. if anf_ofs in addrnodeflags then
  511. result:=ctypeconvnode.create_internal(left,tabstractprocdef(left.resultdef).ofs_address_type)
  512. else
  513. result:=ctypeconvnode.create_internal(left,voidcodepointertype);
  514. include(result.flags,nf_load_procvar);
  515. left:=nil;
  516. end
  517. else
  518. begin
  519. { For procvars and for nested routines we need to return
  520. the proc field of the methodpointer }
  521. if isprocvar or
  522. is_nested_pd(tabstractprocdef(left.resultdef)) then
  523. begin
  524. if tabstractprocdef(left.resultdef).is_methodpointer then
  525. procpointertype:=methodpointertype
  526. else
  527. procpointertype:=nestedprocpointertype;
  528. { find proc field in methodpointer record }
  529. hsym:=tfieldvarsym(trecorddef(procpointertype).symtable.Find('proc'));
  530. if not assigned(hsym) then
  531. internalerror(200412041);
  532. { Load tmehodpointer(left).proc }
  533. result:=csubscriptnode.create(
  534. hsym,
  535. ctypeconvnode.create_internal(left,procpointertype));
  536. left:=nil;
  537. end
  538. else
  539. CGMessage(type_e_variable_id_expected);
  540. end;
  541. end
  542. else
  543. begin
  544. check_mark_read_written;
  545. { Return the typeconvn only }
  546. result:=left;
  547. left:=nil;
  548. exit;
  549. end;
  550. end
  551. else
  552. begin
  553. hp:=left;
  554. while assigned(hp) and (hp.nodetype in [typeconvn,derefn,subscriptn]) do
  555. hp:=tunarynode(hp).left;
  556. if not assigned(hp) then
  557. internalerror(200412042);
  558. if typecheck_non_proc(hp,result) then
  559. begin
  560. if assigned(result) then
  561. exit;
  562. end
  563. else
  564. CGMessage(type_e_variable_id_expected);
  565. end;
  566. check_mark_read_written;
  567. if not(assigned(result)) then
  568. result:=simplify(false);
  569. end;
  570. function taddrnode.simplify(forinline : boolean) : tnode;
  571. function compatible_with_offsetof(res : tdef) : boolean;
  572. begin
  573. result:=(res.typ in [recorddef,objectdef]) and not (is_implicit_pointer_object_type(res))
  574. or (res.typ=arraydef) and not (ado_IsDynamicArray in tarraydef(res).arrayoptions);
  575. end;
  576. var
  577. hsym : tfieldvarsym;
  578. hp : tnode;
  579. fieldoffset : asizeint;
  580. resdef : tdef;
  581. index : int64;
  582. begin
  583. result:=nil;
  584. hp:=left;
  585. fieldoffset:=0;
  586. { Attempt to turn
  587. @PSomeType(nil)^.field
  588. or
  589. @SomeType(nil^).fieldA.aryA[3].fieldB.aryB[5]
  590. into a compile-time constant, numerically equal to the offset of the target field in 'SomeType' (and usually cast to 'PtrUint' right away). }
  591. repeat
  592. case hp.nodetype of
  593. subscriptn:
  594. begin
  595. { Here and below, 'hp<>left' detects non-first iteration,
  596. as the first iteration handles deepest field whose type can be arbitrary: 'c' in @PType(nil)^.a.b.c. }
  597. if (hp<>left) and not compatible_with_offsetof(tsubscriptnode(hp).resultdef) then
  598. exit;
  599. hsym:=tsubscriptnode(hp).vs;
  600. if tabstractrecordsymtable(hsym.owner).is_packed then
  601. begin
  602. if hsym.fieldoffset mod 8<>0 then
  603. exit;
  604. inc(fieldoffset,hsym.fieldoffset div 8);
  605. end
  606. else
  607. inc(fieldoffset,hsym.fieldoffset);
  608. hp:=tsubscriptnode(hp).left;
  609. end;
  610. vecn:
  611. begin
  612. if (tvecnode(hp).right.nodetype<>ordconstn) or
  613. (hp<>left) and not compatible_with_offsetof(tvecnode(hp).resultdef) then
  614. exit;
  615. resdef:=tvecnode(hp).left.resultdef;
  616. if not ((resdef.typ=arraydef) and not (ado_IsDynamicArray in tarraydef(resdef).arrayoptions)) then
  617. exit;
  618. index:=tordconstnode(tvecnode(hp).right).value.svalue;
  619. if not ((index>=tarraydef(resdef).lowrange) and (index<=tarraydef(resdef).highrange)) then
  620. exit;
  621. index:=index-tarraydef(resdef).lowrange;
  622. if ado_IsBitPacked in tarraydef(resdef).arrayoptions then
  623. begin
  624. if index*tarraydef(resdef).elepackedbitsize mod 8<>0 then
  625. exit;
  626. inc(fieldoffset,index*tarraydef(resdef).elepackedbitsize div 8);
  627. end
  628. else
  629. inc(fieldoffset,index*tarraydef(resdef).elesize);
  630. hp:=tvecnode(hp).left;
  631. end;
  632. derefn:
  633. begin
  634. { @PObjectType(nil)^.fields? }
  635. if tderefnode(hp).left.nodetype=niln then
  636. result:=cpointerconstnode.create(fieldoffset,resultdef);
  637. exit;
  638. end;
  639. typeconvn:
  640. begin
  641. { @ObjectType(nil^).fields? }
  642. if (ttypeconvnode(hp).left.nodetype=derefn) and
  643. (tderefnode(ttypeconvnode(hp).left).left.nodetype=niln) then
  644. result:=cpointerconstnode.create(fieldoffset,resultdef);
  645. exit;
  646. end;
  647. niln:
  648. { @ClassType(nil).fields. }
  649. exit(cpointerconstnode.create(fieldoffset,resultdef));
  650. else
  651. exit;
  652. end;
  653. until false;
  654. end;
  655. procedure taddrnode.set_labelsym_resultdef;
  656. begin
  657. resultdef:=voidcodepointertype;
  658. end;
  659. function taddrnode.typecheck_non_proc(realsource: tnode; out res: tnode): boolean;
  660. var
  661. hp : tnode;
  662. hsym : tfieldvarsym;
  663. offset: asizeint;
  664. begin
  665. result:=false;
  666. res:=nil;
  667. if (realsource.nodetype=loadn) and
  668. (tloadnode(realsource).symtableentry.typ=labelsym) then
  669. begin
  670. set_labelsym_resultdef;
  671. result:=true;
  672. end
  673. else if (realsource.nodetype=loadn) and
  674. (tloadnode(realsource).symtableentry.typ=absolutevarsym) and
  675. (tabsolutevarsym(tloadnode(realsource).symtableentry).abstyp=toaddr) then
  676. begin
  677. offset:=tabsolutevarsym(tloadnode(realsource).symtableentry).addroffset;
  678. hp:=left;
  679. while assigned(hp)and(hp.nodetype=subscriptn) do
  680. begin
  681. hsym:=tsubscriptnode(hp).vs;
  682. if tabstractrecordsymtable(hsym.owner).is_packed then
  683. begin
  684. { can't calculate the address of a non-byte aligned field }
  685. if (hsym.fieldoffset mod 8)<>0 then
  686. begin
  687. CGMessagePos(hp.fileinfo,parser_e_packed_element_no_var_addr);
  688. exit
  689. end;
  690. inc(offset,hsym.fieldoffset div 8)
  691. end
  692. else
  693. inc(offset,hsym.fieldoffset);
  694. hp:=tunarynode(hp).left;
  695. end;
  696. if anf_typedaddr in addrnodeflags then
  697. res:=cpointerconstnode.create(offset,cpointerdef.getreusable(left.resultdef))
  698. else
  699. res:=cpointerconstnode.create(offset,voidpointertype);
  700. result:=true;
  701. end
  702. else if (nf_internal in flags) or
  703. valid_for_addr(left,true) then
  704. begin
  705. if not(anf_typedaddr in addrnodeflags) then
  706. resultdef:=voidpointertype
  707. else
  708. resultdef:=cpointerdef.getreusable(left.resultdef);
  709. result:=true;
  710. end
  711. end;
  712. function taddrnode.pass_1 : tnode;
  713. begin
  714. result:=nil;
  715. firstpass(left);
  716. if codegenerror then
  717. exit;
  718. { is this right for object of methods ?? }
  719. expectloc:=LOC_REGISTER;
  720. end;
  721. {*****************************************************************************
  722. TDEREFNODE
  723. *****************************************************************************}
  724. constructor tderefnode.create(l : tnode);
  725. begin
  726. inherited create(derefn,l);
  727. end;
  728. function tderefnode.pass_typecheck:tnode;
  729. begin
  730. result:=nil;
  731. typecheckpass(left);
  732. set_varstate(left,vs_read,[vsf_must_be_valid]);
  733. if codegenerror then
  734. exit;
  735. { tp procvar support }
  736. maybe_call_procvar(left,true);
  737. if left.resultdef.typ=pointerdef then
  738. resultdef:=tpointerdef(left.resultdef).pointeddef
  739. else if left.resultdef.typ=undefineddef then
  740. resultdef:=cundefineddef.create(true)
  741. else
  742. CGMessage(parser_e_invalid_qualifier);
  743. end;
  744. procedure Tderefnode.mark_write;
  745. begin
  746. include(flags,nf_write);
  747. end;
  748. function tderefnode.pass_1 : tnode;
  749. begin
  750. result:=nil;
  751. firstpass(left);
  752. if codegenerror then
  753. exit;
  754. expectloc:=LOC_REFERENCE;
  755. end;
  756. {*****************************************************************************
  757. TSUBSCRIPTNODE
  758. *****************************************************************************}
  759. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  760. begin
  761. inherited create(subscriptn,l);
  762. { vs should be changed to tsym! }
  763. vs:=tfieldvarsym(varsym);
  764. end;
  765. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  766. begin
  767. inherited ppuload(t,ppufile);
  768. ppufile.getderef(vsderef);
  769. end;
  770. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  771. begin
  772. inherited ppuwrite(ppufile);
  773. ppufile.putderef(vsderef);
  774. end;
  775. procedure tsubscriptnode.buildderefimpl;
  776. begin
  777. inherited buildderefimpl;
  778. vsderef.build(vs);
  779. end;
  780. procedure tsubscriptnode.derefimpl;
  781. begin
  782. inherited derefimpl;
  783. vs:=tfieldvarsym(vsderef.resolve);
  784. end;
  785. function tsubscriptnode.dogetcopy : tnode;
  786. var
  787. p : tsubscriptnode;
  788. begin
  789. p:=tsubscriptnode(inherited dogetcopy);
  790. p.vs:=vs;
  791. dogetcopy:=p;
  792. end;
  793. function tsubscriptnode.pass_typecheck:tnode;
  794. begin
  795. result:=nil;
  796. typecheckpass(left);
  797. { tp procvar support }
  798. maybe_call_procvar(left,true);
  799. resultdef:=vs.vardef;
  800. // don't put records from which we load float fields
  801. // in integer registers
  802. if (left.resultdef.typ=recorddef) and
  803. (resultdef.typ=floatdef) then
  804. make_not_regable(left,[ra_addr_regable]);
  805. end;
  806. procedure Tsubscriptnode.mark_write;
  807. begin
  808. include(flags,nf_write);
  809. { if an element of a record is written, then the whole record is changed/it is written to it,
  810. for data types being implicit pointers this does not apply as the object itself does not change }
  811. if not(is_implicit_pointer_object_type(left.resultdef)) then
  812. left.mark_write;
  813. end;
  814. function tsubscriptnode.pass_1 : tnode;
  815. begin
  816. result:=nil;
  817. firstpass(left);
  818. if codegenerror then
  819. exit;
  820. { several object types must be dereferenced implicitly }
  821. if is_implicit_pointer_object_type(left.resultdef) then
  822. expectloc:=LOC_REFERENCE
  823. else
  824. begin
  825. case left.expectloc of
  826. { if a floating point value is casted into a record, it
  827. can happen that we get here an fpu or mm register }
  828. LOC_CMMREGISTER,
  829. LOC_CFPUREGISTER,
  830. LOC_MMREGISTER,
  831. LOC_FPUREGISTER,
  832. LOC_CONSTANT,
  833. LOC_REGISTER,
  834. LOC_SUBSETREG:
  835. // can happen for function results on win32 and darwin/x86
  836. if (left.resultdef.size > sizeof(pint)) then
  837. expectloc:=LOC_REFERENCE
  838. else
  839. expectloc:=LOC_SUBSETREG;
  840. LOC_CREGISTER,
  841. LOC_CSUBSETREG:
  842. expectloc:=LOC_CSUBSETREG;
  843. LOC_REFERENCE,
  844. LOC_CREFERENCE:
  845. expectloc:=left.expectloc;
  846. else internalerror(20060521);
  847. end;
  848. end;
  849. end;
  850. function tsubscriptnode.docompare(p: tnode): boolean;
  851. begin
  852. docompare :=
  853. inherited docompare(p) and
  854. (vs = tsubscriptnode(p).vs);
  855. end;
  856. procedure tsubscriptnode.printnodedata(var T: Text);
  857. begin
  858. inherited printnodedata(T);
  859. writeln(t,printnodeindention,'field = ',vs.name);
  860. end;
  861. {$ifdef DEBUG_NODE_XML}
  862. procedure TSubscriptNode.XMLPrintNodeData(var T: Text);
  863. begin
  864. inherited XMLPrintNodeData(T);
  865. WriteLn(T, PrintNodeIndention, '<field>', vs.Name, '</field>');
  866. end;
  867. {$endif DEBUG_NODE_XML}
  868. {*****************************************************************************
  869. TVECNODE
  870. *****************************************************************************}
  871. constructor tvecnode.create(l,r : tnode);
  872. begin
  873. inherited create(vecn,l,r);
  874. end;
  875. function tvecnode.pass_typecheck:tnode;
  876. var
  877. htype,elementdef,elementptrdef : tdef;
  878. newordtyp: tordtype;
  879. valid : boolean;
  880. minvalue, maxvalue: Tconstexprint;
  881. begin
  882. result:=nil;
  883. typecheckpass(left);
  884. typecheckpass(right);
  885. { implicitly convert stringconstant to stringdef,
  886. see tbs/tb0476.pp for a test }
  887. if (left.nodetype=stringconstn) and
  888. (tstringconstnode(left).cst_type=cst_conststring) then
  889. begin
  890. if tstringconstnode(left).len>255 then
  891. inserttypeconv(left,getansistringdef)
  892. else
  893. inserttypeconv(left,cshortstringtype);
  894. end;
  895. { In p[1] p is always valid, it is not possible to
  896. declared a shortstring or normal array that has
  897. undefined number of elements. Dynamic array and
  898. ansi/widestring needs to be valid }
  899. valid:=is_dynamic_array(left.resultdef) or
  900. is_ansistring(left.resultdef) or
  901. is_wide_or_unicode_string(left.resultdef) or
  902. { implicit pointer dereference -> pointer is read }
  903. (left.resultdef.typ = pointerdef);
  904. if valid then
  905. set_varstate(left,vs_read,[vsf_must_be_valid]);
  906. {
  907. A vecn is, just like a loadn, always part of an expression with its
  908. own read/write and must_be_valid semantics. Therefore we don't have
  909. to do anything else here, just like for loadn's
  910. }
  911. set_varstate(right,vs_read,[vsf_must_be_valid]);
  912. if codegenerror then
  913. exit;
  914. { maybe type conversion for the index value, but
  915. do not convert range nodes }
  916. if (right.nodetype<>rangen) then
  917. case left.resultdef.typ of
  918. arraydef:
  919. begin
  920. htype:=Tarraydef(left.resultdef).rangedef;
  921. if ado_isvariant in Tarraydef(left.resultdef).arrayoptions then
  922. {Variant arrays are a special array, can have negative indexes and would therefore
  923. need s32bit. However, they should not appear in a vecn, as they are handled in
  924. handle_variantarray in pexpr.pas. Therefore, encountering a variant array is an
  925. internal error... }
  926. internalerror(200707031)
  927. { open array and array constructor range checking is handled
  928. below at the node level, where the validity of the index
  929. will be checked -> use a regular type conversion to either
  930. the signed or unsigned native int type to prevent another
  931. range check from getting inserted here (unless the type is
  932. larger than the int type). Exception: if it's an ordinal
  933. constant, because then this check should be performed at
  934. compile time }
  935. else if is_open_array(left.resultdef) or
  936. is_array_constructor(left.resultdef) then
  937. begin
  938. if is_signed(right.resultdef) and
  939. not is_constnode(right) then
  940. inserttypeconv(right,sizesinttype)
  941. else
  942. inserttypeconv(right,sizeuinttype)
  943. end
  944. else if is_special_array(left.resultdef) then
  945. {Arrays without a high bound (dynamic arrays, open arrays) are zero based,
  946. convert indexes into these arrays to aword.}
  947. inserttypeconv(right,uinttype)
  948. { note: <> rather than </>, because indexing e.g. an array 0..0
  949. must not result in truncating the indexing value from 2/4/8
  950. bytes to 1 byte (with range checking off, the full index
  951. value must be used) }
  952. else if (htype.typ=enumdef) and
  953. (right.resultdef.typ=enumdef) and
  954. (tenumdef(htype).basedef=tenumdef(right.resultdef).basedef) and
  955. ((tarraydef(left.resultdef).lowrange<>tenumdef(htype).min) or
  956. (tarraydef(left.resultdef).highrange<>tenumdef(htype).max) or
  957. { while we could assume that the value might not be out of range,
  958. memory corruption could have resulted in an illegal value,
  959. so do not skip the type conversion in case of range checking
  960. After all, range checking is a safety mean }
  961. (cs_check_range in current_settings.localswitches)) then
  962. {Convert array indexes to low_bound..high_bound.}
  963. inserttypeconv(right,cenumdef.create_subrange(tenumdef(right.resultdef),
  964. asizeint(Tarraydef(left.resultdef).lowrange),
  965. asizeint(Tarraydef(left.resultdef).highrange)
  966. ))
  967. else if (htype.typ=orddef) and
  968. { right can also be a variant or another type with
  969. overloaded assignment }
  970. (right.resultdef.typ=orddef) and
  971. { don't try to create boolean types with custom ranges }
  972. not is_boolean(right.resultdef) and
  973. { ordtype determines the size of the loaded value -> make
  974. sure we don't truncate }
  975. ((Torddef(right.resultdef).ordtype<>torddef(htype).ordtype) or
  976. (tarraydef(left.resultdef).lowrange<>torddef(htype).low) or
  977. (tarraydef(left.resultdef).highrange<>torddef(htype).high)) then
  978. {Convert array indexes to low_bound..high_bound.}
  979. begin
  980. if (right.resultdef.typ=orddef)
  981. {$ifndef cpu64bitaddr}
  982. { do truncate 64 bit values on 32 bit cpus, since
  983. a) the arrays cannot be > 32 bit anyway
  984. b) their code generators can't directly handle 64 bit
  985. loads
  986. }
  987. and not is_64bit(right.resultdef)
  988. {$endif not cpu64bitaddr}
  989. then
  990. begin
  991. { in case of an integer type, we need a new type which covers declaration range and index range,
  992. see tests/webtbs/tw38413.pp
  993. This matters only if we sign extend, if the type exceeds the sint range, we can fall back only
  994. to the index type
  995. }
  996. if is_integer(right.resultdef) and ((torddef(right.resultdef).low<0) or (TConstExprInt(Tarraydef(left.resultdef).lowrange)<0)) then
  997. begin
  998. minvalue:=min(TConstExprInt(Tarraydef(left.resultdef).lowrange),torddef(right.resultdef).low);
  999. maxvalue:=max(TConstExprInt(Tarraydef(left.resultdef).highrange),torddef(right.resultdef).high);
  1000. if maxvalue>torddef(sinttype).high then
  1001. newordtyp:=Torddef(right.resultdef).ordtype
  1002. else
  1003. newordtyp:=range_to_basetype(minvalue,maxvalue);
  1004. end
  1005. else
  1006. newordtyp:=Torddef(right.resultdef).ordtype;
  1007. end
  1008. else
  1009. newordtyp:=torddef(sizesinttype).ordtype;
  1010. inserttypeconv(right,corddef.create(newordtyp,
  1011. int64(Tarraydef(left.resultdef).lowrange),
  1012. int64(Tarraydef(left.resultdef).highrange),
  1013. true
  1014. ));
  1015. end
  1016. else
  1017. begin
  1018. inserttypeconv(right,htype);
  1019. { insert type conversion so cse can pick it up }
  1020. if (htype.size<ptrsinttype.size) and is_integer(htype) and not(cs_check_range in current_settings.localswitches) then
  1021. inserttypeconv_internal(right,ptrsinttype);
  1022. end;
  1023. end;
  1024. stringdef:
  1025. if is_open_string(left.resultdef) then
  1026. inserttypeconv(right,u8inttype)
  1027. else if is_shortstring(left.resultdef) then
  1028. {Convert shortstring indexes to 0..length.}
  1029. inserttypeconv(right,corddef.create(u8bit,0,int64(Tstringdef(left.resultdef).len),true))
  1030. else
  1031. {Convert indexes into dynamically allocated strings to aword.}
  1032. inserttypeconv(right,uinttype);
  1033. pointerdef:
  1034. inserttypeconv(right,tpointerdef(left.resultdef).pointer_arithmetic_int_type);
  1035. else
  1036. {Others, (are there any?) indexes to aint.}
  1037. inserttypeconv(right,sinttype);
  1038. end;
  1039. { although we never put regular arrays or shortstrings in registers,
  1040. it's possible that another type was typecasted to a small record
  1041. that has a field of one of these types -> in that case the record
  1042. can't be a regvar either }
  1043. if ((left.resultdef.typ=arraydef) and
  1044. not is_special_array(left.resultdef) and
  1045. { arrays with elements equal to the alu size and with a constant index can be kept in register }
  1046. not(is_constnode(right) and (tarraydef(left.resultdef).elementdef.size=alusinttype.size))) or
  1047. ((left.resultdef.typ=stringdef) and
  1048. (tstringdef(left.resultdef).stringtype in [st_shortstring,st_longstring])) then
  1049. make_not_regable(left,[ra_addr_regable]);
  1050. case left.resultdef.typ of
  1051. arraydef :
  1052. begin
  1053. { check type of the index value }
  1054. if (compare_defs(right.resultdef,tarraydef(left.resultdef).rangedef,right.nodetype)=te_incompatible) then
  1055. IncompatibleTypes(right.resultdef,tarraydef(left.resultdef).rangedef);
  1056. if right.nodetype=rangen then
  1057. resultdef:=left.resultdef
  1058. else
  1059. resultdef:=Tarraydef(left.resultdef).elementdef;
  1060. result:=gen_array_rangecheck;
  1061. if assigned(result) then
  1062. exit;
  1063. { in case of a bitpacked array of enums that are size 2 (due to
  1064. packenum 2) but whose values all fit in one byte, the size of
  1065. bitpacked array elements will be 1 byte while the resultdef of
  1066. will currently say it's two bytes) -> create a temp enumdef
  1067. with packenum=1 for the resultdef as subtype of the main
  1068. enumdef }
  1069. if is_enum(resultdef) and
  1070. is_packed_array(left.resultdef) and
  1071. ((tarraydef(left.resultdef).elepackedbitsize div 8) <> resultdef.size) then
  1072. begin
  1073. resultdef:=cenumdef.create_subrange(tenumdef(resultdef),tenumdef(resultdef).min,tenumdef(resultdef).max);
  1074. tenumdef(resultdef).calcsavesize(1);
  1075. end
  1076. end;
  1077. pointerdef :
  1078. begin
  1079. { are we accessing a pointer[], then convert the pointer to
  1080. an array first, in FPC this is allowed for all pointers
  1081. (except voidpointer) in delphi/tp7 it's only allowed for pchars. }
  1082. if not is_voidpointer(left.resultdef) and
  1083. (
  1084. (cs_pointermath in current_settings.localswitches) or
  1085. tpointerdef(left.resultdef).has_pointer_math or
  1086. is_pchar(left.resultdef) or
  1087. is_pwidechar(left.resultdef)
  1088. ) then
  1089. begin
  1090. { convert pointer to array }
  1091. htype:=carraydef.create_from_pointer(tpointerdef(left.resultdef));
  1092. inserttypeconv(left,htype);
  1093. if right.nodetype=rangen then
  1094. resultdef:=htype
  1095. else
  1096. resultdef:=tarraydef(htype).elementdef;
  1097. end
  1098. else
  1099. CGMessage(type_e_array_required);
  1100. end;
  1101. stringdef :
  1102. begin
  1103. case tstringdef(left.resultdef).stringtype of
  1104. st_unicodestring,
  1105. st_widestring :
  1106. begin
  1107. elementdef:=cwidechartype;
  1108. elementptrdef:=widecharpointertype;
  1109. end;
  1110. st_ansistring,
  1111. st_longstring,
  1112. st_shortstring :
  1113. begin
  1114. elementdef:=cansichartype;
  1115. elementptrdef:=charpointertype;
  1116. end;
  1117. end;
  1118. if right.nodetype=rangen then
  1119. begin
  1120. htype:=carraydef.create_from_pointer(tpointerdef(elementptrdef));
  1121. resultdef:=htype;
  1122. end
  1123. else
  1124. begin
  1125. { indexed access to 0 element is only allowed for shortstrings or if
  1126. zero based strings is turned on }
  1127. if (right.nodetype=ordconstn) and
  1128. (Tordconstnode(right).value.svalue=0) and
  1129. not is_shortstring(left.resultdef) and
  1130. not(cs_zerobasedstrings in current_settings.localswitches) then
  1131. CGMessage(cg_e_can_access_element_zero);
  1132. resultdef:=elementdef;
  1133. end;
  1134. end;
  1135. variantdef :
  1136. resultdef:=cvarianttype;
  1137. else
  1138. CGMessage(type_e_array_required);
  1139. end;
  1140. end;
  1141. procedure Tvecnode.mark_write;
  1142. begin
  1143. include(flags,nf_write);
  1144. { see comment in tsubscriptnode.mark_write }
  1145. if not(is_implicit_array_pointer(left.resultdef)) then
  1146. left.mark_write;
  1147. end;
  1148. function tvecnode.pass_1 : tnode;
  1149. begin
  1150. result:=nil;
  1151. firstpass(left);
  1152. firstpass(right);
  1153. if codegenerror then
  1154. exit;
  1155. if (nf_callunique in flags) and
  1156. (is_ansistring(left.resultdef) or
  1157. is_unicodestring(left.resultdef) or
  1158. (is_widestring(left.resultdef) and not(tf_winlikewidestring in target_info.flags))) then
  1159. begin
  1160. left := ctypeconvnode.create_internal(ccallnode.createintern('fpc_'+tstringdef(left.resultdef).stringtypname+'_unique',
  1161. ccallparanode.create(
  1162. ctypeconvnode.create_internal(left,voidpointertype),nil)),
  1163. left.resultdef);
  1164. firstpass(left);
  1165. { double resultdef passes somwhere else may cause this to be }
  1166. { reset though :/ }
  1167. exclude(flags,nf_callunique);
  1168. end
  1169. else if is_widestring(left.resultdef) and (tf_winlikewidestring in target_info.flags) then
  1170. exclude(flags,nf_callunique);
  1171. { a range node as array index can only appear in function calls, and
  1172. those convert the range node into something else in
  1173. tcallnode.gen_high_tree }
  1174. if (right.nodetype=rangen) then
  1175. CGMessagePos(right.fileinfo,parser_e_illegal_expression)
  1176. else if left.resultdef.typ=arraydef then
  1177. result:=first_arraydef
  1178. else
  1179. begin
  1180. if left.expectloc=LOC_CREFERENCE then
  1181. expectloc:=LOC_CREFERENCE
  1182. else
  1183. expectloc:=LOC_REFERENCE
  1184. end;
  1185. end;
  1186. function tvecnode.simplify(forinline : boolean) : tnode;
  1187. begin
  1188. Result := nil;
  1189. { If left is a string constant and right is an ordinal constant, then
  1190. we can replace the entire branch with an ordinal constant
  1191. corresponding to the character
  1192. }
  1193. if
  1194. { If the address of the result is taken, do not optimise, as the
  1195. pointer of the original string constant is in use }
  1196. not (nf_address_taken in flags) and
  1197. (left.nodetype = stringconstn) and
  1198. (right.nodetype = ordconstn) and
  1199. { Ensure the index is in range }
  1200. (TOrdConstNode(right).value > 0) and
  1201. (TOrdConstNode(right).value <= TStringConstNode(left).len) then
  1202. begin
  1203. { The internal fields are zero-based }
  1204. case TStringConstNode(left).cst_type of
  1205. cst_widestring, cst_unicodestring:
  1206. { value_str is of type PCompilerWideString }
  1207. { while the conversion to PtrUInt is not correct when compiling from an 32 bit to a 64 bit platform because
  1208. in theory for a 64 bit target the string could be longer than 2^32,
  1209. it does not matter as a 32 bit host cannot handle such long strings anyways due to memory limitations
  1210. }
  1211. Result := COrdConstNode.create(
  1212. PCompilerWideString(TStringConstNode(left).value_str)^.data[PtrUInt(TOrdConstNode(right).value.uvalue) - 1],
  1213. resultdef,
  1214. False
  1215. );
  1216. else
  1217. { while the conversion to PtrUInt is not correct when compiling from an 32 bit to a 64 bit platform because
  1218. in theory for a 64 bit target the string could be longer than 2^32,
  1219. it does not matter as a 32 bit host cannot handle such long strings anyways due to memory limitations
  1220. }
  1221. Result := COrdConstNode.create(
  1222. Byte(TStringConstNode(left).value_str[PtrUInt(TOrdConstNode(right).value.uvalue) - 1]),
  1223. resultdef,
  1224. False
  1225. );
  1226. end;
  1227. end;
  1228. end;
  1229. function tvecnode.first_arraydef: tnode;
  1230. begin
  1231. result:=nil;
  1232. if (not is_packed_array(left.resultdef)) or
  1233. ((tarraydef(left.resultdef).elepackedbitsize mod 8) = 0) then
  1234. if left.expectloc=LOC_CREFERENCE then
  1235. expectloc:=LOC_CREFERENCE
  1236. else
  1237. expectloc:=LOC_REFERENCE
  1238. else
  1239. if left.expectloc=LOC_CREFERENCE then
  1240. expectloc:=LOC_CSUBSETREF
  1241. else
  1242. expectloc:=LOC_SUBSETREF;
  1243. end;
  1244. function tvecnode.gen_array_rangecheck: tnode;
  1245. var
  1246. htype: tdef;
  1247. temp: ttempcreatenode;
  1248. stat: tstatementnode;
  1249. indextree: tnode;
  1250. hightree: tnode;
  1251. begin
  1252. result:=nil;
  1253. { Range checking an array of const/open array/dynamic array is
  1254. more complicated than regular arrays, because the bounds must
  1255. be checked dynamically. Additionally, in case of array of const
  1256. and open array we need the high parameter, which must not be
  1257. made a regvar in case this is a nested rountine relative to the
  1258. array parameter -> generate te check at the node tree level
  1259. rather than in the code generator }
  1260. if (cs_check_range in current_settings.localswitches) and
  1261. (is_open_array(left.resultdef) or
  1262. is_array_of_const(left.resultdef)) and
  1263. (right.nodetype<>rangen) then
  1264. begin
  1265. { expect to find the load node }
  1266. if get_open_const_array(left).nodetype<>loadn then
  1267. internalerror(2014040601);
  1268. { cdecl functions don't have high() so we can not check the range }
  1269. { (can't use current_procdef, since it may be a nested procedure) }
  1270. if not(tprocdef(tparasymtable(tparavarsym(tloadnode(get_open_const_array(left)).symtableentry).owner).defowner).proccalloption in cdecl_pocalls) then
  1271. begin
  1272. temp:=nil;
  1273. result:=internalstatements(stat);
  1274. { can't use node_complexity here, assumes that the code has
  1275. already been firstpassed }
  1276. if not is_const(right) then
  1277. begin
  1278. temp:=ctempcreatenode.create(right.resultdef,right.resultdef.size,tt_persistent,true);
  1279. addstatement(stat,temp);
  1280. { needed so we can typecheck its temprefnodes }
  1281. typecheckpass(tnode(temp));
  1282. addstatement(stat,cassignmentnode.create(
  1283. ctemprefnode.create(temp),right)
  1284. );
  1285. right:=ctemprefnode.create(temp);
  1286. { right.resultdef is used below }
  1287. typecheckpass(right);
  1288. end;
  1289. { range check will be made explicit here }
  1290. exclude(localswitches,cs_check_range);
  1291. hightree:=load_high_value_node(tparavarsym(tloadnode(
  1292. get_open_const_array(left)).symtableentry));
  1293. { make index unsigned so we only need one comparison;
  1294. lower bound is always zero for these arrays, but
  1295. hightree can be -1 in case the array was empty ->
  1296. add 1 before comparing (ignoring overflows) }
  1297. htype:=get_unsigned_inttype(right.resultdef);
  1298. inserttypeconv_explicit(hightree,htype);
  1299. hightree:=caddnode.create(addn,hightree,genintconstnode(1));
  1300. hightree.localswitches:=hightree.localswitches-[cs_check_range,
  1301. cs_check_overflow];
  1302. indextree:=ctypeconvnode.create_explicit(right.getcopy,htype);
  1303. { range error if index >= hightree+1 }
  1304. addstatement(stat,
  1305. cifnode.create_internal(
  1306. caddnode.create_internal(gten,indextree,hightree),
  1307. ccallnode.createintern('fpc_rangeerror',nil),
  1308. nil
  1309. )
  1310. );
  1311. if assigned(temp) then
  1312. addstatement(stat,ctempdeletenode.create_normal_temp(temp));
  1313. addstatement(stat,self.getcopy);
  1314. end;
  1315. end;
  1316. end;
  1317. {$ifdef DEBUG_NODE_XML}
  1318. procedure TVecNode.XMLPrintNodeData(var T: Text);
  1319. begin
  1320. XMLPrintNode(T, Left);
  1321. { The right node is the index }
  1322. WriteLn(T, PrintNodeIndention, '<index>');
  1323. PrintNodeIndent;
  1324. XMLPrintNode(T, Right);
  1325. PrintNodeUnindent;
  1326. WriteLn(T, PrintNodeIndention, '</index>');
  1327. PrintNodeUnindent;
  1328. WriteLn(T, PrintNodeIndention, '</', nodetype2str[nodetype], '>');
  1329. end;
  1330. {$endif DEBUG_NODE_XML}
  1331. function is_big_untyped_addrnode(p: tnode): boolean;
  1332. begin
  1333. is_big_untyped_addrnode:=(p.nodetype=addrn) and
  1334. not (anf_typedaddr in taddrnode(p).addrnodeflags) and
  1335. (taddrnode(p).left.resultdef.size > 1);
  1336. end;
  1337. end.