nmem.pas 50 KB

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