ncgmem.pas 51 KB

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