nmem.pas 50 KB

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