ncgmem.pas 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  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:=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.parast.Find('parentfp'));
  164. if not assigned(hsym) then
  165. internalerror(200309282);
  166. if hsym.localloc.loc<>LOC_REFERENCE then
  167. internalerror(200309283);
  168. hlcg.reference_reset_base(href,parentfpvoidpointertype,location.register,hsym.localloc.reference.offset,ctempposinvalid,parentfpvoidpointertype.alignment,[]);
  169. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,parentfpvoidpointertype,parentfpvoidpointertype,href,location.register);
  170. end;
  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.getcgtempparaloc(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,ctempposinvalid,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,ctempposinvalid,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.getcgtempparaloc(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. TCGVECNODE
  562. *****************************************************************************}
  563. function tcgvecnode.get_mul_size : asizeint;
  564. begin
  565. if nf_memindex in flags then
  566. get_mul_size:=1
  567. else
  568. begin
  569. if (left.resultdef.typ=arraydef) then
  570. if not is_packed_array(left.resultdef) then
  571. get_mul_size:=tarraydef(left.resultdef).elesize
  572. else
  573. get_mul_size:=tarraydef(left.resultdef).elepackedbitsize
  574. else
  575. get_mul_size:=resultdef.size;
  576. end
  577. end;
  578. { this routine must, like any other routine, not change the contents }
  579. { of base/index registers of references, as these may be regvars. }
  580. { The register allocator can coalesce one LOC_REGISTER being moved }
  581. { into another (as their live ranges won't overlap), but not a }
  582. { LOC_CREGISTER moved into a LOC_(C)REGISTER most of the time (as }
  583. { the live range of the LOC_CREGISTER will most likely overlap the }
  584. { the live range of the target LOC_(C)REGISTER) }
  585. { The passed register may be a LOC_CREGISTER as well. }
  586. procedure tcgvecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
  587. var
  588. hreg: tregister;
  589. begin
  590. if l<>1 then
  591. begin
  592. hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  593. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,maybe_const_reg,hreg);
  594. maybe_const_reg:=hreg;
  595. end;
  596. if location.reference.base=NR_NO then
  597. location.reference.base:=maybe_const_reg
  598. else if location.reference.index=NR_NO then
  599. location.reference.index:=maybe_const_reg
  600. else
  601. begin
  602. hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  603. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,hreg);
  604. reference_reset_base(location.reference,hreg,0,location.reference.temppos,location.reference.alignment,location.reference.volatility);
  605. { insert new index register }
  606. location.reference.index:=maybe_const_reg;
  607. end;
  608. { update alignment }
  609. if (location.reference.alignment=0) then
  610. internalerror(2009020704);
  611. location.reference.alignment:=newalignment(location.reference.alignment,l);
  612. end;
  613. { see remarks for tcgvecnode.update_reference_reg_mul above }
  614. procedure tcgvecnode.update_reference_reg_packed(maybe_const_reg: tregister; regsize: tdef; l:aint);
  615. var
  616. sref: tsubsetreference;
  617. offsetreg, hreg: tregister;
  618. alignpower: aint;
  619. temp : longint;
  620. begin
  621. { only orddefs are bitpacked. Even then we only need special code in }
  622. { case the bitpacked *byte size* is not a power of two, otherwise }
  623. { everything can be handled using the the regular array code. }
  624. if ((l mod 8) = 0) and
  625. (ispowerof2(l div 8,temp) or
  626. not is_ordinal(resultdef)
  627. {$ifndef cpu64bitalu}
  628. or is_64bitint(resultdef)
  629. {$endif not cpu64bitalu}
  630. ) then
  631. begin
  632. update_reference_reg_mul(maybe_const_reg,regsize,l div 8);
  633. exit;
  634. end;
  635. if (l > 8*sizeof(aint)) then
  636. internalerror(200608051);
  637. sref.ref := location.reference;
  638. hreg := cg.getaddressregister(current_asmdata.CurrAsmList);
  639. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_ADDR,tarraydef(left.resultdef).lowrange,maybe_const_reg,hreg);
  640. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,hreg);
  641. { keep alignment for index }
  642. sref.ref.alignment := left.resultdef.alignment;
  643. if not ispowerof2(packedbitsloadsize(l),temp) then
  644. internalerror(2006081201);
  645. alignpower:=temp;
  646. offsetreg := cg.getaddressregister(current_asmdata.CurrAsmList);
  647. cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_ADDR,3+alignpower,hreg,offsetreg);
  648. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,alignpower,offsetreg);
  649. if (sref.ref.base = NR_NO) then
  650. sref.ref.base := offsetreg
  651. else if (sref.ref.index = NR_NO) then
  652. sref.ref.index := offsetreg
  653. else
  654. begin
  655. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,sref.ref.base,offsetreg);
  656. sref.ref.base := offsetreg;
  657. end;
  658. { the if expression below is a constant evaluated at compile time, so disable the unreachable code
  659. warning }
  660. {$push}
  661. {$warn 6018 off}
  662. { we can reuse hreg only if OS_INT and OS_ADDR have the same size/type }
  663. if OS_INT<>OS_ADDR then
  664. begin
  665. sref.bitindexreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  666. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_INT,hreg,sref.bitindexreg);
  667. end
  668. else
  669. sref.bitindexreg:=hreg;
  670. {$pop}
  671. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,(1 shl (3+alignpower))-1,sref.bitindexreg);
  672. sref.startbit := 0;
  673. sref.bitlen := resultdef.packedbitsize;
  674. if (left.location.loc = LOC_REFERENCE) then
  675. location.loc := LOC_SUBSETREF
  676. else
  677. location.loc := LOC_CSUBSETREF;
  678. location.sref := sref;
  679. end;
  680. procedure tcgvecnode.update_reference_offset(var ref: treference; index, mulsize: ASizeInt);
  681. begin
  682. inc(ref.offset,index*mulsize);
  683. end;
  684. procedure tcgvecnode.second_wideansistring;
  685. begin
  686. end;
  687. procedure tcgvecnode.second_dynamicarray;
  688. begin
  689. end;
  690. function tcgvecnode.valid_index_size(size: tcgsize): boolean;
  691. begin
  692. result:=
  693. tcgsize2signed[size]=tcgsize2signed[OS_ADDR];
  694. end;
  695. procedure tcgvecnode.rangecheck_array;
  696. var
  697. paraloc1,paraloc2 : tcgpara;
  698. pd : tprocdef;
  699. begin
  700. { omit range checking when this is an array access to a pointer which has been
  701. typecasted from an array }
  702. if (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions) then
  703. exit;
  704. paraloc1.init;
  705. paraloc2.init;
  706. if is_dynamic_array(left.resultdef) then
  707. begin
  708. pd:=search_system_proc('fpc_dynarray_rangecheck');
  709. paramanager.getcgtempparaloc(current_asmdata.CurrAsmList,pd,1,paraloc1);
  710. paramanager.getcgtempparaloc(current_asmdata.CurrAsmList,pd,2,paraloc2);
  711. if pd.is_pushleftright then
  712. begin
  713. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.resultdef,left.location,paraloc1);
  714. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.resultdef,right.location,paraloc2);
  715. end
  716. else
  717. begin
  718. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.resultdef,right.location,paraloc2);
  719. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.resultdef,left.location,paraloc1);
  720. end;
  721. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  722. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
  723. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,pd,[@paraloc1,@paraloc2],nil).resetiftemp;
  724. end;
  725. { for regular arrays, we don't have to do anything because the index has been
  726. type converted to the index type, which already inserted a range check if
  727. necessary }
  728. paraloc1.done;
  729. paraloc2.done;
  730. end;
  731. procedure tcgvecnode.rangecheck_string;
  732. var
  733. paraloc1,
  734. paraloc2: tcgpara;
  735. helpername: TIDString;
  736. pd: tprocdef;
  737. begin
  738. paraloc1.init;
  739. paraloc2.init;
  740. case tstringdef(left.resultdef).stringtype of
  741. { it's the same for ansi- and wide strings }
  742. st_unicodestring,
  743. st_widestring,
  744. st_ansistring:
  745. begin
  746. helpername:='fpc_'+tstringdef(left.resultdef).stringtypname+'_rangecheck';
  747. pd:=search_system_proc(helpername);
  748. paramanager.getcgtempparaloc(current_asmdata.CurrAsmList,pd,1,paraloc1);
  749. paramanager.getcgtempparaloc(current_asmdata.CurrAsmList,pd,2,paraloc2);
  750. if pd.is_pushleftright then
  751. begin
  752. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.resultdef,left.location,paraloc1);
  753. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.resultdef,right.location,paraloc2);
  754. end
  755. else
  756. begin
  757. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.resultdef,right.location,paraloc2);
  758. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.resultdef,left.location,paraloc1);
  759. end;
  760. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  761. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
  762. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,pd,[@paraloc1,@paraloc2],nil).resetiftemp;
  763. end;
  764. st_shortstring:
  765. begin
  766. {!!!!!!!!!!!!!!!!!}
  767. { if this one is implemented making use of the high parameter for openshortstrings, update ncgutils.do_get_used_regvars() too (JM) }
  768. end;
  769. st_longstring:
  770. begin
  771. {!!!!!!!!!!!!!!!!!}
  772. end;
  773. end;
  774. paraloc1.done;
  775. paraloc2.done;
  776. end;
  777. procedure tcgvecnode.pass_generate_code;
  778. var
  779. offsetdec,
  780. extraoffset : ASizeInt;
  781. rightp : pnode;
  782. newsize : tcgsize;
  783. mulsize,
  784. bytemulsize : ASizeInt;
  785. alignpow : aint;
  786. paraloc1,
  787. paraloc2 : tcgpara;
  788. subsetref : tsubsetreference;
  789. temp : longint;
  790. hreg : tregister;
  791. indexdef : tdef;
  792. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  793. i : Integer;
  794. {$endif}
  795. begin
  796. paraloc1.init;
  797. paraloc2.init;
  798. mulsize:=get_mul_size;
  799. if not is_packed_array(left.resultdef) then
  800. bytemulsize:=mulsize
  801. else
  802. bytemulsize:=mulsize div 8;
  803. newsize:=def_cgsize(resultdef);
  804. secondpass(left);
  805. if left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
  806. location_reset_ref(location,left.location.loc,newsize,left.location.reference.alignment,left.location.reference.volatility)
  807. else
  808. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment,[]);
  809. { an ansistring needs to be dereferenced }
  810. if is_ansistring(left.resultdef) or
  811. is_wide_or_unicode_string(left.resultdef) then
  812. begin
  813. if nf_callunique in flags then
  814. internalerror(200304236);
  815. {DM!!!!!}
  816. case left.location.loc of
  817. LOC_REGISTER,
  818. LOC_CREGISTER :
  819. begin
  820. hlcg.reference_reset_base(location.reference,left.resultdef,left.location.register,0,ctempposinvalid,location.reference.alignment,[]);
  821. end;
  822. LOC_CREFERENCE,
  823. LOC_REFERENCE :
  824. begin
  825. hlcg.reference_reset_base(location.reference,left.resultdef,hlcg.getaddressregister(current_asmdata.CurrAsmList,left.resultdef),0,ctempposinvalid,location.reference.alignment,[]);
  826. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location.reference,location.reference.base);
  827. end;
  828. LOC_CONSTANT:
  829. begin
  830. hlcg.reference_reset_base(location.reference,left.resultdef,NR_NO,left.location.value,ctempposinvalid,location.reference.alignment,[]);
  831. end;
  832. else
  833. internalerror(2002032218);
  834. end;
  835. if is_ansistring(left.resultdef) then
  836. offsetdec:=1
  837. else
  838. offsetdec:=2;
  839. location.reference.alignment:=offsetdec;
  840. location.reference.volatility:=[];
  841. { in ansistrings/widestrings S[1] is p<w>char(S)[0] }
  842. if not(cs_zerobasedstrings in current_settings.localswitches) then
  843. update_reference_offset(location.reference,-1,offsetdec);
  844. end
  845. else if is_dynamic_array(left.resultdef) then
  846. begin
  847. case left.location.loc of
  848. LOC_REGISTER,
  849. LOC_CREGISTER :
  850. hlcg.reference_reset_base(location.reference,left.resultdef,left.location.register,0,ctempposinvalid,location.reference.alignment,[]);
  851. LOC_REFERENCE,
  852. LOC_CREFERENCE :
  853. begin
  854. hlcg.reference_reset_base(location.reference,left.resultdef,hlcg.getaddressregister(current_asmdata.CurrAsmList,left.resultdef),0,ctempposinvalid,location.reference.alignment,[]);
  855. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,
  856. left.location.reference,location.reference.base);
  857. end;
  858. else
  859. internalerror(2002032219);
  860. end;
  861. { a dynarray points to the start of a memory block, which
  862. we assume to be always aligned to a multiple of the
  863. pointer size
  864. }
  865. location.reference.alignment:=voidpointertype.size;
  866. location.reference.volatility:=[];
  867. end
  868. else
  869. begin
  870. { may happen in case of function results }
  871. case left.location.loc of
  872. LOC_CREGISTER,
  873. LOC_REGISTER:
  874. begin
  875. if not(is_constnode(right)) or (tarraydef(left.resultdef).elementdef.size<>alusinttype.size) then
  876. begin
  877. hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
  878. location_copy(location,left.location);
  879. end
  880. else
  881. { we use location here only to get the right offset }
  882. location_reset_ref(location,LOC_REFERENCE,OS_NO,1,[]);
  883. end;
  884. LOC_CSUBSETREG,
  885. LOC_CMMREGISTER,
  886. LOC_SUBSETREG,
  887. LOC_MMREGISTER:
  888. begin
  889. hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
  890. location_copy(location,left.location);
  891. end;
  892. LOC_INVALID:
  893. Internalerror(2019061101);
  894. else
  895. location_copy(location,left.location);
  896. end;
  897. end;
  898. { location must be memory }
  899. if not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  900. internalerror(200411013);
  901. { offset can only differ from 0 if arraydef }
  902. if (left.resultdef.typ=arraydef) and
  903. not(is_dynamic_array(left.resultdef)) and
  904. (not(is_packed_array(left.resultdef)) or
  905. ((mulsize mod 8 = 0) and
  906. ispowerof2(mulsize div 8,temp)) or
  907. { only orddefs are bitpacked }
  908. not is_ordinal(resultdef)
  909. {$ifndef cpu64bitalu}
  910. or is_64bitint(resultdef)
  911. {$endif not cpu64bitalu}
  912. ) then
  913. update_reference_offset(location.reference,-tarraydef(left.resultdef).lowrange,bytemulsize);
  914. if right.nodetype=ordconstn then
  915. begin
  916. { offset can only differ from 0 if arraydef }
  917. if cs_check_range in current_settings.localswitches then
  918. begin
  919. secondpass(right);
  920. case left.resultdef.typ of
  921. arraydef :
  922. rangecheck_array;
  923. stringdef :
  924. rangecheck_string;
  925. else
  926. ;
  927. end;
  928. end;
  929. if not(is_packed_array(left.resultdef)) or
  930. ((mulsize mod 8 = 0) and
  931. (ispowerof2(mulsize div 8,temp) or
  932. { only orddefs are bitpacked }
  933. not is_ordinal(resultdef))) then
  934. begin
  935. extraoffset:=tordconstnode(right).value.svalue;
  936. update_reference_offset(location.reference,extraoffset,bytemulsize);
  937. { adjust alignment after this change }
  938. location.reference.alignment:=newalignment(location.reference.alignment,extraoffset*bytemulsize);
  939. { actually an array in a register? }
  940. if (left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) and
  941. is_normal_array(left.resultdef) then
  942. begin
  943. {$if defined(cpu64bitalu)}
  944. hreg:=left.location.register;
  945. {$else defined(cpu64bitalu)}
  946. if target_info.endian=endian_little then
  947. begin
  948. if location.reference.offset>3 then
  949. hreg:=left.location.register64.reghi
  950. else
  951. hreg:=left.location.register64.reglo;
  952. end
  953. else
  954. begin
  955. if location.reference.offset>3 then
  956. hreg:=left.location.register64.reglo
  957. else
  958. hreg:=left.location.register64.reghi;
  959. end;
  960. {$endif defined(cpu64bitalu)}
  961. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  962. { we support only the case that one element fills at least one register }
  963. for i:=1 to location.reference.offset mod 4 do
  964. hreg:=cg.GetNextReg(hreg);
  965. {$endif defined(cpu8bitalu) or defined(cpu16bitalu)}
  966. location_reset(location,left.location.loc,def_cgsize(tarraydef(left.resultdef).elementdef));
  967. location.register:=hreg;
  968. end;
  969. end
  970. else
  971. begin
  972. subsetref.ref := location.reference;
  973. subsetref.ref.alignment := left.resultdef.alignment;
  974. if not ispowerof2(packedbitsloadsize(resultdef.packedbitsize),temp) then
  975. internalerror(2006081212);
  976. alignpow:=temp;
  977. update_reference_offset(subsetref.ref,(mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) shr (3+alignpow),1 shl alignpow);
  978. subsetref.bitindexreg := NR_NO;
  979. subsetref.startbit := (mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) and ((1 shl (3+alignpow))-1);
  980. subsetref.bitlen := resultdef.packedbitsize;
  981. if (left.location.loc = LOC_REFERENCE) then
  982. location.loc := LOC_SUBSETREF
  983. else
  984. location.loc := LOC_CSUBSETREF;
  985. location.sref := subsetref;
  986. end;
  987. end
  988. else
  989. { not nodetype=ordconstn }
  990. begin
  991. if (cs_opt_level1 in current_settings.optimizerswitches) and
  992. { if we do range checking, we don't }
  993. { need that fancy code (it would be }
  994. { buggy) }
  995. not(cs_check_range in current_settings.localswitches) and
  996. (left.resultdef.typ=arraydef) and
  997. not is_packed_array(left.resultdef) then
  998. begin
  999. extraoffset:=0;
  1000. rightp:=actualtargetnode(@right);
  1001. if rightp^.nodetype=addn then
  1002. begin
  1003. if taddnode(rightp^).right.nodetype=ordconstn then
  1004. begin
  1005. extraoffset:=tordconstnode(taddnode(rightp^).right).value.svalue;
  1006. replacenode(rightp^,taddnode(rightp^).left);
  1007. end
  1008. else if taddnode(rightp^).left.nodetype=ordconstn then
  1009. begin
  1010. extraoffset:=tordconstnode(taddnode(rightp^).left).value.svalue;
  1011. replacenode(rightp^,taddnode(rightp^).right);
  1012. end;
  1013. end
  1014. else if rightp^.nodetype=subn then
  1015. begin
  1016. if taddnode(rightp^).right.nodetype=ordconstn then
  1017. begin
  1018. extraoffset:=-tordconstnode(taddnode(rightp^).right).value.svalue;
  1019. replacenode(rightp^,taddnode(rightp^).left);
  1020. end;
  1021. end;
  1022. update_reference_offset(location.reference,extraoffset,mulsize);
  1023. end;
  1024. { calculate from left to right }
  1025. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  1026. internalerror(200304237);
  1027. secondpass(right);
  1028. if (right.expectloc=LOC_JUMP)<>
  1029. (right.location.loc=LOC_JUMP) then
  1030. internalerror(2006010801);
  1031. { if mulsize = 1, we won't have to modify the index }
  1032. if not(right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
  1033. not valid_index_size(right.location.size) then
  1034. begin
  1035. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,sizeuinttype,true);
  1036. indexdef:=sizeuinttype
  1037. end
  1038. else
  1039. indexdef:=right.resultdef;
  1040. { produce possible range check code: }
  1041. if cs_check_range in current_settings.localswitches then
  1042. begin
  1043. if left.resultdef.typ=arraydef then
  1044. rangecheck_array
  1045. else if (left.resultdef.typ=stringdef) then
  1046. rangecheck_string;
  1047. end;
  1048. { insert the register and the multiplication factor in the
  1049. reference }
  1050. if not is_packed_array(left.resultdef) then
  1051. update_reference_reg_mul(right.location.register,indexdef,mulsize)
  1052. else
  1053. update_reference_reg_packed(right.location.register,indexdef,mulsize);
  1054. end;
  1055. location.size:=newsize;
  1056. paraloc1.done;
  1057. paraloc2.done;
  1058. end;
  1059. begin
  1060. cloadvmtaddrnode:=tcgloadvmtaddrnode;
  1061. cloadparentfpnode:=tcgloadparentfpnode;
  1062. caddrnode:=tcgaddrnode;
  1063. cderefnode:=tcgderefnode;
  1064. csubscriptnode:=tcgsubscriptnode;
  1065. cvecnode:=tcgvecnode;
  1066. end.