2
0

nmem.pas 48 KB

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