2
0

nmem.pas 48 KB

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