ncgmem.pas 52 KB

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