ncgmem.pas 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for memory related nodes which are
  4. the same for all (most?) processors
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgmem;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,cgbase,cpuinfo,cpubase,
  23. node,nmem;
  24. type
  25. tcgloadvmtaddrnode = class(tloadvmtaddrnode)
  26. procedure pass_generate_code;override;
  27. end;
  28. tcgloadparentfpnode = class(tloadparentfpnode)
  29. procedure pass_generate_code;override;
  30. end;
  31. tcgaddrnode = class(taddrnode)
  32. procedure pass_generate_code;override;
  33. end;
  34. tcgderefnode = class(tderefnode)
  35. procedure pass_generate_code;override;
  36. end;
  37. tcgsubscriptnode = class(tsubscriptnode)
  38. procedure pass_generate_code;override;
  39. end;
  40. tcgwithnode = class(twithnode)
  41. procedure pass_generate_code;override;
  42. end;
  43. tcgvecnode = class(tvecnode)
  44. function get_mul_size : aint;
  45. private
  46. procedure rangecheck_array;
  47. protected
  48. {# This routine is used to calculate the address of the reference.
  49. On entry reg contains the index in the array,
  50. and l contains the size of each element in the array.
  51. This routine should update location.reference correctly,
  52. so it points to the correct address.
  53. }
  54. procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);virtual;
  55. procedure update_reference_reg_packed(maybe_const_reg:tregister;l:aint);virtual;
  56. procedure second_wideansistring;virtual;
  57. procedure second_dynamicarray;virtual;
  58. public
  59. procedure pass_generate_code;override;
  60. end;
  61. implementation
  62. uses
  63. systems,
  64. cutils,cclasses,verbose,globals,constexp,
  65. symconst,symdef,symsym,symtable,defutil,paramgr,
  66. aasmbase,aasmtai,aasmdata,
  67. procinfo,pass_2,parabase,
  68. pass_1,nld,ncon,nadd,nutils,
  69. cgutils,cgobj,
  70. tgobj,ncgutil,objcgutl
  71. ;
  72. {*****************************************************************************
  73. TCGLOADVMTADDRNODE
  74. *****************************************************************************}
  75. procedure tcgloadvmtaddrnode.pass_generate_code;
  76. var
  77. href : treference;
  78. pool : THashSet;
  79. entry : PHashSetItem;
  80. begin
  81. location_reset(location,LOC_REGISTER,OS_ADDR);
  82. if (left.nodetype=typen) then
  83. begin
  84. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  85. if not is_objcclass(left.resultdef) then
  86. begin
  87. reference_reset_symbol(href,
  88. current_asmdata.RefAsmSymbol(tobjectdef(tclassrefdef(resultdef).pointeddef).vmt_mangledname),0,
  89. sizeof(pint));
  90. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
  91. end
  92. else
  93. begin
  94. if current_asmdata.ConstPools[sp_objcclassnamerefs]=nil then
  95. current_asmdata.ConstPools[sp_objcclassnamerefs]:=THashSet.Create(64, True, False);
  96. pool:=current_asmdata.ConstPools[sp_objcclassnamerefs];
  97. entry:=pool.FindOrAdd(@tobjectdef(left.resultdef).objextname^[1],length(tobjectdef(left.resultdef).objextname^));
  98. if (target_info.system in systems_objc_nfabi) then
  99. begin
  100. { find/add necessary classref/classname pool entries }
  101. objcfinishclassrefnfpoolentry(entry,tobjectdef(left.resultdef));
  102. end
  103. else
  104. begin
  105. { find/add necessary classref/classname pool entries }
  106. objcfinishstringrefpoolentry(entry,sp_objcclassnames,sec_objc_cls_refs,sec_objc_class_names);
  107. end;
  108. reference_reset_symbol(href,tasmlabel(entry^.Data),0,sizeof(pint));
  109. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
  110. end;
  111. end
  112. else
  113. begin
  114. { left contains self, load vmt from self }
  115. secondpass(left);
  116. gen_load_vmt_register(current_asmdata.CurrAsmList,tobjectdef(left.resultdef),left.location,location.register);
  117. end;
  118. end;
  119. {*****************************************************************************
  120. TCGLOADPARENTFPNODE
  121. *****************************************************************************}
  122. procedure tcgloadparentfpnode.pass_generate_code;
  123. var
  124. currpi : tprocinfo;
  125. hsym : tparavarsym;
  126. href : treference;
  127. begin
  128. if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
  129. begin
  130. location_reset(location,LOC_REGISTER,OS_ADDR);
  131. location.register:=current_procinfo.framepointer;
  132. end
  133. else
  134. begin
  135. currpi:=current_procinfo;
  136. location_reset(location,LOC_REGISTER,OS_ADDR);
  137. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  138. { load framepointer of current proc }
  139. hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
  140. if not assigned(hsym) then
  141. internalerror(200309281);
  142. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,hsym.localloc,location.register);
  143. { walk parents }
  144. while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
  145. begin
  146. currpi:=currpi.parent;
  147. if not assigned(currpi) then
  148. internalerror(200311201);
  149. hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
  150. if not assigned(hsym) then
  151. internalerror(200309282);
  152. if hsym.localloc.loc<>LOC_REFERENCE then
  153. internalerror(200309283);
  154. reference_reset_base(href,location.register,hsym.localloc.reference.offset,sizeof(pint));
  155. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
  156. end;
  157. end;
  158. end;
  159. {*****************************************************************************
  160. TCGADDRNODE
  161. *****************************************************************************}
  162. procedure tcgaddrnode.pass_generate_code;
  163. begin
  164. secondpass(left);
  165. location_reset(location,LOC_REGISTER,OS_ADDR);
  166. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  167. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  168. { on x86_64-win64, array of chars can be returned in registers, however,
  169. when passing these arrays to other functions, the compiler wants to take
  170. the address of the array so when the addrnode has been created internally,
  171. we have to force the data into memory, see also tw14388.pp
  172. }
  173. if nf_internal in flags then
  174. location_force_mem(current_asmdata.CurrAsmList,left.location)
  175. else
  176. internalerror(2006111510);
  177. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
  178. end;
  179. {*****************************************************************************
  180. TCGDEREFNODE
  181. *****************************************************************************}
  182. procedure tcgderefnode.pass_generate_code;
  183. var
  184. paraloc1 : tcgpara;
  185. begin
  186. secondpass(left);
  187. { assume natural alignment, except for packed records }
  188. if not(resultdef.typ in [recorddef,objectdef]) or
  189. (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
  190. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),resultdef.alignment)
  191. else
  192. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),1);
  193. if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE,LOC_CONSTANT]) then
  194. location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,true);
  195. case left.location.loc of
  196. LOC_CREGISTER,
  197. LOC_REGISTER:
  198. begin
  199. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
  200. {$ifdef cpu_uses_separate_address_registers}
  201. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  202. begin
  203. location.reference.base := cg.getaddressregister(current_asmdata.CurrAsmList);
  204. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,
  205. location.reference.base);
  206. end
  207. else
  208. {$endif}
  209. location.reference.base := left.location.register;
  210. end;
  211. LOC_CREFERENCE,
  212. LOC_REFERENCE:
  213. begin
  214. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  215. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference.base);
  216. end;
  217. LOC_CONSTANT:
  218. begin
  219. location.reference.offset:=left.location.value;
  220. end;
  221. else
  222. internalerror(200507031);
  223. end;
  224. if (cs_use_heaptrc in current_settings.globalswitches) and
  225. (cs_checkpointer in current_settings.localswitches) and
  226. not(cs_compilesystem in current_settings.moduleswitches) and
  227. not(tpointerdef(left.resultdef).is_far) and
  228. not(nf_no_checkpointer in flags) and
  229. { can be NR_NO in case of LOC_CONSTANT }
  230. (location.reference.base<>NR_NO) then
  231. begin
  232. paraloc1.init;
  233. paramanager.getintparaloc(pocall_default,1,paraloc1);
  234. cg.a_load_reg_cgpara(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  235. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  236. paraloc1.done;
  237. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  238. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER',false);
  239. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  240. end;
  241. end;
  242. {*****************************************************************************
  243. TCGSUBSCRIPTNODE
  244. *****************************************************************************}
  245. procedure tcgsubscriptnode.pass_generate_code;
  246. var
  247. sym: tasmsymbol;
  248. paraloc1 : tcgpara;
  249. hreg : tregister;
  250. tmpref: treference;
  251. sref: tsubsetreference;
  252. begin
  253. secondpass(left);
  254. if codegenerror then
  255. exit;
  256. paraloc1.init;
  257. { classes and interfaces must be dereferenced implicitly }
  258. if is_class_or_interface_or_dispinterface_or_objc(left.resultdef) then
  259. begin
  260. { the contents of a class are aligned to a sizeof(pointer) }
  261. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),sizeof(pint));
  262. case left.location.loc of
  263. LOC_CREGISTER,
  264. LOC_REGISTER:
  265. begin
  266. {$ifdef cpu_uses_separate_address_registers}
  267. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  268. begin
  269. location.reference.base:=rg.getaddressregister(current_asmdata.CurrAsmList);
  270. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
  271. left.location.register,location.reference.base);
  272. end
  273. else
  274. {$endif}
  275. location.reference.base := left.location.register;
  276. end;
  277. LOC_CREFERENCE,
  278. LOC_REFERENCE:
  279. begin
  280. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  281. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference.base);
  282. end;
  283. LOC_CONSTANT:
  284. begin
  285. { can happen with @classtype(pointerconst).field }
  286. location.reference.offset:=left.location.value;
  287. end;
  288. else
  289. internalerror(2009092401);
  290. end;
  291. { implicit deferencing }
  292. if (cs_use_heaptrc in current_settings.globalswitches) and
  293. (cs_checkpointer in current_settings.localswitches) and
  294. not(cs_compilesystem in current_settings.moduleswitches) then
  295. begin
  296. paramanager.getintparaloc(pocall_default,1,paraloc1);
  297. cg.a_load_reg_cgpara(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  298. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  299. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  300. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER',false);
  301. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  302. end;
  303. end
  304. else if is_interfacecom(left.resultdef) then
  305. begin
  306. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),sizeof(pint));
  307. tg.GetTempTyped(current_asmdata.CurrAsmList,left.resultdef,tt_normal,location.reference);
  308. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference);
  309. { implicit deferencing also for interfaces }
  310. if (cs_use_heaptrc in current_settings.globalswitches) and
  311. (cs_checkpointer in current_settings.localswitches) and
  312. not(cs_compilesystem in current_settings.moduleswitches) then
  313. begin
  314. paramanager.getintparaloc(pocall_default,1,paraloc1);
  315. cg.a_load_reg_cgpara(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  316. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  317. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  318. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER',false);
  319. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  320. end;
  321. end
  322. else
  323. begin
  324. location_copy(location,left.location);
  325. { some abi's require that functions return (some) records in }
  326. { registers }
  327. case location.loc of
  328. LOC_REFERENCE,
  329. LOC_CREFERENCE:
  330. ;
  331. LOC_REGISTER,
  332. LOC_CREGISTER,
  333. LOC_MMREGISTER,
  334. LOC_FPUREGISTER:
  335. begin
  336. // in case the result is not something that can be put
  337. // into an integer register (e.g.
  338. // function_returning_record().non_regable_field, or
  339. // a function returning a value > sizeof(intreg))
  340. // -> force to memory
  341. if not tstoreddef(left.resultdef).is_intregable or
  342. not tstoreddef(resultdef).is_intregable or
  343. (location.loc in [LOC_MMREGISTER,LOC_FPUREGISTER]) then
  344. location_force_mem(current_asmdata.CurrAsmList,location)
  345. else
  346. begin
  347. if (left.location.loc = LOC_REGISTER) then
  348. location.loc := LOC_SUBSETREG
  349. else
  350. location.loc := LOC_CSUBSETREG;
  351. location.size:=def_cgsize(resultdef);
  352. location.sreg.subsetreg := left.location.register;
  353. location.sreg.subsetregsize := left.location.size;
  354. if not is_packed_record_or_object(left.resultdef) then
  355. begin
  356. if (target_info.endian = ENDIAN_BIG) then
  357. location.sreg.startbit := (tcgsize2size[location.sreg.subsetregsize] - tcgsize2size[location.size] - vs.fieldoffset) * 8
  358. else
  359. location.sreg.startbit := (vs.fieldoffset * 8);
  360. location.sreg.bitlen := tcgsize2size[location.size] * 8;
  361. end
  362. else
  363. begin
  364. location.sreg.bitlen := resultdef.packedbitsize;
  365. if (target_info.endian = ENDIAN_BIG) then
  366. location.sreg.startbit := (tcgsize2size[location.sreg.subsetregsize]*8 - location.sreg.bitlen) - vs.fieldoffset
  367. else
  368. location.sreg.startbit := vs.fieldoffset;
  369. end;
  370. end;
  371. end;
  372. LOC_SUBSETREG,
  373. LOC_CSUBSETREG:
  374. begin
  375. location.size:=def_cgsize(resultdef);
  376. if not is_packed_record_or_object(left.resultdef) then
  377. begin
  378. if (target_info.endian = ENDIAN_BIG) then
  379. inc(location.sreg.startbit, (left.resultdef.size - tcgsize2size[location.size] - vs.fieldoffset) * 8)
  380. else
  381. inc(location.sreg.startbit, vs.fieldoffset * 8);
  382. location.sreg.bitlen := tcgsize2size[location.size] * 8;
  383. end
  384. else
  385. begin
  386. location.sreg.bitlen := resultdef.packedbitsize;
  387. if (target_info.endian = ENDIAN_BIG) then
  388. inc(location.sreg.startbit, left.location.sreg.bitlen - location.sreg.bitlen - vs.fieldoffset)
  389. else
  390. inc(location.sreg.startbit, vs.fieldoffset);
  391. end;
  392. end;
  393. else
  394. internalerror(2006031901);
  395. end;
  396. end;
  397. if is_objc_class_or_protocol(left.resultdef) and
  398. (target_info.system in systems_objc_nfabi) then
  399. begin
  400. if (location.loc<>LOC_REFERENCE) or
  401. (location.reference.index<>NR_NO) then
  402. internalerror(2009092402);
  403. { the actual field offset is stored in memory (to solve the
  404. "fragile base class" problem: this way the layout of base
  405. classes can be changed without breaking programs compiled against
  406. earlier versions)
  407. }
  408. hreg:=cg.g_indirect_sym_load(current_asmdata.CurrAsmList,vs.mangledname,false);
  409. { TODO: clean up. g_indirect_sym_load cannot perform
  410. a plain load for targets that don't need an indirect load
  411. because it's also used in ncgld, but this is not very nice...
  412. }
  413. if (hreg=NR_NO) then
  414. begin
  415. sym:=current_asmdata.RefAsmSymbol(vs.mangledname);
  416. reference_reset_symbol(tmpref,sym,0,sizeof(pint));
  417. location.reference.index:=cg.getaddressregister(current_asmdata.CurrAsmList);
  418. end
  419. else
  420. begin
  421. reference_reset_base(tmpref,hreg,0,sizeof(pint));
  422. location.reference.index:=hreg;
  423. end;
  424. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,location.reference.index);
  425. { always packrecords C -> natural alignment }
  426. location.reference.alignment:=vs.vardef.alignment;
  427. end
  428. else if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  429. begin
  430. if not is_packed_record_or_object(left.resultdef) then
  431. begin
  432. inc(location.reference.offset,vs.fieldoffset);
  433. location.reference.alignment:=newalignment(location.reference.alignment,vs.fieldoffset);
  434. end
  435. else if (vs.fieldoffset mod 8 = 0) and
  436. (resultdef.packedbitsize mod 8 = 0) and
  437. { is different in case of e.g. packenum 2 and an enum }
  438. { which fits in 8 bits }
  439. (resultdef.size*8 = resultdef.packedbitsize) then
  440. begin
  441. inc(location.reference.offset,vs.fieldoffset div 8);
  442. location.reference.alignment:=newalignment(location.reference.alignment,vs.fieldoffset div 8);
  443. end
  444. else
  445. begin
  446. sref.ref:=location.reference;
  447. sref.ref.alignment:=1;
  448. sref.bitindexreg:=NR_NO;
  449. inc(sref.ref.offset,vs.fieldoffset div 8);
  450. sref.startbit:=vs.fieldoffset mod 8;
  451. sref.bitlen:=resultdef.packedbitsize;
  452. if (left.location.loc=LOC_REFERENCE) then
  453. location.loc:=LOC_SUBSETREF
  454. else
  455. location.loc:=LOC_CSUBSETREF;
  456. location.sref:=sref;
  457. end;
  458. { also update the size of the location }
  459. location.size:=def_cgsize(resultdef);
  460. end;
  461. paraloc1.done;
  462. end;
  463. {*****************************************************************************
  464. TCGWITHNODE
  465. *****************************************************************************}
  466. procedure tcgwithnode.pass_generate_code;
  467. begin
  468. location_reset(location,LOC_VOID,OS_NO);
  469. if assigned(left) then
  470. secondpass(left);
  471. end;
  472. {*****************************************************************************
  473. TCGVECNODE
  474. *****************************************************************************}
  475. function tcgvecnode.get_mul_size : aint;
  476. begin
  477. if nf_memindex in flags then
  478. get_mul_size:=1
  479. else
  480. begin
  481. if (left.resultdef.typ=arraydef) then
  482. if not is_packed_array(left.resultdef) then
  483. get_mul_size:=tarraydef(left.resultdef).elesize
  484. else
  485. get_mul_size:=tarraydef(left.resultdef).elepackedbitsize
  486. else
  487. get_mul_size:=resultdef.size;
  488. end
  489. end;
  490. { this routine must, like any other routine, not change the contents }
  491. { of base/index registers of references, as these may be regvars. }
  492. { The register allocator can coalesce one LOC_REGISTER being moved }
  493. { into another (as their live ranges won't overlap), but not a }
  494. { LOC_CREGISTER moved into a LOC_(C)REGISTER most of the time (as }
  495. { the live range of the LOC_CREGISTER will most likely overlap the }
  496. { the live range of the target LOC_(C)REGISTER) }
  497. { The passed register may be a LOC_CREGISTER as well. }
  498. procedure tcgvecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
  499. var
  500. hreg: tregister;
  501. begin
  502. if l<>1 then
  503. begin
  504. hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  505. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,maybe_const_reg,hreg);
  506. maybe_const_reg:=hreg;
  507. end;
  508. if location.reference.base=NR_NO then
  509. location.reference.base:=maybe_const_reg
  510. else if location.reference.index=NR_NO then
  511. location.reference.index:=maybe_const_reg
  512. else
  513. begin
  514. hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  515. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,hreg);
  516. reference_reset_base(location.reference,hreg,0,location.reference.alignment);
  517. { insert new index register }
  518. location.reference.index:=maybe_const_reg;
  519. end;
  520. { update alignment }
  521. if (location.reference.alignment=0) then
  522. internalerror(2009020704);
  523. location.reference.alignment:=newalignment(location.reference.alignment,l);
  524. end;
  525. { see remarks for tcgvecnode.update_reference_reg_mul above }
  526. procedure tcgvecnode.update_reference_reg_packed(maybe_const_reg:tregister;l:aint);
  527. var
  528. sref: tsubsetreference;
  529. offsetreg, hreg: tregister;
  530. alignpower: aint;
  531. temp : longint;
  532. begin
  533. { only orddefs are bitpacked. Even then we only need special code in }
  534. { case the bitpacked *byte size* is not a power of two, otherwise }
  535. { everything can be handled using the the regular array code. }
  536. if ((l mod 8) = 0) and
  537. (ispowerof2(l div 8,temp) or
  538. not is_ordinal(resultdef)
  539. {$ifndef cpu64bitalu}
  540. or is_64bitint(resultdef)
  541. {$endif not cpu64bitalu}
  542. ) then
  543. begin
  544. update_reference_reg_mul(maybe_const_reg,l div 8);
  545. exit;
  546. end;
  547. if (l > 8*sizeof(aint)) then
  548. internalerror(200608051);
  549. sref.ref := location.reference;
  550. hreg := cg.getaddressregister(current_asmdata.CurrAsmList);
  551. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,tarraydef(left.resultdef).lowrange,maybe_const_reg,hreg);
  552. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_INT,l,hreg);
  553. { keep alignment for index }
  554. sref.ref.alignment := left.resultdef.alignment;
  555. if not ispowerof2(sref.ref.alignment,temp) then
  556. internalerror(2006081201);
  557. alignpower:=temp;
  558. offsetreg := cg.getaddressregister(current_asmdata.CurrAsmList);
  559. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_ADDR,3+alignpower,hreg,offsetreg);
  560. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,alignpower,offsetreg);
  561. if (sref.ref.base = NR_NO) then
  562. sref.ref.base := offsetreg
  563. else if (sref.ref.index = NR_NO) then
  564. sref.ref.index := offsetreg
  565. else
  566. begin
  567. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,sref.ref.base,offsetreg);
  568. sref.ref.base := offsetreg;
  569. end;
  570. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,(1 shl (3+alignpower))-1,hreg);
  571. sref.bitindexreg := hreg;
  572. sref.startbit := 0;
  573. sref.bitlen := resultdef.packedbitsize;
  574. if (left.location.loc = LOC_REFERENCE) then
  575. location.loc := LOC_SUBSETREF
  576. else
  577. location.loc := LOC_CSUBSETREF;
  578. location.sref := sref;
  579. end;
  580. procedure tcgvecnode.second_wideansistring;
  581. begin
  582. end;
  583. procedure tcgvecnode.second_dynamicarray;
  584. begin
  585. end;
  586. procedure tcgvecnode.rangecheck_array;
  587. var
  588. hightree : tnode;
  589. poslabel,
  590. neglabel : tasmlabel;
  591. hreg : tregister;
  592. paraloc1,paraloc2 : tcgpara;
  593. begin
  594. paraloc1.init;
  595. paraloc2.init;
  596. if is_open_array(left.resultdef) or
  597. is_array_of_const(left.resultdef) then
  598. begin
  599. { cdecl functions don't have high() so we can not check the range }
  600. { (can't use current_procdef, since it may be a nested procedure) }
  601. if not(tprocdef(tparasymtable(tparavarsym(tloadnode(left).symtableentry).owner).defowner).proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  602. begin
  603. { Get high value }
  604. hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
  605. { it must be available }
  606. if not assigned(hightree) then
  607. internalerror(200212201);
  608. firstpass(hightree);
  609. secondpass(hightree);
  610. { generate compares }
  611. if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  612. hreg:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_INT)
  613. else
  614. begin
  615. hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  616. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,right.location,hreg);
  617. end;
  618. current_asmdata.getjumplabel(neglabel);
  619. current_asmdata.getjumplabel(poslabel);
  620. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_LT,0,hreg,poslabel);
  621. cg.a_cmp_loc_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_BE,hightree.location,hreg,neglabel);
  622. cg.a_label(current_asmdata.CurrAsmList,poslabel);
  623. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RANGEERROR',false);
  624. cg.a_label(current_asmdata.CurrAsmList,neglabel);
  625. { release hightree }
  626. hightree.free;
  627. end;
  628. end
  629. else
  630. if is_dynamic_array(left.resultdef) then
  631. begin
  632. paramanager.getintparaloc(pocall_default,1,paraloc1);
  633. paramanager.getintparaloc(pocall_default,2,paraloc2);
  634. cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
  635. cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
  636. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  637. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
  638. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  639. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DYNARRAY_RANGECHECK',false);
  640. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  641. end;
  642. { for regular arrays, we don't have to do anything because the index has been
  643. type converted to the index type, which already inserted a range check if
  644. necessary }
  645. paraloc1.done;
  646. paraloc2.done;
  647. end;
  648. procedure tcgvecnode.pass_generate_code;
  649. var
  650. offsetdec,
  651. extraoffset : aint;
  652. t : tnode;
  653. href : treference;
  654. otl,ofl : tasmlabel;
  655. newsize : tcgsize;
  656. mulsize,
  657. bytemulsize,
  658. alignpow : aint;
  659. isjump : boolean;
  660. paraloc1,
  661. paraloc2 : tcgpara;
  662. subsetref : tsubsetreference;
  663. temp : longint;
  664. begin
  665. paraloc1.init;
  666. paraloc2.init;
  667. mulsize:=get_mul_size;
  668. if not is_packed_array(left.resultdef) then
  669. bytemulsize:=mulsize
  670. else
  671. bytemulsize:=mulsize div 8;
  672. newsize:=def_cgsize(resultdef);
  673. secondpass(left);
  674. if left.location.loc=LOC_CREFERENCE then
  675. location_reset_ref(location,LOC_CREFERENCE,newsize,left.location.reference.alignment)
  676. else
  677. location_reset_ref(location,LOC_REFERENCE,newsize,left.location.reference.alignment);
  678. { an ansistring needs to be dereferenced }
  679. if is_ansistring(left.resultdef) or
  680. is_widestring(left.resultdef) or
  681. is_unicodestring(left.resultdef) then
  682. begin
  683. if nf_callunique in flags then
  684. internalerror(200304236);
  685. {DM!!!!!}
  686. case left.location.loc of
  687. LOC_REGISTER,
  688. LOC_CREGISTER :
  689. begin
  690. {$ifdef m68k}
  691. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  692. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,location.reference.base);
  693. {$else m68k}
  694. location.reference.base:=left.location.register;
  695. {$endif m68k}
  696. end;
  697. LOC_CREFERENCE,
  698. LOC_REFERENCE :
  699. begin
  700. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  701. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.reference.base);
  702. end;
  703. else
  704. internalerror(2002032218);
  705. end;
  706. { check for a zero length string,
  707. we can use the ansistring routine here }
  708. if (cs_check_range in current_settings.localswitches) then
  709. begin
  710. paramanager.getintparaloc(pocall_default,1,paraloc1);
  711. cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,location.reference.base,paraloc1);
  712. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  713. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  714. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_CHECKZERO',false);
  715. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  716. end;
  717. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  718. if is_ansistring(left.resultdef) then
  719. offsetdec:=1
  720. else
  721. offsetdec:=2;
  722. location.reference.alignment:=offsetdec;
  723. dec(location.reference.offset,offsetdec);
  724. end
  725. else if is_dynamic_array(left.resultdef) then
  726. begin
  727. case left.location.loc of
  728. LOC_REGISTER,
  729. LOC_CREGISTER :
  730. location.reference.base:=left.location.register;
  731. LOC_REFERENCE,
  732. LOC_CREFERENCE :
  733. begin
  734. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  735. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
  736. left.location.reference,location.reference.base);
  737. end;
  738. else
  739. internalerror(2002032219);
  740. end;
  741. { a dynarray points to the start of a memory block, which
  742. we assume to be always aligned to a multiple of the
  743. pointer size
  744. }
  745. location.reference.alignment:=sizeof(pint);
  746. end
  747. else
  748. begin
  749. { may happen in case of function results }
  750. case left.location.loc of
  751. LOC_REGISTER,
  752. LOC_MMREGISTER:
  753. location_force_mem(current_asmdata.CurrAsmList,left.location);
  754. end;
  755. location_copy(location,left.location);
  756. end;
  757. { location must be memory }
  758. if not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  759. internalerror(200411013);
  760. { offset can only differ from 0 if arraydef }
  761. if (left.resultdef.typ=arraydef) and
  762. not(is_dynamic_array(left.resultdef)) and
  763. (not(is_packed_array(left.resultdef)) or
  764. ((mulsize mod 8 = 0) and
  765. ispowerof2(mulsize div 8,temp)) or
  766. { only orddefs are bitpacked }
  767. not is_ordinal(resultdef)
  768. {$ifndef cpu64bitalu}
  769. or is_64bitint(resultdef)
  770. {$endif not cpu64bitalu}
  771. ) then
  772. dec(location.reference.offset,bytemulsize*tarraydef(left.resultdef).lowrange);
  773. if right.nodetype=ordconstn then
  774. begin
  775. { offset can only differ from 0 if arraydef }
  776. case left.resultdef.typ of
  777. arraydef :
  778. begin
  779. { do not do any range checking when this is an array access to a pointer which has been
  780. typecasted from an array }
  781. if (not (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions)) then
  782. begin
  783. if not(is_open_array(left.resultdef)) and
  784. not(is_array_of_const(left.resultdef)) and
  785. not(is_dynamic_array(left.resultdef)) then
  786. begin
  787. if (tordconstnode(right).value.svalue>tarraydef(left.resultdef).highrange) or
  788. (tordconstnode(right).value.svalue<tarraydef(left.resultdef).lowrange) then
  789. begin
  790. { this should be caught in the typecheckpass! (JM) }
  791. if (cs_check_range in current_settings.localswitches) then
  792. CGMessage(parser_e_range_check_error)
  793. else
  794. CGMessage(parser_w_range_check_error);
  795. end;
  796. end
  797. else
  798. begin
  799. { range checking for open and dynamic arrays needs
  800. runtime code }
  801. secondpass(right);
  802. if (cs_check_range in current_settings.localswitches) then
  803. rangecheck_array;
  804. end;
  805. end;
  806. end;
  807. stringdef :
  808. begin
  809. if (cs_check_range in current_settings.localswitches) then
  810. begin
  811. case tstringdef(left.resultdef).stringtype of
  812. { it's the same for ansi- and wide strings }
  813. st_unicodestring,
  814. st_widestring,
  815. st_ansistring:
  816. begin
  817. paramanager.getintparaloc(pocall_default,1,paraloc1);
  818. paramanager.getintparaloc(pocall_default,2,paraloc2);
  819. cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_INT,tordconstnode(right).value.svalue,paraloc2);
  820. href:=location.reference;
  821. if not(tf_winlikewidestring in target_info.flags) or
  822. (tstringdef(left.resultdef).stringtype<>st_widestring) then
  823. begin
  824. dec(href.offset,sizeof(pint)-offsetdec);
  825. cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
  826. end
  827. else
  828. begin
  829. { winlike widestrings have a 4 byte length }
  830. dec(href.offset,4-offsetdec);
  831. cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  832. end;
  833. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  834. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
  835. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  836. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
  837. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  838. end;
  839. st_shortstring:
  840. begin
  841. {!!!!!!!!!!!!!!!!!}
  842. { if this one is implemented making use of the high parameter for openshortstrings, update ncgutils.do_get_used_regvars() too (JM) }
  843. end;
  844. st_longstring:
  845. begin
  846. {!!!!!!!!!!!!!!!!!}
  847. end;
  848. end;
  849. end;
  850. end;
  851. end;
  852. if not(is_packed_array(left.resultdef)) or
  853. ((mulsize mod 8 = 0) and
  854. (ispowerof2(mulsize div 8,temp) or
  855. { only orddefs are bitpacked }
  856. not is_ordinal(resultdef))) then
  857. begin
  858. extraoffset:=bytemulsize*tordconstnode(right).value.svalue;
  859. inc(location.reference.offset,extraoffset);
  860. { adjust alignment after to this change }
  861. location.reference.alignment:=newalignment(location.reference.alignment,extraoffset);
  862. { don't do this for floats etc.; needed to properly set the }
  863. { size for bitpacked arrays (e.g. a bitpacked array of }
  864. { enums who are size 2 but fit in one byte -> in the array }
  865. { they will be one byte and have to be stored like that) }
  866. if is_packed_array(left.resultdef) and
  867. (tcgsize2size[newsize] <> bytemulsize) then
  868. newsize:=int_cgsize(bytemulsize);
  869. end
  870. else
  871. begin
  872. subsetref.ref := location.reference;
  873. subsetref.ref.alignment := left.resultdef.alignment;
  874. if not ispowerof2(subsetref.ref.alignment,temp) then
  875. internalerror(2006081212);
  876. alignpow:=temp;
  877. inc(subsetref.ref.offset,((mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) shr (3+alignpow)) shl alignpow);
  878. subsetref.bitindexreg := NR_NO;
  879. subsetref.startbit := (mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) and ((1 shl (3+alignpow))-1);
  880. subsetref.bitlen := resultdef.packedbitsize;
  881. if (left.location.loc = LOC_REFERENCE) then
  882. location.loc := LOC_SUBSETREF
  883. else
  884. location.loc := LOC_CSUBSETREF;
  885. location.sref := subsetref;
  886. end;
  887. end
  888. else
  889. { not nodetype=ordconstn }
  890. begin
  891. if (cs_opt_level1 in current_settings.optimizerswitches) and
  892. { if we do range checking, we don't }
  893. { need that fancy code (it would be }
  894. { buggy) }
  895. not(cs_check_range in current_settings.localswitches) and
  896. (left.resultdef.typ=arraydef) and
  897. not is_packed_array(left.resultdef) then
  898. begin
  899. extraoffset:=0;
  900. if (right.nodetype=addn) then
  901. begin
  902. if taddnode(right).right.nodetype=ordconstn then
  903. begin
  904. extraoffset:=tordconstnode(taddnode(right).right).value.svalue;
  905. t:=taddnode(right).left;
  906. taddnode(right).left:=nil;
  907. right.free;
  908. right:=t;
  909. end
  910. else if taddnode(right).left.nodetype=ordconstn then
  911. begin
  912. extraoffset:=tordconstnode(taddnode(right).left).value.svalue;
  913. t:=taddnode(right).right;
  914. taddnode(right).right:=nil;
  915. right.free;
  916. right:=t;
  917. end;
  918. end
  919. else if (right.nodetype=subn) then
  920. begin
  921. if taddnode(right).right.nodetype=ordconstn then
  922. begin
  923. extraoffset:=-tordconstnode(taddnode(right).right).value.svalue;
  924. t:=taddnode(right).left;
  925. taddnode(right).left:=nil;
  926. right.free;
  927. right:=t;
  928. end;
  929. end;
  930. inc(location.reference.offset,
  931. mulsize*extraoffset);
  932. end;
  933. { calculate from left to right }
  934. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  935. internalerror(200304237);
  936. isjump:=(right.expectloc=LOC_JUMP);
  937. if isjump then
  938. begin
  939. otl:=current_procinfo.CurrTrueLabel;
  940. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  941. ofl:=current_procinfo.CurrFalseLabel;
  942. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  943. end;
  944. secondpass(right);
  945. { if mulsize = 1, we won't have to modify the index }
  946. location_force_reg(current_asmdata.CurrAsmList,right.location,OS_ADDR,true);
  947. if isjump then
  948. begin
  949. current_procinfo.CurrTrueLabel:=otl;
  950. current_procinfo.CurrFalseLabel:=ofl;
  951. end
  952. else if (right.location.loc = LOC_JUMP) then
  953. internalerror(2006010801);
  954. { produce possible range check code: }
  955. if cs_check_range in current_settings.localswitches then
  956. begin
  957. if left.resultdef.typ=arraydef then
  958. begin
  959. { do not do any range checking when this is an array access to a pointer which has been
  960. typecasted from an array }
  961. if (not (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions)) then
  962. rangecheck_array
  963. end
  964. else if (left.resultdef.typ=stringdef) then
  965. begin
  966. case tstringdef(left.resultdef).stringtype of
  967. { it's the same for ansi- and wide strings }
  968. st_unicodestring,
  969. st_widestring,
  970. st_ansistring:
  971. begin
  972. paramanager.getintparaloc(pocall_default,1,paraloc1);
  973. paramanager.getintparaloc(pocall_default,2,paraloc2);
  974. cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_INT,right.location.register,paraloc2);
  975. href:=location.reference;
  976. dec(href.offset,sizeof(pint)-offsetdec);
  977. href:=location.reference;
  978. if not(tf_winlikewidestring in target_info.flags) or
  979. (tstringdef(left.resultdef).stringtype<>st_widestring) then
  980. begin
  981. dec(href.offset,sizeof(pint)-offsetdec);
  982. cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
  983. end
  984. else
  985. begin
  986. { winlike widestrings have a 4 byte length }
  987. dec(href.offset,4-offsetdec);
  988. cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  989. end;
  990. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  991. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
  992. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  993. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
  994. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  995. end;
  996. st_shortstring:
  997. begin
  998. {!!!!!!!!!!!!!!!!!}
  999. end;
  1000. st_longstring:
  1001. begin
  1002. {!!!!!!!!!!!!!!!!!}
  1003. end;
  1004. end;
  1005. end;
  1006. end;
  1007. { insert the register and the multiplication factor in the
  1008. reference }
  1009. if not is_packed_array(left.resultdef) then
  1010. update_reference_reg_mul(right.location.register,mulsize)
  1011. else
  1012. update_reference_reg_packed(right.location.register,mulsize);
  1013. end;
  1014. location.size:=newsize;
  1015. paraloc1.done;
  1016. paraloc2.done;
  1017. end;
  1018. begin
  1019. cloadvmtaddrnode:=tcgloadvmtaddrnode;
  1020. cloadparentfpnode:=tcgloadparentfpnode;
  1021. caddrnode:=tcgaddrnode;
  1022. cderefnode:=tcgderefnode;
  1023. csubscriptnode:=tcgsubscriptnode;
  1024. cwithnode:=tcgwithnode;
  1025. cvecnode:=tcgvecnode;
  1026. end.