ncgmem.pas 49 KB

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