nmem.pas 48 KB

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