ncgmem.pas 48 KB

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