nmem.pas 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  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. (not assigned(current_procinfo) or
  250. (po_inline in current_procinfo.procdef.procoptions) or
  251. wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) 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. if current_procinfo.procdef.parast.symtablelevel>pd.parast.symtablelevel then
  287. current_procinfo.set_needs_parentfp(pd.parast.symtablelevel);
  288. end;
  289. constructor tloadparentfpnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  290. begin
  291. inherited ppuload(t,ppufile);
  292. ppufile.getderef(parentpdderef);
  293. kind:=tloadparentfpkind(ppufile.getbyte);
  294. end;
  295. procedure tloadparentfpnode.ppuwrite(ppufile:tcompilerppufile);
  296. begin
  297. inherited ppuwrite(ppufile);
  298. ppufile.putderef(parentpdderef);
  299. ppufile.putbyte(byte(kind));
  300. end;
  301. procedure tloadparentfpnode.buildderefimpl;
  302. begin
  303. inherited buildderefimpl;
  304. parentpdderef.build(parentpd);
  305. end;
  306. procedure tloadparentfpnode.derefimpl;
  307. begin
  308. inherited derefimpl;
  309. parentpd:=tprocdef(parentpdderef.resolve);
  310. end;
  311. function tloadparentfpnode.docompare(p: tnode): boolean;
  312. begin
  313. result:=
  314. inherited docompare(p) and
  315. (tloadparentfpnode(p).parentpd=parentpd) and
  316. (tloadparentfpnode(p).kind=kind);
  317. end;
  318. function tloadparentfpnode.dogetcopy : tnode;
  319. var
  320. p : tloadparentfpnode;
  321. begin
  322. p:=tloadparentfpnode(inherited dogetcopy);
  323. p.parentpd:=parentpd;
  324. p.kind:=kind;
  325. dogetcopy:=p;
  326. end;
  327. function tloadparentfpnode.pass_typecheck:tnode;
  328. begin
  329. result:=nil;
  330. resultdef:=parentfpvoidpointertype;
  331. end;
  332. function tloadparentfpnode.pass_1 : tnode;
  333. begin
  334. result:=nil;
  335. expectloc:=LOC_REGISTER;
  336. end;
  337. {*****************************************************************************
  338. TADDRNODE
  339. *****************************************************************************}
  340. constructor taddrnode.create(l : tnode);
  341. begin
  342. inherited create(addrn,l);
  343. getprocvardef:=nil;
  344. addrnodeflags:=[];
  345. mark_read_written := true;
  346. end;
  347. constructor taddrnode.create_internal(l : tnode);
  348. begin
  349. self.create(l);
  350. include(flags,nf_internal);
  351. end;
  352. constructor taddrnode.create_internal_nomark(l : tnode);
  353. begin
  354. self.create_internal(l);
  355. mark_read_written := false;
  356. end;
  357. constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  358. begin
  359. inherited ppuload(t,ppufile);
  360. ppufile.getderef(getprocvardefderef);
  361. ppufile.getset(tppuset1(addrnodeflags));
  362. end;
  363. procedure taddrnode.ppuwrite(ppufile:tcompilerppufile);
  364. begin
  365. inherited ppuwrite(ppufile);
  366. ppufile.putderef(getprocvardefderef);
  367. ppufile.putset(tppuset1(addrnodeflags));
  368. end;
  369. procedure Taddrnode.mark_write;
  370. begin
  371. {@procvar:=nil is legal in Delphi mode.}
  372. left.mark_write;
  373. end;
  374. procedure taddrnode.buildderefimpl;
  375. begin
  376. inherited buildderefimpl;
  377. getprocvardefderef.build(getprocvardef);
  378. end;
  379. procedure taddrnode.derefimpl;
  380. begin
  381. inherited derefimpl;
  382. getprocvardef:=tprocvardef(getprocvardefderef.resolve);
  383. end;
  384. procedure taddrnode.printnodeinfo(var t: text);
  385. var
  386. first: Boolean;
  387. i: taddrnodeflag;
  388. begin
  389. inherited printnodeinfo(t);
  390. write(t,', addrnodeflags = [');
  391. first:=true;
  392. for i:=low(taddrnodeflag) to high(taddrnodeflag) do
  393. if i in addrnodeflags then
  394. begin
  395. if not first then
  396. write(t,',')
  397. else
  398. first:=false;
  399. write(t,i);
  400. end;
  401. write(t,']');
  402. end;
  403. {$ifdef DEBUG_NODE_XML}
  404. procedure TAddrNode.XMLPrintNodeInfo(var T: Text);
  405. var
  406. First: Boolean;
  407. i: TAddrNodeFlag;
  408. begin
  409. inherited XMLPrintNodeInfo(t);
  410. First := True;
  411. for i := Low(TAddrNodeFlag) to High(TAddrNodeFlag) do
  412. if i in addrnodeflags then
  413. begin
  414. if First then
  415. begin
  416. Write(T, ' addrnodeflags="', i);
  417. First := False;
  418. end
  419. else
  420. Write(T, ',', i);
  421. end;
  422. if not First then
  423. Write(T, '"');
  424. end;
  425. {$endif DEBUG_NODE_XML}
  426. function taddrnode.docompare(p: tnode): boolean;
  427. begin
  428. result:=
  429. inherited docompare(p) and
  430. (taddrnode(p).getprocvardef=getprocvardef) and
  431. (taddrnode(p).addrnodeflags=addrnodeflags);
  432. end;
  433. function taddrnode.dogetcopy : tnode;
  434. var
  435. p : taddrnode;
  436. begin
  437. p:=taddrnode(inherited dogetcopy);
  438. p.getprocvardef:=getprocvardef;
  439. p.addrnodeflags:=addrnodeflags;
  440. dogetcopy:=p;
  441. end;
  442. function taddrnode.pass_typecheck:tnode;
  443. procedure check_mark_read_written;
  444. begin
  445. if mark_read_written then
  446. begin
  447. { This is actually only "read", but treat it nevertheless as
  448. modified due to the possible use of pointers
  449. To avoid false positives regarding "uninitialised"
  450. warnings when using arrays, perform it in two steps }
  451. set_varstate(left,vs_written,[]);
  452. { vsf_must_be_valid so it doesn't get changed into
  453. vsf_referred_not_inited }
  454. set_varstate(left,vs_read,[vsf_must_be_valid]);
  455. end;
  456. end;
  457. var
  458. hp : tnode;
  459. hsym : tfieldvarsym;
  460. isprocvar,need_conv_to_voidptr: boolean;
  461. procpointertype: tdef;
  462. begin
  463. result:=nil;
  464. typecheckpass(left);
  465. if codegenerror then
  466. exit;
  467. make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
  468. { don't allow constants, for internal use we also
  469. allow taking the address of strings and sets }
  470. if is_constnode(left) and
  471. not(
  472. (nf_internal in flags) and
  473. (left.nodetype in [stringconstn,setconstn])
  474. ) then
  475. begin
  476. CGMessagePos(left.fileinfo,type_e_no_addr_of_constant);
  477. exit;
  478. end;
  479. { Handle @proc special, also @procvar in tp-mode needs
  480. special handling }
  481. if (left.resultdef.typ=procdef) or
  482. (
  483. { in case of nf_internal, follow the normal FPC semantics so that
  484. we can easily get the actual address of a procvar }
  485. not(nf_internal in flags) and
  486. (left.resultdef.typ=procvardef) and
  487. ((m_tp_procvar in current_settings.modeswitches) or
  488. (m_mac_procvar in current_settings.modeswitches))
  489. ) then
  490. begin
  491. isprocvar:=(left.resultdef.typ=procvardef);
  492. need_conv_to_voidptr:=
  493. (m_tp_procvar in current_settings.modeswitches) or
  494. (m_mac_procvar in current_settings.modeswitches);
  495. if not isprocvar then
  496. begin
  497. left:=ctypeconvnode.create_proc_to_procvar(left);
  498. if need_conv_to_voidptr then
  499. include(ttypeconvnode(left).convnodeflags,tcnf_proc_2_procvar_2_voidpointer);
  500. if anf_ofs in addrnodeflags then
  501. include(ttypeconvnode(left).convnodeflags,tcnf_proc_2_procvar_get_offset_only);
  502. left.fileinfo:=fileinfo;
  503. typecheckpass(left);
  504. end;
  505. { In tp procvar mode the result is always a voidpointer. Insert
  506. a typeconversion to voidpointer. For methodpointers we need
  507. to load the proc field }
  508. if need_conv_to_voidptr then
  509. begin
  510. if tabstractprocdef(left.resultdef).is_addressonly then
  511. begin
  512. if anf_ofs in addrnodeflags then
  513. result:=ctypeconvnode.create_internal(left,tabstractprocdef(left.resultdef).ofs_address_type)
  514. else
  515. result:=ctypeconvnode.create_internal(left,voidcodepointertype);
  516. include(result.flags,nf_load_procvar);
  517. left:=nil;
  518. end
  519. else
  520. begin
  521. { For procvars and for nested routines we need to return
  522. the proc field of the methodpointer }
  523. if isprocvar or
  524. is_nested_pd(tabstractprocdef(left.resultdef)) then
  525. begin
  526. if tabstractprocdef(left.resultdef).is_methodpointer then
  527. procpointertype:=methodpointertype
  528. else
  529. procpointertype:=nestedprocpointertype;
  530. { find proc field in methodpointer record }
  531. hsym:=tfieldvarsym(trecorddef(procpointertype).symtable.Find('proc'));
  532. if not assigned(hsym) then
  533. internalerror(200412041);
  534. { Load tmehodpointer(left).proc }
  535. result:=csubscriptnode.create(
  536. hsym,
  537. ctypeconvnode.create_internal(left,procpointertype));
  538. left:=nil;
  539. end
  540. else
  541. CGMessage(type_e_variable_id_expected);
  542. end;
  543. end
  544. else
  545. begin
  546. check_mark_read_written;
  547. { Return the typeconvn only }
  548. result:=left;
  549. left:=nil;
  550. exit;
  551. end;
  552. end
  553. else
  554. begin
  555. hp:=left;
  556. while assigned(hp) and (hp.nodetype in [typeconvn,derefn,subscriptn]) do
  557. hp:=tunarynode(hp).left;
  558. if not assigned(hp) then
  559. internalerror(200412042);
  560. if typecheck_non_proc(hp,result) then
  561. begin
  562. if assigned(result) then
  563. exit;
  564. end
  565. else
  566. CGMessage(type_e_variable_id_expected);
  567. end;
  568. check_mark_read_written;
  569. if not(assigned(result)) then
  570. result:=simplify(false);
  571. end;
  572. function taddrnode.simplify(forinline : boolean) : tnode;
  573. var
  574. hsym : tfieldvarsym;
  575. begin
  576. result:=nil;
  577. if ((left.nodetype=subscriptn) and
  578. (tsubscriptnode(left).left.nodetype=derefn) and
  579. (tsubscriptnode(left).left.resultdef.typ=recorddef) and
  580. (tderefnode(tsubscriptnode(left).left).left.nodetype=niln)) or
  581. ((left.nodetype=subscriptn) and
  582. (tsubscriptnode(left).left.nodetype=typeconvn) and
  583. (tsubscriptnode(left).left.resultdef.typ=recorddef) and
  584. (ttypeconvnode(tsubscriptnode(left).left).left.nodetype=derefn) and
  585. (tderefnode(ttypeconvnode(tsubscriptnode(left).left).left).left.nodetype=niln)) then
  586. begin
  587. hsym:=tsubscriptnode(left).vs;
  588. if tabstractrecordsymtable(hsym.owner).is_packed then
  589. result:=cpointerconstnode.create(hsym.fieldoffset div 8,resultdef)
  590. else
  591. result:=cpointerconstnode.create(hsym.fieldoffset,resultdef);
  592. end;
  593. end;
  594. procedure taddrnode.set_labelsym_resultdef;
  595. begin
  596. resultdef:=voidcodepointertype;
  597. end;
  598. function taddrnode.typecheck_non_proc(realsource: tnode; out res: tnode): boolean;
  599. var
  600. hp : tnode;
  601. hsym : tfieldvarsym;
  602. offset: asizeint;
  603. begin
  604. result:=false;
  605. res:=nil;
  606. if (realsource.nodetype=loadn) and
  607. (tloadnode(realsource).symtableentry.typ=labelsym) then
  608. begin
  609. set_labelsym_resultdef;
  610. result:=true;
  611. end
  612. else if (realsource.nodetype=loadn) and
  613. (tloadnode(realsource).symtableentry.typ=absolutevarsym) and
  614. (tabsolutevarsym(tloadnode(realsource).symtableentry).abstyp=toaddr) then
  615. begin
  616. offset:=tabsolutevarsym(tloadnode(realsource).symtableentry).addroffset;
  617. hp:=left;
  618. while assigned(hp)and(hp.nodetype=subscriptn) do
  619. begin
  620. hsym:=tsubscriptnode(hp).vs;
  621. if tabstractrecordsymtable(hsym.owner).is_packed then
  622. begin
  623. { can't calculate the address of a non-byte aligned field }
  624. if (hsym.fieldoffset mod 8)<>0 then
  625. begin
  626. CGMessagePos(hp.fileinfo,parser_e_packed_element_no_var_addr);
  627. exit
  628. end;
  629. inc(offset,hsym.fieldoffset div 8)
  630. end
  631. else
  632. inc(offset,hsym.fieldoffset);
  633. hp:=tunarynode(hp).left;
  634. end;
  635. if anf_typedaddr in addrnodeflags then
  636. res:=cpointerconstnode.create(offset,cpointerdef.getreusable(left.resultdef))
  637. else
  638. res:=cpointerconstnode.create(offset,voidpointertype);
  639. result:=true;
  640. end
  641. else if (nf_internal in flags) or
  642. valid_for_addr(left,true) then
  643. begin
  644. if not(anf_typedaddr in addrnodeflags) then
  645. resultdef:=voidpointertype
  646. else
  647. resultdef:=cpointerdef.getreusable(left.resultdef);
  648. result:=true;
  649. end
  650. end;
  651. function taddrnode.pass_1 : tnode;
  652. begin
  653. result:=nil;
  654. firstpass(left);
  655. if codegenerror then
  656. exit;
  657. { is this right for object of methods ?? }
  658. expectloc:=LOC_REGISTER;
  659. end;
  660. {*****************************************************************************
  661. TDEREFNODE
  662. *****************************************************************************}
  663. constructor tderefnode.create(l : tnode);
  664. begin
  665. inherited create(derefn,l);
  666. end;
  667. function tderefnode.pass_typecheck:tnode;
  668. begin
  669. result:=nil;
  670. typecheckpass(left);
  671. set_varstate(left,vs_read,[vsf_must_be_valid]);
  672. if codegenerror then
  673. exit;
  674. { tp procvar support }
  675. maybe_call_procvar(left,true);
  676. if left.resultdef.typ=pointerdef then
  677. resultdef:=tpointerdef(left.resultdef).pointeddef
  678. else if left.resultdef.typ=undefineddef then
  679. resultdef:=cundefineddef.create(true)
  680. else
  681. CGMessage(parser_e_invalid_qualifier);
  682. end;
  683. procedure Tderefnode.mark_write;
  684. begin
  685. include(flags,nf_write);
  686. end;
  687. function tderefnode.pass_1 : tnode;
  688. begin
  689. result:=nil;
  690. firstpass(left);
  691. if codegenerror then
  692. exit;
  693. expectloc:=LOC_REFERENCE;
  694. end;
  695. {*****************************************************************************
  696. TSUBSCRIPTNODE
  697. *****************************************************************************}
  698. constructor tsubscriptnode.create(varsym : tsym;l : tnode);
  699. begin
  700. inherited create(subscriptn,l);
  701. { vs should be changed to tsym! }
  702. vs:=tfieldvarsym(varsym);
  703. end;
  704. constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  705. begin
  706. inherited ppuload(t,ppufile);
  707. ppufile.getderef(vsderef);
  708. end;
  709. procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
  710. begin
  711. inherited ppuwrite(ppufile);
  712. ppufile.putderef(vsderef);
  713. end;
  714. procedure tsubscriptnode.buildderefimpl;
  715. begin
  716. inherited buildderefimpl;
  717. vsderef.build(vs);
  718. end;
  719. procedure tsubscriptnode.derefimpl;
  720. begin
  721. inherited derefimpl;
  722. vs:=tfieldvarsym(vsderef.resolve);
  723. end;
  724. function tsubscriptnode.dogetcopy : tnode;
  725. var
  726. p : tsubscriptnode;
  727. begin
  728. p:=tsubscriptnode(inherited dogetcopy);
  729. p.vs:=vs;
  730. dogetcopy:=p;
  731. end;
  732. function tsubscriptnode.pass_typecheck:tnode;
  733. begin
  734. result:=nil;
  735. typecheckpass(left);
  736. { tp procvar support }
  737. maybe_call_procvar(left,true);
  738. resultdef:=vs.vardef;
  739. // don't put records from which we load float fields
  740. // in integer registers
  741. if (left.resultdef.typ=recorddef) and
  742. (resultdef.typ=floatdef) then
  743. make_not_regable(left,[ra_addr_regable]);
  744. end;
  745. procedure Tsubscriptnode.mark_write;
  746. begin
  747. include(flags,nf_write);
  748. { if an element of a record is written, then the whole record is changed/it is written to it,
  749. for data types being implicit pointers this does not apply as the object itself does not change }
  750. if not(is_implicit_pointer_object_type(left.resultdef)) then
  751. left.mark_write;
  752. end;
  753. function tsubscriptnode.pass_1 : tnode;
  754. begin
  755. result:=nil;
  756. firstpass(left);
  757. if codegenerror then
  758. exit;
  759. { several object types must be dereferenced implicitly }
  760. if is_implicit_pointer_object_type(left.resultdef) then
  761. expectloc:=LOC_REFERENCE
  762. else
  763. begin
  764. case left.expectloc of
  765. { if a floating point value is casted into a record, it
  766. can happen that we get here an fpu or mm register }
  767. LOC_CMMREGISTER,
  768. LOC_CFPUREGISTER,
  769. LOC_MMREGISTER,
  770. LOC_FPUREGISTER,
  771. LOC_CONSTANT,
  772. LOC_REGISTER,
  773. LOC_SUBSETREG:
  774. // can happen for function results on win32 and darwin/x86
  775. if (left.resultdef.size > sizeof(pint)) then
  776. expectloc:=LOC_REFERENCE
  777. else
  778. expectloc:=LOC_SUBSETREG;
  779. LOC_CREGISTER,
  780. LOC_CSUBSETREG:
  781. expectloc:=LOC_CSUBSETREG;
  782. LOC_REFERENCE,
  783. LOC_CREFERENCE:
  784. expectloc:=left.expectloc;
  785. else internalerror(20060521);
  786. end;
  787. end;
  788. end;
  789. function tsubscriptnode.docompare(p: tnode): boolean;
  790. begin
  791. docompare :=
  792. inherited docompare(p) and
  793. (vs = tsubscriptnode(p).vs);
  794. end;
  795. {$ifdef DEBUG_NODE_XML}
  796. procedure TSubscriptNode.XMLPrintNodeData(var T: Text);
  797. begin
  798. inherited XMLPrintNodeData(T);
  799. WriteLn(T, PrintNodeIndention, '<field>', vs.Name, '</field>');
  800. end;
  801. {$endif DEBUG_NODE_XML}
  802. {*****************************************************************************
  803. TVECNODE
  804. *****************************************************************************}
  805. constructor tvecnode.create(l,r : tnode);
  806. begin
  807. inherited create(vecn,l,r);
  808. end;
  809. function tvecnode.pass_typecheck:tnode;
  810. var
  811. htype,elementdef,elementptrdef : tdef;
  812. newordtyp: tordtype;
  813. valid : boolean;
  814. begin
  815. result:=nil;
  816. typecheckpass(left);
  817. typecheckpass(right);
  818. { implicitly convert stringconstant to stringdef,
  819. see tbs/tb0476.pp for a test }
  820. if (left.nodetype=stringconstn) and
  821. (tstringconstnode(left).cst_type=cst_conststring) then
  822. begin
  823. if tstringconstnode(left).len>255 then
  824. inserttypeconv(left,getansistringdef)
  825. else
  826. inserttypeconv(left,cshortstringtype);
  827. end;
  828. { In p[1] p is always valid, it is not possible to
  829. declared a shortstring or normal array that has
  830. undefined number of elements. Dynamic array and
  831. ansi/widestring needs to be valid }
  832. valid:=is_dynamic_array(left.resultdef) or
  833. is_ansistring(left.resultdef) or
  834. is_wide_or_unicode_string(left.resultdef) or
  835. { implicit pointer dereference -> pointer is read }
  836. (left.resultdef.typ = pointerdef);
  837. if valid then
  838. set_varstate(left,vs_read,[vsf_must_be_valid]);
  839. {
  840. A vecn is, just like a loadn, always part of an expression with its
  841. own read/write and must_be_valid semantics. Therefore we don't have
  842. to do anything else here, just like for loadn's
  843. }
  844. set_varstate(right,vs_read,[vsf_must_be_valid]);
  845. if codegenerror then
  846. exit;
  847. { maybe type conversion for the index value, but
  848. do not convert range nodes }
  849. if (right.nodetype<>rangen) then
  850. case left.resultdef.typ of
  851. arraydef:
  852. begin
  853. htype:=Tarraydef(left.resultdef).rangedef;
  854. if ado_isvariant in Tarraydef(left.resultdef).arrayoptions then
  855. {Variant arrays are a special array, can have negative indexes and would therefore
  856. need s32bit. However, they should not appear in a vecn, as they are handled in
  857. handle_variantarray in pexpr.pas. Therefore, encountering a variant array is an
  858. internal error... }
  859. internalerror(200707031)
  860. { open array and array constructor range checking is handled
  861. below at the node level, where the validity of the index
  862. will be checked -> use a regular type conversion to either
  863. the signed or unsigned native int type to prevent another
  864. range check from getting inserted here (unless the type is
  865. larger than the int type). Exception: if it's an ordinal
  866. constant, because then this check should be performed at
  867. compile time }
  868. else if is_open_array(left.resultdef) or
  869. is_array_constructor(left.resultdef) then
  870. begin
  871. if is_signed(right.resultdef) and
  872. not is_constnode(right) then
  873. inserttypeconv(right,sizesinttype)
  874. else
  875. inserttypeconv(right,sizeuinttype)
  876. end
  877. else if is_special_array(left.resultdef) then
  878. {Arrays without a high bound (dynamic arrays, open arrays) are zero based,
  879. convert indexes into these arrays to aword.}
  880. inserttypeconv(right,uinttype)
  881. { note: <> rather than </>, because indexing e.g. an array 0..0
  882. must not result in truncating the indexing value from 2/4/8
  883. bytes to 1 byte (with range checking off, the full index
  884. value must be used) }
  885. else if (htype.typ=enumdef) and
  886. (right.resultdef.typ=enumdef) and
  887. (tenumdef(htype).basedef=tenumdef(right.resultdef).basedef) and
  888. ((tarraydef(left.resultdef).lowrange<>tenumdef(htype).min) or
  889. (tarraydef(left.resultdef).highrange<>tenumdef(htype).max)) then
  890. {Convert array indexes to low_bound..high_bound.}
  891. inserttypeconv(right,cenumdef.create_subrange(tenumdef(right.resultdef),
  892. asizeint(Tarraydef(left.resultdef).lowrange),
  893. asizeint(Tarraydef(left.resultdef).highrange)
  894. ))
  895. else if (htype.typ=orddef) and
  896. { right can also be a variant or another type with
  897. overloaded assignment }
  898. (right.resultdef.typ=orddef) and
  899. { don't try to create boolean types with custom ranges }
  900. not is_boolean(right.resultdef) and
  901. { ordtype determines the size of the loaded value -> make
  902. sure we don't truncate }
  903. ((Torddef(right.resultdef).ordtype<>torddef(htype).ordtype) or
  904. (tarraydef(left.resultdef).lowrange<>torddef(htype).low) or
  905. (tarraydef(left.resultdef).highrange<>torddef(htype).high)) then
  906. {Convert array indexes to low_bound..high_bound.}
  907. begin
  908. if (right.resultdef.typ=orddef)
  909. {$ifndef cpu64bitaddr}
  910. { do truncate 64 bit values on 32 bit cpus, since
  911. a) the arrays cannot be > 32 bit anyway
  912. b) their code generators can't directly handle 64 bit
  913. loads
  914. }
  915. and not is_64bit(right.resultdef)
  916. {$endif not cpu64bitaddr}
  917. then
  918. newordtyp:=Torddef(right.resultdef).ordtype
  919. else
  920. newordtyp:=torddef(sizesinttype).ordtype;
  921. inserttypeconv(right,corddef.create(newordtyp,
  922. int64(Tarraydef(left.resultdef).lowrange),
  923. int64(Tarraydef(left.resultdef).highrange),
  924. true
  925. ))
  926. end
  927. else
  928. inserttypeconv(right,htype)
  929. end;
  930. stringdef:
  931. if is_open_string(left.resultdef) then
  932. inserttypeconv(right,u8inttype)
  933. else if is_shortstring(left.resultdef) then
  934. {Convert shortstring indexes to 0..length.}
  935. inserttypeconv(right,corddef.create(u8bit,0,int64(Tstringdef(left.resultdef).len),true))
  936. else
  937. {Convert indexes into dynamically allocated strings to aword.}
  938. inserttypeconv(right,uinttype);
  939. pointerdef:
  940. inserttypeconv(right,tpointerdef(left.resultdef).pointer_arithmetic_int_type);
  941. else
  942. {Others, (are there any?) indexes to aint.}
  943. inserttypeconv(right,sinttype);
  944. end;
  945. { although we never put regular arrays or shortstrings in registers,
  946. it's possible that another type was typecasted to a small record
  947. that has a field of one of these types -> in that case the record
  948. can't be a regvar either }
  949. if ((left.resultdef.typ=arraydef) and
  950. not is_special_array(left.resultdef) and
  951. { arrays with elements equal to the alu size and with a constant index can be kept in register }
  952. not(is_constnode(right) and (tarraydef(left.resultdef).elementdef.size=alusinttype.size))) or
  953. ((left.resultdef.typ=stringdef) and
  954. (tstringdef(left.resultdef).stringtype in [st_shortstring,st_longstring])) then
  955. make_not_regable(left,[ra_addr_regable]);
  956. case left.resultdef.typ of
  957. arraydef :
  958. begin
  959. { check type of the index value }
  960. if (compare_defs(right.resultdef,tarraydef(left.resultdef).rangedef,right.nodetype)=te_incompatible) then
  961. IncompatibleTypes(right.resultdef,tarraydef(left.resultdef).rangedef);
  962. if right.nodetype=rangen then
  963. resultdef:=left.resultdef
  964. else
  965. resultdef:=Tarraydef(left.resultdef).elementdef;
  966. result:=gen_array_rangecheck;
  967. if assigned(result) then
  968. exit;
  969. { in case of a bitpacked array of enums that are size 2 (due to
  970. packenum 2) but whose values all fit in one byte, the size of
  971. bitpacked array elements will be 1 byte while the resultdef of
  972. will currently say it's two bytes) -> create a temp enumdef
  973. with packenum=1 for the resultdef as subtype of the main
  974. enumdef }
  975. if is_enum(resultdef) and
  976. is_packed_array(left.resultdef) and
  977. ((tarraydef(left.resultdef).elepackedbitsize div 8) <> resultdef.size) then
  978. begin
  979. resultdef:=cenumdef.create_subrange(tenumdef(resultdef),tenumdef(resultdef).min,tenumdef(resultdef).max);
  980. tenumdef(resultdef).calcsavesize(1);
  981. end
  982. end;
  983. pointerdef :
  984. begin
  985. { are we accessing a pointer[], then convert the pointer to
  986. an array first, in FPC this is allowed for all pointers
  987. (except voidpointer) in delphi/tp7 it's only allowed for pchars. }
  988. if not is_voidpointer(left.resultdef) and
  989. (
  990. (cs_pointermath in current_settings.localswitches) or
  991. tpointerdef(left.resultdef).has_pointer_math or
  992. is_pchar(left.resultdef) or
  993. is_pwidechar(left.resultdef)
  994. ) then
  995. begin
  996. { convert pointer to array }
  997. htype:=carraydef.create_from_pointer(tpointerdef(left.resultdef));
  998. inserttypeconv(left,htype);
  999. if right.nodetype=rangen then
  1000. resultdef:=htype
  1001. else
  1002. resultdef:=tarraydef(htype).elementdef;
  1003. end
  1004. else
  1005. CGMessage(type_e_array_required);
  1006. end;
  1007. stringdef :
  1008. begin
  1009. case tstringdef(left.resultdef).stringtype of
  1010. st_unicodestring,
  1011. st_widestring :
  1012. begin
  1013. elementdef:=cwidechartype;
  1014. elementptrdef:=widecharpointertype;
  1015. end;
  1016. st_ansistring,
  1017. st_longstring,
  1018. st_shortstring :
  1019. begin
  1020. elementdef:=cansichartype;
  1021. elementptrdef:=charpointertype;
  1022. end;
  1023. end;
  1024. if right.nodetype=rangen then
  1025. begin
  1026. htype:=carraydef.create_from_pointer(tpointerdef(elementptrdef));
  1027. resultdef:=htype;
  1028. end
  1029. else
  1030. begin
  1031. { indexed access to 0 element is only allowed for shortstrings or if
  1032. zero based strings is turned on }
  1033. if (right.nodetype=ordconstn) and
  1034. (Tordconstnode(right).value.svalue=0) and
  1035. not is_shortstring(left.resultdef) and
  1036. not(cs_zerobasedstrings in current_settings.localswitches) then
  1037. CGMessage(cg_e_can_access_element_zero);
  1038. resultdef:=elementdef;
  1039. end;
  1040. end;
  1041. variantdef :
  1042. resultdef:=cvarianttype;
  1043. else
  1044. CGMessage(type_e_array_required);
  1045. end;
  1046. end;
  1047. procedure Tvecnode.mark_write;
  1048. begin
  1049. include(flags,nf_write);
  1050. { see comment in tsubscriptnode.mark_write }
  1051. if not(is_implicit_array_pointer(left.resultdef)) then
  1052. left.mark_write;
  1053. end;
  1054. function tvecnode.pass_1 : tnode;
  1055. begin
  1056. result:=nil;
  1057. firstpass(left);
  1058. firstpass(right);
  1059. if codegenerror then
  1060. exit;
  1061. if (nf_callunique in flags) and
  1062. (is_ansistring(left.resultdef) or
  1063. is_unicodestring(left.resultdef) or
  1064. (is_widestring(left.resultdef) and not(tf_winlikewidestring in target_info.flags))) then
  1065. begin
  1066. left := ctypeconvnode.create_internal(ccallnode.createintern('fpc_'+tstringdef(left.resultdef).stringtypname+'_unique',
  1067. ccallparanode.create(
  1068. ctypeconvnode.create_internal(left,voidpointertype),nil)),
  1069. left.resultdef);
  1070. firstpass(left);
  1071. { double resultdef passes somwhere else may cause this to be }
  1072. { reset though :/ }
  1073. exclude(flags,nf_callunique);
  1074. end
  1075. else if is_widestring(left.resultdef) and (tf_winlikewidestring in target_info.flags) then
  1076. exclude(flags,nf_callunique);
  1077. { a range node as array index can only appear in function calls, and
  1078. those convert the range node into something else in
  1079. tcallnode.gen_high_tree }
  1080. if (right.nodetype=rangen) then
  1081. CGMessagePos(right.fileinfo,parser_e_illegal_expression)
  1082. else if left.resultdef.typ=arraydef then
  1083. result:=first_arraydef
  1084. else
  1085. begin
  1086. if left.expectloc=LOC_CREFERENCE then
  1087. expectloc:=LOC_CREFERENCE
  1088. else
  1089. expectloc:=LOC_REFERENCE
  1090. end;
  1091. end;
  1092. function tvecnode.first_arraydef: tnode;
  1093. begin
  1094. result:=nil;
  1095. if (not is_packed_array(left.resultdef)) or
  1096. ((tarraydef(left.resultdef).elepackedbitsize mod 8) = 0) then
  1097. if left.expectloc=LOC_CREFERENCE then
  1098. expectloc:=LOC_CREFERENCE
  1099. else
  1100. expectloc:=LOC_REFERENCE
  1101. else
  1102. if left.expectloc=LOC_CREFERENCE then
  1103. expectloc:=LOC_CSUBSETREF
  1104. else
  1105. expectloc:=LOC_SUBSETREF;
  1106. end;
  1107. function tvecnode.gen_array_rangecheck: tnode;
  1108. var
  1109. htype: tdef;
  1110. temp: ttempcreatenode;
  1111. stat: tstatementnode;
  1112. indextree: tnode;
  1113. hightree: tnode;
  1114. begin
  1115. result:=nil;
  1116. { Range checking an array of const/open array/dynamic array is
  1117. more complicated than regular arrays, because the bounds must
  1118. be checked dynamically. Additionally, in case of array of const
  1119. and open array we need the high parameter, which must not be
  1120. made a regvar in case this is a nested rountine relative to the
  1121. array parameter -> generate te check at the node tree level
  1122. rather than in the code generator }
  1123. if (cs_check_range in current_settings.localswitches) and
  1124. (is_open_array(left.resultdef) or
  1125. is_array_of_const(left.resultdef)) and
  1126. (right.nodetype<>rangen) then
  1127. begin
  1128. { expect to find the load node }
  1129. if get_open_const_array(left).nodetype<>loadn then
  1130. internalerror(2014040601);
  1131. { cdecl functions don't have high() so we can not check the range }
  1132. { (can't use current_procdef, since it may be a nested procedure) }
  1133. if not(tprocdef(tparasymtable(tparavarsym(tloadnode(get_open_const_array(left)).symtableentry).owner).defowner).proccalloption in cdecl_pocalls) then
  1134. begin
  1135. temp:=nil;
  1136. result:=internalstatements(stat);
  1137. { can't use node_complexity here, assumes that the code has
  1138. already been firstpassed }
  1139. if not is_const(right) then
  1140. begin
  1141. temp:=ctempcreatenode.create(right.resultdef,right.resultdef.size,tt_persistent,true);
  1142. addstatement(stat,temp);
  1143. { needed so we can typecheck its temprefnodes }
  1144. typecheckpass(tnode(temp));
  1145. addstatement(stat,cassignmentnode.create(
  1146. ctemprefnode.create(temp),right)
  1147. );
  1148. right:=ctemprefnode.create(temp);
  1149. { right.resultdef is used below }
  1150. typecheckpass(right);
  1151. end;
  1152. { range check will be made explicit here }
  1153. exclude(localswitches,cs_check_range);
  1154. hightree:=load_high_value_node(tparavarsym(tloadnode(
  1155. get_open_const_array(left)).symtableentry));
  1156. { make index unsigned so we only need one comparison;
  1157. lower bound is always zero for these arrays, but
  1158. hightree can be -1 in case the array was empty ->
  1159. add 1 before comparing (ignoring overflows) }
  1160. htype:=get_unsigned_inttype(right.resultdef);
  1161. inserttypeconv_explicit(hightree,htype);
  1162. hightree:=caddnode.create(addn,hightree,genintconstnode(1));
  1163. hightree.localswitches:=hightree.localswitches-[cs_check_range,
  1164. cs_check_overflow];
  1165. indextree:=ctypeconvnode.create_explicit(right.getcopy,htype);
  1166. { range error if index >= hightree+1 }
  1167. addstatement(stat,
  1168. cifnode.create_internal(
  1169. caddnode.create_internal(gten,indextree,hightree),
  1170. ccallnode.createintern('fpc_rangeerror',nil),
  1171. nil
  1172. )
  1173. );
  1174. if assigned(temp) then
  1175. addstatement(stat,ctempdeletenode.create_normal_temp(temp));
  1176. addstatement(stat,self.getcopy);
  1177. end;
  1178. end;
  1179. end;
  1180. {$ifdef DEBUG_NODE_XML}
  1181. procedure TVecNode.XMLPrintNodeData(var T: Text);
  1182. begin
  1183. XMLPrintNode(T, Left);
  1184. { The right node is the index }
  1185. WriteLn(T, PrintNodeIndention, '<index>');
  1186. PrintNodeIndent;
  1187. XMLPrintNode(T, Right);
  1188. PrintNodeUnindent;
  1189. WriteLn(T, PrintNodeIndention, '</index>');
  1190. PrintNodeUnindent;
  1191. WriteLn(T, PrintNodeIndention, '</', nodetype2str[nodetype], '>');
  1192. end;
  1193. {$endif DEBUG_NODE_XML}
  1194. function is_big_untyped_addrnode(p: tnode): boolean;
  1195. begin
  1196. is_big_untyped_addrnode:=(p.nodetype=addrn) and
  1197. not (anf_typedaddr in taddrnode(p).addrnodeflags) and
  1198. (taddrnode(p).left.resultdef.size > 1);
  1199. end;
  1200. end.