ncgmem.pas 49 KB

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