ncgmem.pas 49 KB

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