nmem.pas 49 KB

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