nmem.pas 54 KB

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