ncgld.pas 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for nodes that handle loads and assignments which
  4. are 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 ncgld;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,
  23. symtype,symsym,
  24. aasmdata,
  25. node,nld,cgutils;
  26. type
  27. tcgloadnode = class(tloadnode)
  28. protected
  29. procedure generate_nested_access(vs: tsym);virtual;
  30. procedure generate_absaddr_access(vs: tabsolutevarsym); virtual;
  31. procedure generate_threadvar_access(gvs: tstaticvarsym); virtual;
  32. function use_indirect_symbol(gvs: tstaticvarsym): boolean;
  33. public
  34. procedure pass_generate_code;override;
  35. procedure changereflocation(const ref: treference);
  36. end;
  37. tcgassignmentnode = class(tassignmentnode)
  38. protected
  39. function maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;virtual;
  40. public
  41. procedure pass_generate_code;override;
  42. end;
  43. tcgarrayconstructornode = class(tarrayconstructornode)
  44. protected
  45. procedure makearrayref(var ref: treference; eledef: tdef);virtual;
  46. procedure advancearrayoffset(var ref: treference; elesize: asizeint);virtual;
  47. public
  48. procedure pass_generate_code;override;
  49. end;
  50. tcgrttinode = class(trttinode)
  51. procedure pass_generate_code;override;
  52. end;
  53. implementation
  54. uses
  55. cutils,
  56. systems,
  57. verbose,globals,constexp,fmodule,
  58. nutils,
  59. symtable,symconst,symdef,defutil,paramgr,ncon,nbas,ncgrtti,
  60. aasmbase,
  61. cgbase,pass_2,
  62. procinfo,
  63. cpubase,parabase,
  64. tgobj,
  65. cgobj,hlcgobj,
  66. ncgbas,ncgflw,
  67. wpobase;
  68. {*****************************************************************************
  69. SSA (for memory temps) support
  70. *****************************************************************************}
  71. type
  72. preplacerefrec = ^treplacerefrec;
  73. treplacerefrec = record
  74. old, new: preference;
  75. ressym: tsym;
  76. end;
  77. function doreplaceref(var n: tnode; para: pointer): foreachnoderesult;
  78. var
  79. rr: preplacerefrec absolute para;
  80. begin
  81. result := fen_false;
  82. case n.nodetype of
  83. loadn:
  84. begin
  85. { regular variable }
  86. if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
  87. not assigned(tloadnode(n).left) and
  88. { not function result, or no exit in function }
  89. (((tloadnode(n).symtableentry <> rr^.ressym) and
  90. not(vo_is_funcret in tabstractvarsym(tloadnode(n).symtableentry).varoptions)) or
  91. not(fc_exit in flowcontrol)) and
  92. { stored in memory... }
  93. (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_REFERENCE]) and
  94. { ... at the place we are looking for }
  95. references_equal(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.reference,rr^.old^) and
  96. { its address cannot have escaped the current routine }
  97. not(tabstractvarsym(tloadnode(n).symtableentry).addr_taken) and
  98. { it is not accessed in nested procedures }
  99. not(tabstractvarsym(tloadnode(n).symtableentry).different_scope) then
  100. begin
  101. { relocate variable }
  102. tcgloadnode(n).changereflocation(rr^.new^);
  103. result := fen_norecurse_true;
  104. end;
  105. end;
  106. temprefn:
  107. begin
  108. if (ti_valid in ttemprefnode(n).tempflags) and
  109. { memory temp... }
  110. (ttemprefnode(n).tempinfo^.location.loc in [LOC_REFERENCE]) and
  111. { ... at the place we are looking for }
  112. references_equal(ttemprefnode(n).tempinfo^.location.reference,rr^.old^) and
  113. { its address cannot have escaped the current routine }
  114. not(ti_addr_taken in ttemprefnode(n).tempflags) then
  115. begin
  116. { relocate the temp }
  117. tcgtemprefnode(n).changelocation(rr^.new^);
  118. result := fen_norecurse_true;
  119. end;
  120. end;
  121. { Subscriptn must be rejected, otherwise we may replace an
  122. an entire record with a temp for its first field, mantis #13948)
  123. Exception: the field's size is the same as the entire record
  124. The same goes for array indexing
  125. }
  126. subscriptn,
  127. vecn:
  128. if not(tunarynode(n).left.resultdef.typ in [recorddef,objectdef,arraydef,stringdef]) or
  129. { make sure we don't try to call resultdef.size for types that
  130. don't have a compile-time size such as open arrays }
  131. is_special_array(tunarynode(n).left.resultdef) or
  132. (tunarynode(n).left.resultdef.size<>tunarynode(n).resultdef.size) then
  133. result := fen_norecurse_false;
  134. { optimize the searching a bit }
  135. derefn,addrn,
  136. calln,inlinen,casen,
  137. addn,subn,muln,
  138. andn,orn,xorn,
  139. ltn,lten,gtn,gten,equaln,unequaln,
  140. slashn,divn,shrn,shln,notn,
  141. inn,
  142. asn,isn:
  143. result := fen_norecurse_false;
  144. end;
  145. end;
  146. function tcgassignmentnode.maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;
  147. var
  148. rr: treplacerefrec;
  149. begin
  150. result := false;
  151. { only do for -O2 or higher (breaks debugging since }
  152. { variables move to different memory locations) }
  153. if not(cs_opt_level2 in current_settings.optimizerswitches) or
  154. { must be a copy to a memory location ... }
  155. (n.location.loc <> LOC_REFERENCE) or
  156. { not inside a control flow statement and no goto's in sight }
  157. ([fc_inflowcontrol,fc_gotolabel] * flowcontrol <> []) or
  158. { not for refcounted types, because those locations are }
  159. { still used later on in initialisation/finalisation code }
  160. is_managed_type(n.resultdef) or
  161. { source and destination are temps (= not global variables) }
  162. { and both point to the start of a temp, and the source is a }
  163. { non-persistent temp (otherwise we need some kind of copy- }
  164. { on-write support in case later on both are still used) }
  165. not tg.isstartoftemp(newref) or
  166. not tg.isstartoftemp(n.location.reference) or
  167. (tg.gettypeoftemp(newref) <> tt_normal) or
  168. not (tg.gettypeoftemp(n.location.reference) in [tt_normal,tt_persistent]) or
  169. { and both have the same size }
  170. (tg.sizeoftemp(current_asmdata.CurrAsmList,newref) <> tg.sizeoftemp(current_asmdata.CurrAsmList,n.location.reference)) then
  171. exit;
  172. { find the source of the old reference (loadnode or tempnode) }
  173. { and replace it with the new reference }
  174. rr.old := @n.location.reference;
  175. rr.new := @newref;
  176. rr.ressym := nil;
  177. if assigned(current_procinfo.procdef.funcretsym) and
  178. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
  179. if (current_procinfo.procdef.proctypeoption=potype_constructor) then
  180. rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
  181. else
  182. rr.ressym:=current_procinfo.procdef.funcretsym;
  183. { if source not found, don't do anything }
  184. if not foreachnodestatic(n,@doreplaceref,@rr) then
  185. exit;
  186. n.location.reference := newref;
  187. result:=true;
  188. end;
  189. {*****************************************************************************
  190. SecondLoad
  191. *****************************************************************************}
  192. procedure tcgloadnode.changereflocation(const ref: treference);
  193. var
  194. oldtemptype: ttemptype;
  195. begin
  196. if (location.loc<>LOC_REFERENCE) then
  197. internalerror(2007020812);
  198. if not tg.istemp(location.reference) then
  199. internalerror(2007020813);
  200. oldtemptype:=tg.gettypeoftemp(location.reference);
  201. if (oldtemptype = tt_persistent) then
  202. tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,tt_normal);
  203. tg.ungettemp(current_asmdata.CurrAsmList,location.reference);
  204. location.reference:=ref;
  205. tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,oldtemptype);
  206. tabstractnormalvarsym(symtableentry).localloc:=location;
  207. end;
  208. procedure tcgloadnode.generate_nested_access(vs: tsym);
  209. var
  210. { paramter declared as tsym to reduce interface unit dependencies }
  211. lvs: tabstractnormalvarsym absolute vs;
  212. begin
  213. secondpass(left);
  214. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  215. internalerror(200309286);
  216. if lvs.localloc.loc<>LOC_REFERENCE then
  217. internalerror(200409241);
  218. hlcg.reference_reset_base(location.reference,left.resultdef,left.location.register,lvs.localloc.reference.offset,ctempposinvalid,lvs.localloc.reference.alignment,lvs.localloc.reference.volatility);
  219. end;
  220. procedure tcgloadnode.generate_absaddr_access(vs: tabsolutevarsym);
  221. begin
  222. location.reference.offset:=asizeint(vs.addroffset);
  223. location.reference.volatility:=[vol_read,vol_write];
  224. end;
  225. procedure tcgloadnode.generate_threadvar_access(gvs: tstaticvarsym);
  226. var
  227. respara,
  228. paraloc1 : tcgpara;
  229. fieldptrdef,
  230. pvd : tdef;
  231. endrelocatelab,
  232. norelocatelab : tasmlabel;
  233. tvref,
  234. href : treference;
  235. hregister, hreg_tv_rec : tregister;
  236. tv_rec : trecorddef;
  237. tv_index_field,
  238. tv_non_mt_data_field: tsym;
  239. tmpresloc: tlocation;
  240. issystemunit,
  241. indirect : boolean;
  242. size_opt : boolean;
  243. begin
  244. if (tf_section_threadvars in target_info.flags) then
  245. begin
  246. if gvs.localloc.loc=LOC_INVALID then
  247. if not(vo_is_weak_external in gvs.varoptions) then
  248. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,location.reference.alignment,[])
  249. else
  250. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,location.reference.alignment,[])
  251. else
  252. location:=gvs.localloc;
  253. end
  254. else
  255. begin
  256. {
  257. Thread var loading is optimized to first check if
  258. a relocate function is available. When the function
  259. is available it is called to retrieve the address.
  260. Otherwise the address is loaded with the symbol
  261. }
  262. tv_rec:=get_threadvar_record(resultdef,tv_index_field,tv_non_mt_data_field);
  263. fieldptrdef:=cpointerdef.getreusable(resultdef);
  264. current_asmdata.getjumplabel(norelocatelab);
  265. current_asmdata.getjumplabel(endrelocatelab);
  266. { make sure hregister can't allocate the register necessary for the parameter }
  267. pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
  268. if pvd.typ<>procvardef then
  269. internalerror(2012120901);
  270. { FPC_THREADVAR_RELOCATE is nil? }
  271. issystemunit:=not current_module.is_unit or
  272. (
  273. assigned(current_module.globalsymtable) and
  274. (current_module.globalsymtable=systemunit)
  275. ) or
  276. (
  277. not assigned(current_module.globalsymtable) and
  278. (current_module.localsymtable=systemunit)
  279. );
  280. indirect:=(tf_supports_packages in target_info.flags) and
  281. (target_info.system in systems_indirect_var_imports) and
  282. (cs_imported_data in current_settings.localswitches) and
  283. not issystemunit;
  284. if not(vo_is_weak_external in gvs.varoptions) then
  285. reference_reset_symbol(tvref,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,sizeof(pint),[])
  286. else
  287. reference_reset_symbol(tvref,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,sizeof(pint),[]);
  288. { Enable size optimization with -Os or PIC code is generated and PIC uses GOT }
  289. size_opt:=(cs_opt_size in current_settings.optimizerswitches)
  290. or ((cs_create_pic in current_settings.moduleswitches) and (tf_pic_uses_got in target_info.flags));
  291. hreg_tv_rec:=NR_INVALID;
  292. if size_opt then
  293. begin
  294. { Load a pointer to the thread var record into a register. }
  295. { This register will be used in both multithreaded and non-multithreaded cases. }
  296. hreg_tv_rec:=hlcg.getaddressregister(current_asmdata.CurrAsmList,fieldptrdef);
  297. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,tvref,hreg_tv_rec);
  298. end;
  299. paraloc1.init;
  300. paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
  301. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
  302. reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE',AT_DATA,indirect),0,pvd.alignment,[]);
  303. if not issystemunit then
  304. current_module.add_extern_asmsym('FPC_THREADVAR_RELOCATE',AB_EXTERNAL,AT_DATA);
  305. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,pvd,pvd,href,hregister);
  306. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,pvd,OC_EQ,0,hregister,norelocatelab);
  307. { no, call it with the index of the threadvar as parameter }
  308. href:=tvref;
  309. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
  310. tv_rec,
  311. tfieldvarsym(tv_index_field),href);
  312. if size_opt then
  313. hlcg.reference_reset_base(href,tfieldvarsym(tv_index_field).vardef,hreg_tv_rec,href.offset,href.temppos,href.alignment,[]);
  314. hlcg.a_load_ref_cgpara(current_asmdata.CurrAsmList,tfieldvarsym(tv_index_field).vardef,href,paraloc1);
  315. { Dealloc the threadvar record register before calling the helper function to allow }
  316. { the register allocator to assign non-mandatory real registers for hreg_tv_rec. }
  317. if size_opt then
  318. cg.a_reg_dealloc(current_asmdata.CurrAsmList,hreg_tv_rec);
  319. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  320. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  321. { result is the address of the threadvar }
  322. respara:=hlcg.a_call_reg(current_asmdata.CurrAsmList,tprocvardef(pvd),hregister,[@paraloc1]);
  323. paraloc1.done;
  324. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  325. { load the address of the result in hregister }
  326. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,fieldptrdef);
  327. location_reset(tmpresloc,LOC_REGISTER,def_cgsize(fieldptrdef));
  328. tmpresloc.register:=hregister;
  329. hlcg.gen_load_cgpara_loc(current_asmdata.CurrAsmList,fieldptrdef,respara,tmpresloc,true);
  330. respara.resetiftemp;
  331. hlcg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
  332. { no relocation needed, load the address of the variable only, the
  333. layout of a threadvar is:
  334. 0 - Threadvar index
  335. sizeof(pint) - Threadvar value in single threading }
  336. hlcg.a_label(current_asmdata.CurrAsmList,norelocatelab);
  337. href:=tvref;
  338. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
  339. tv_rec,
  340. tfieldvarsym(tv_non_mt_data_field),href);
  341. { load in the same "hregister" as above, so after this sequence
  342. the address of the threadvar is always in hregister }
  343. if size_opt then
  344. hlcg.reference_reset_base(href,fieldptrdef,hreg_tv_rec,href.offset,href.temppos,href.alignment,[]);
  345. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,href,hregister);
  346. hlcg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
  347. hlcg.reference_reset_base(location.reference,fieldptrdef,hregister,0,ctempposinvalid,resultdef.alignment,[]);
  348. end;
  349. end;
  350. function tcgloadnode.use_indirect_symbol(gvs:tstaticvarsym):boolean;
  351. begin
  352. { we are using a direct reference if any of the following is true:
  353. - the target does not support packages
  354. - the target does not use indirect references
  355. - the variable is declared as (weak) external
  356. - G- is set
  357. - the variable is located inside the same unit }
  358. result:=(tf_supports_packages in target_info.flags) and
  359. (target_info.system in systems_indirect_var_imports) and
  360. (gvs.varoptions*[vo_is_external,vo_is_weak_external]=[]) and
  361. (gvs.owner.symtabletype in [globalsymtable,staticsymtable]) and
  362. (cs_imported_data in current_settings.localswitches) and
  363. not sym_is_owned_by(gvs,current_module.globalsymtable) and
  364. (
  365. (current_module.globalsymtable=current_module.localsymtable) or
  366. not sym_is_owned_by(gvs,current_module.localsymtable)
  367. );
  368. end;
  369. procedure tcgloadnode.pass_generate_code;
  370. var
  371. hregister : tregister;
  372. vs : tabstractnormalvarsym;
  373. gvs : tstaticvarsym;
  374. vmtdef : tpointerdef;
  375. vmtentry: tfieldvarsym;
  376. pd : tprocdef;
  377. href : treference;
  378. newsize : tcgsize;
  379. vd : tdef;
  380. alignment: longint;
  381. indirect : boolean;
  382. name : TSymStr;
  383. begin
  384. { we don't know the size of all arrays }
  385. newsize:=def_cgsize(resultdef);
  386. { alignment is overridden per case below }
  387. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment,[]);
  388. case symtableentry.typ of
  389. absolutevarsym :
  390. begin
  391. { this is only for toasm and toaddr }
  392. case tabsolutevarsym(symtableentry).abstyp of
  393. toaddr :
  394. generate_absaddr_access(tabsolutevarsym(symtableentry));
  395. toasm :
  396. location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname,AT_DATA);
  397. else
  398. internalerror(200310283);
  399. end;
  400. end;
  401. constsym:
  402. begin
  403. if tconstsym(symtableentry).consttyp=constresourcestring then
  404. begin
  405. location_reset_ref(location,LOC_CREFERENCE,def_cgsize(cansistringtype),cansistringtype.size,[]);
  406. indirect:=(tf_supports_packages in target_info.flags) and
  407. (target_info.system in systems_indirect_var_imports) and
  408. (cs_imported_data in current_settings.localswitches) and
  409. (symtableentry.owner.moduleid<>current_module.moduleid);
  410. name:=make_mangledname('RESSTR',symtableentry.owner,symtableentry.name);
  411. location.reference.symbol:=current_asmdata.RefAsmSymbol(name,AT_DATA,indirect);
  412. if symtableentry.owner.moduleid<>current_module.moduleid then
  413. current_module.addimportedsym(symtableentry);
  414. vd:=search_system_type('TRESOURCESTRINGRECORD').typedef;
  415. hlcg.g_set_addr_nonbitpacked_field_ref(
  416. current_asmdata.CurrAsmList,
  417. trecorddef(vd),
  418. tfieldvarsym(search_struct_member(trecorddef(vd),'CURRENTVALUE')),
  419. location.reference);
  420. end
  421. else
  422. internalerror(22798);
  423. end;
  424. staticvarsym :
  425. begin
  426. gvs:=tstaticvarsym(symtableentry);
  427. if (vo_is_dll_var in gvs.varoptions) then
  428. { DLL variable }
  429. begin
  430. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  431. if not(vo_is_weak_external in gvs.varoptions) then
  432. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname,AT_DATA)
  433. else
  434. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(tstaticvarsym(symtableentry).mangledname,AT_DATA);
  435. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
  436. reference_reset_base(location.reference,hregister,0,ctempposinvalid,location.reference.alignment,[]);
  437. end
  438. { Thread variable }
  439. else if (vo_is_thread_var in gvs.varoptions) then
  440. generate_threadvar_access(gvs)
  441. { Normal (or external) variable }
  442. else
  443. begin
  444. if gvs.localloc.loc=LOC_INVALID then
  445. begin
  446. { static data is currently always volatile }
  447. if not(vo_is_weak_external in gvs.varoptions) then
  448. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,location.reference.alignment,[])
  449. else
  450. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,location.reference.alignment,[])
  451. end
  452. else
  453. location:=gvs.localloc;
  454. end;
  455. { make const a LOC_CREFERENCE }
  456. if (gvs.varspez=vs_const) and
  457. (location.loc=LOC_REFERENCE) then
  458. location.loc:=LOC_CREFERENCE;
  459. end;
  460. paravarsym,
  461. localvarsym :
  462. begin
  463. vs:=tabstractnormalvarsym(symtableentry);
  464. { Nested variable }
  465. if assigned(left) then
  466. generate_nested_access(vs)
  467. else
  468. location:=vs.localloc;
  469. { handle call by reference variables when they are not
  470. already copied to local copies. Also ignore the reference
  471. when we need to load the self pointer for objects }
  472. if is_addr_param_load then
  473. begin
  474. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  475. hregister:=location.register
  476. else
  477. begin
  478. vd:=cpointerdef.getreusable(resultdef);
  479. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vd);
  480. { we need to load only an address }
  481. location.size:=int_cgsize(vd.size);
  482. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,vd,vd,location,hregister);
  483. end;
  484. { assume packed records may always be unaligned }
  485. if not(resultdef.typ in [recorddef,objectdef]) or
  486. (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
  487. begin
  488. alignment:=min(min(min(resultdef.alignment,current_settings.alignment.localalignmax),current_settings.alignment.constalignmax),current_settings.alignment.varalignmax);
  489. location_reset_ref(location,LOC_REFERENCE,newsize,alignment,[]);
  490. end
  491. else
  492. location_reset_ref(location,LOC_REFERENCE,newsize,1,[]);
  493. hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,ctempposinvalid,location.reference.alignment,[]);
  494. end;
  495. { make const a LOC_CREFERENCE }
  496. if (vs.varspez=vs_const) and
  497. (location.loc=LOC_REFERENCE) then
  498. location.loc:=LOC_CREFERENCE;
  499. end;
  500. procsym:
  501. begin
  502. if not assigned(procdef) then
  503. internalerror(200312011);
  504. if assigned(left) and
  505. (resultdef.typ in [symconst.procdef,procvardef]) and
  506. not tabstractprocdef(resultdef).is_addressonly then
  507. begin
  508. location_reset(location,LOC_CREGISTER,int_cgsize(voidpointertype.size*2));
  509. secondpass(left);
  510. { load class instance/classrefdef address }
  511. if left.location.loc=LOC_CONSTANT then
  512. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  513. { vd will contain the type of the self pointer (self in
  514. case of a class/classref, address of self in case of
  515. an object }
  516. vd:=nil;
  517. case left.location.loc of
  518. LOC_CREGISTER,
  519. LOC_REGISTER:
  520. begin
  521. { this is not possible for objects }
  522. if is_object(left.resultdef) then
  523. internalerror(200304234);
  524. location.registerhi:=left.location.register;
  525. vd:=left.resultdef;
  526. end;
  527. LOC_CREFERENCE,
  528. LOC_REFERENCE:
  529. begin
  530. if is_implicit_pointer_object_type(left.resultdef) or
  531. (left.resultdef.typ=classrefdef) then
  532. begin
  533. vd:=left.resultdef;
  534. location.registerhi:=hlcg.getaddressregister(current_asmdata.CurrAsmList,left.resultdef);
  535. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location.reference,location.registerhi)
  536. end
  537. else
  538. begin
  539. vd:=cpointerdef.getreusable(left.resultdef);
  540. location.registerhi:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vd);
  541. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,vd,left.location.reference,location.registerhi);
  542. end;
  543. location_freetemp(current_asmdata.CurrAsmList,left.location);
  544. end;
  545. else
  546. internalerror(200610311);
  547. end;
  548. { virtual method ? }
  549. if (po_virtualmethod in procdef.procoptions) and
  550. not(loadnf_inherited in loadnodeflags) and
  551. not is_objectpascal_helper(procdef.struct) then
  552. begin
  553. if (not assigned(current_procinfo) or
  554. wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
  555. tobjectdef(procdef.struct).register_vmt_call(procdef.extnumber);
  556. {$ifdef vtentry}
  557. if not is_interface(procdef.struct) then
  558. begin
  559. inc(current_asmdata.NextVTEntryNr);
  560. current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+procdef._class.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0,voidpointerdef));
  561. end;
  562. {$endif vtentry}
  563. if (left.resultdef.typ=objectdef) and
  564. assigned(tobjectdef(left.resultdef).vmt_field) then
  565. begin
  566. { vmt pointer is a pointer to the vmt record }
  567. hlcg.reference_reset_base(href,vd,location.registerhi,0,ctempposinvalid,vd.alignment,[]);
  568. vmtdef:=cpointerdef.getreusable(tobjectdef(left.resultdef).vmt_def);
  569. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,tobjectdef(left.resultdef),tfieldvarsym(tobjectdef(left.resultdef).vmt_field),href);
  570. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtdef);
  571. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,tfieldvarsym(tobjectdef(left.resultdef).vmt_field).vardef,vmtdef,href,hregister);
  572. end
  573. else if left.resultdef.typ=classrefdef then
  574. begin
  575. { classrefdef is a pointer to the vmt already }
  576. hregister:=location.registerhi;
  577. vmtdef:=cpointerdef.getreusable(tobjectdef(tclassrefdef(left.resultdef).pointeddef).vmt_def);
  578. hlcg.g_ptrtypecast_reg(current_asmdata.CurrAsmList,left.resultdef,vmtdef,hregister);
  579. end
  580. else if is_any_interface_kind(left.resultdef) then
  581. begin
  582. { an interface is a pointer to a pointer to a vmt }
  583. hlcg.reference_reset_base(href,vd,location.registerhi,0,ctempposinvalid,vd.alignment,[]);
  584. vmtdef:=cpointerdef.getreusable(tobjectdef(left.resultdef).vmt_def);
  585. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtdef);
  586. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,vmtdef,vmtdef,href,hregister);
  587. end
  588. else
  589. internalerror(2015112501);
  590. { load method address }
  591. vmtentry:=tabstractrecordsymtable(trecorddef(vmtdef.pointeddef).symtable).findfieldbyoffset(
  592. tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber));
  593. hlcg.reference_reset_base(href,vmtdef,hregister,0,ctempposinvalid,vmtdef.alignment,[]);
  594. location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtentry.vardef);
  595. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,tabstractrecorddef(vmtdef.pointeddef),vmtentry,href);
  596. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,vmtentry.vardef,vmtentry.vardef,href,location.register);
  597. end
  598. else
  599. begin
  600. { load address of the function }
  601. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION),0,procdef.address_type.alignment,[]);
  602. location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef));
  603. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,procdef,cprocvardef.getreusableprocaddr(procdef),href,location.register);
  604. end;
  605. { to get methodpointers stored correctly, code and self register must be swapped on
  606. big endian targets }
  607. if target_info.endian=endian_big then
  608. begin
  609. hregister:=location.register;
  610. location.register:=location.registerhi;
  611. location.registerhi:=hregister;
  612. end;
  613. end
  614. else
  615. begin
  616. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  617. { def_cgsize does not work for tprocdef, so we use pd.address_type }
  618. location.size:=def_cgsize(pd.address_type);
  619. if not(po_weakexternal in pd.procoptions) then
  620. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION)
  621. else
  622. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname,AT_FUNCTION);
  623. end;
  624. end;
  625. labelsym :
  626. if assigned(tlabelsym(symtableentry).asmblocklabel) then
  627. location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
  628. else
  629. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  630. else internalerror(200510032);
  631. end;
  632. end;
  633. {*****************************************************************************
  634. SecondAssignment
  635. *****************************************************************************}
  636. procedure tcgassignmentnode.pass_generate_code;
  637. var
  638. shuffle : pmmshuffle;
  639. hlabel : tasmlabel;
  640. href : treference;
  641. releaseright : boolean;
  642. alignmentrequirement,
  643. len : aint;
  644. r : tregister;
  645. {$if not defined(cpu64bitalu)}
  646. r64 : tregister64;
  647. {$endif}
  648. oldflowcontrol : tflowcontrol;
  649. begin
  650. { previously, managed types were handled in firstpass
  651. newer FPCs however can identify situations when
  652. assignments of managed types require no special code and the
  653. value could be just copied so this could should be able also to handle
  654. managed types without any special "managing code"}
  655. location_reset(location,LOC_VOID,OS_NO);
  656. {
  657. in most cases we can process first the right node which contains
  658. the most complex code. Exceptions for this are:
  659. - result is in flags, loading left will then destroy the flags
  660. - result is a jump, loading left must be already done before the jump is made
  661. - result need reference count, when left points to a value used in
  662. right then decreasing the refcnt on left can possibly release
  663. the memory before right increased the refcnt, result is that an
  664. empty value is assigned
  665. But not when the result is in the flags, then
  666. loading the left node afterwards can destroy the flags.
  667. Neither if right contains conditional nodes: this might cause problems with
  668. temp. nodes with init code used by CSE, see e.g. #38129
  669. }
  670. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  671. (node_complexity(right)>node_complexity(left)) and not(has_conditional_nodes(right)) then
  672. begin
  673. secondpass(right);
  674. if codegenerror then
  675. exit;
  676. secondpass(left);
  677. if codegenerror then
  678. exit;
  679. end
  680. else
  681. begin
  682. { calculate left sides }
  683. secondpass(left);
  684. if codegenerror then
  685. exit;
  686. { tell the SSA/SSL code that the left side was handled first so
  687. ni SSL is done
  688. }
  689. oldflowcontrol:=flowcontrol;
  690. include(flowcontrol,fc_lefthandled);
  691. secondpass(right);
  692. flowcontrol:=oldflowcontrol;
  693. if codegenerror then
  694. exit;
  695. end;
  696. releaseright:=
  697. (left.nodetype<>temprefn) or
  698. not(ti_const in ttemprefnode(left).tempflags);
  699. { shortstring assignments are handled separately }
  700. if is_shortstring(left.resultdef) then
  701. begin
  702. {
  703. we can get here only in the following situations
  704. for the right node:
  705. - empty constant string
  706. - char
  707. }
  708. { The addn is replaced by a blockn or calln that already returns
  709. a shortstring }
  710. if is_shortstring(right.resultdef) and
  711. (right.nodetype in [blockn,calln]) then
  712. begin
  713. { verify that we indeed have nothing to do }
  714. if not(nf_assign_done_in_right in flags) then
  715. internalerror(2015042201);
  716. end
  717. { empty constant string }
  718. else if (right.nodetype=stringconstn) and
  719. (tstringconstnode(right).len=0) then
  720. begin
  721. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),tpointerdef(charpointertype),left.location.reference);
  722. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,cansichartype,0,left.location.reference);
  723. end
  724. { char loading }
  725. else if is_char(right.resultdef) then
  726. begin
  727. if right.nodetype=ordconstn then
  728. begin
  729. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),cpointerdef.getreusable(u16inttype),left.location.reference);
  730. if (target_info.endian = endian_little) then
  731. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,(tordconstnode(right).value.svalue shl 8) or 1,
  732. setalignment(left.location.reference,1))
  733. else
  734. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,tordconstnode(right).value.svalue or (1 shl 8),
  735. setalignment(left.location.reference,1));
  736. end
  737. else
  738. begin
  739. href:=left.location.reference;
  740. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),tpointerdef(charpointertype),href);
  741. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,cansichartype,1,href);
  742. inc(href.offset,1);
  743. href.alignment:=1;
  744. case right.location.loc of
  745. LOC_REGISTER,
  746. LOC_CREGISTER :
  747. begin
  748. {$ifndef cpuhighleveltarget}
  749. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  750. {$else not cpuhighleveltarget}
  751. r:=hlcg.getintregister(current_asmdata.CurrAsmList,u8inttype);
  752. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,cansichartype,u8inttype,right.location.register,r);
  753. {$endif cpuhighleveltarget}
  754. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,r,href);
  755. end;
  756. LOC_REFERENCE,
  757. LOC_CREFERENCE :
  758. hlcg.a_load_ref_ref(current_asmdata.CurrAsmList,cansichartype,cansichartype,right.location.reference,href);
  759. else
  760. internalerror(200205111);
  761. end;
  762. end;
  763. end
  764. else
  765. internalerror(2002042410);
  766. end
  767. { try to reuse memory locations instead of copying }
  768. { copy to a memory location ... }
  769. else if (right.location.loc = LOC_REFERENCE) and
  770. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  771. begin
  772. { if it worked, we're done }
  773. end
  774. else
  775. begin
  776. { SSA support }
  777. hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
  778. hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,right,true);
  779. case right.location.loc of
  780. LOC_CONSTANT :
  781. begin
  782. {$ifndef cpu64bitalu}
  783. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  784. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  785. else
  786. {$endif not cpu64bitalu}
  787. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
  788. end;
  789. LOC_REFERENCE,
  790. LOC_CREFERENCE :
  791. begin
  792. case left.location.loc of
  793. LOC_REGISTER,
  794. LOC_CREGISTER :
  795. begin
  796. {$ifndef cpuhighleveltarget}
  797. {$ifdef cpu64bitalu}
  798. if left.location.size in [OS_128,OS_S128] then
  799. cg128.a_load128_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register128)
  800. else
  801. {$else cpu64bitalu}
  802. if left.location.size in [OS_64,OS_S64] then
  803. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  804. else
  805. {$endif cpu64bitalu}
  806. {$endif not cpuhighleveltarget}
  807. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
  808. end;
  809. LOC_FPUREGISTER,
  810. LOC_CFPUREGISTER :
  811. begin
  812. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  813. right.resultdef,left.resultdef,
  814. right.location.reference,
  815. left.location.register);
  816. end;
  817. LOC_REFERENCE,
  818. LOC_CREFERENCE :
  819. begin
  820. if (left.resultdef.typ=floatdef) and
  821. (right.resultdef.typ=floatdef) and
  822. (left.location.size<>right.location.size) then
  823. begin
  824. { assume that all float types can be handed by the
  825. fpu if one can be handled by the fpu }
  826. if not use_vectorfpu(left.resultdef) or
  827. not use_vectorfpu(right.resultdef) then
  828. hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  829. right.resultdef,left.resultdef,
  830. right.location.reference,left.location.reference)
  831. else
  832. hlcg.a_loadmm_ref_ref(current_asmdata.CurrAsmList,
  833. right.resultdef,left.resultdef,
  834. right.location.reference,left.location.reference,mms_movescalar)
  835. end
  836. else
  837. begin
  838. { TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  839. { Use unaligned copy when the offset is not aligned }
  840. len:=left.resultdef.size;
  841. { can be 0 in case of formaldef on JVM target }
  842. if len=0 then
  843. len:=sizeof(pint);
  844. { data smaller than an aint has less alignment requirements }
  845. { max(1,...) avoids div by zero in case of an empty record }
  846. alignmentrequirement:=min(max(1,len),sizeof(aint));
  847. if (right.location.reference.offset mod alignmentrequirement<>0) or
  848. (left.location.reference.offset mod alignmentrequirement<>0) or
  849. (right.resultdef.alignment<alignmentrequirement) or
  850. ((right.location.reference.alignment<>0) and
  851. (right.location.reference.alignment<alignmentrequirement)) or
  852. ((left.location.reference.alignment<>0) and
  853. (left.location.reference.alignment<alignmentrequirement)) then
  854. hlcg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference)
  855. else
  856. hlcg.g_concatcopy(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference);
  857. end;
  858. end;
  859. LOC_MMREGISTER,
  860. LOC_CMMREGISTER:
  861. begin
  862. {$if defined(x86) and not defined(llvm)}
  863. if (right.resultdef.typ=floatdef) and
  864. not use_vectorfpu(right.resultdef) then
  865. begin
  866. { perform size conversion if needed (the mm-code cannot }
  867. { convert an extended into a double/single, since sse }
  868. { doesn't support extended) }
  869. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  870. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  871. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  872. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  873. if releaseright then
  874. location_freetemp(current_asmdata.CurrAsmList,right.location);
  875. releaseright:=true;
  876. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0,[]);
  877. right.location.reference:=href;
  878. right.resultdef:=left.resultdef;
  879. end;
  880. {$endif}
  881. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  882. right.resultdef,
  883. left.resultdef,
  884. right.location.reference,
  885. left.location.register,mms_movescalar);
  886. end;
  887. LOC_SUBSETREG,
  888. LOC_CSUBSETREG:
  889. hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
  890. LOC_SUBSETREF,
  891. LOC_CSUBSETREF:
  892. {$ifndef cpu64bitalu}
  893. if right.location.size in [OS_64,OS_S64] then
  894. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  895. else
  896. {$endif not cpu64bitalu}
  897. hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
  898. else
  899. internalerror(200203284);
  900. end;
  901. end;
  902. {$ifdef SUPPORT_MMX}
  903. LOC_CMMXREGISTER,
  904. LOC_MMXREGISTER:
  905. begin
  906. if left.location.loc=LOC_CMMXREGISTER then
  907. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  908. else
  909. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  910. end;
  911. {$endif SUPPORT_MMX}
  912. LOC_MMREGISTER,
  913. LOC_CMMREGISTER:
  914. begin
  915. if (is_vector(left.resultdef)) then
  916. shuffle := nil
  917. else
  918. shuffle := mms_movescalar;
  919. case left.location.loc of
  920. LOC_CMMREGISTER,
  921. LOC_MMREGISTER:
  922. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.register, shuffle);
  923. LOC_REFERENCE,
  924. LOC_CREFERENCE:
  925. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.reference, shuffle);
  926. else
  927. internalerror(2009112601);
  928. end;
  929. end;
  930. LOC_REGISTER,
  931. LOC_CREGISTER :
  932. begin
  933. {$ifndef cpuhighleveltarget}
  934. {$ifdef cpu64bitalu}
  935. if left.location.size in [OS_128,OS_S128] then
  936. cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
  937. right.location.register128,left.location)
  938. else
  939. {$else cpu64bitalu}
  940. { also OS_F64 in case of mmreg -> intreg }
  941. if left.location.size in [OS_64,OS_S64,OS_F64] then
  942. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  943. right.location.register64,left.location)
  944. else
  945. {$endif cpu64bitalu}
  946. {$endif not cpuhighleveltarget}
  947. {$ifdef i8086}
  948. { prefer a_load_loc_ref, because it supports i8086-specific types
  949. that use registerhi (like 6-byte method pointers)
  950. (todo: maybe we should add a_load_loc_loc?) }
  951. if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  952. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.reference)
  953. else
  954. {$endif i8086}
  955. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
  956. end;
  957. LOC_FPUREGISTER,
  958. LOC_CFPUREGISTER :
  959. begin
  960. { we can't do direct moves between fpu and mm registers }
  961. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  962. begin
  963. {$if defined(x86) and not defined(llvm)}
  964. if not use_vectorfpu(right.resultdef) then
  965. begin
  966. { perform size conversion if needed (the mm-code cannot convert an }
  967. { extended into a double/single, since sse doesn't support extended) }
  968. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  969. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  970. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0,[]);
  971. right.location.reference:=href;
  972. right.resultdef:=left.resultdef;
  973. end;
  974. {$endif}
  975. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,false);
  976. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  977. right.resultdef,left.resultdef,
  978. right.location.register,left.location.register,mms_movescalar);
  979. end
  980. else
  981. hlcg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  982. right.resultdef,left.resultdef,
  983. right.location.register,left.location);
  984. end;
  985. LOC_SUBSETREG,
  986. LOC_CSUBSETREG:
  987. begin
  988. hlcg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  989. right.resultdef,left.resultdef,right.location.sreg,left.location);
  990. end;
  991. LOC_SUBSETREF,
  992. LOC_CSUBSETREF:
  993. begin
  994. {$ifndef cpu64bitalu}
  995. if right.location.size in [OS_64,OS_S64] then
  996. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  997. else
  998. {$endif not cpu64bitalu}
  999. hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  1000. right.resultdef,left.resultdef,right.location.sref,left.location);
  1001. end;
  1002. LOC_JUMP :
  1003. begin
  1004. current_asmdata.getjumplabel(hlabel);
  1005. hlcg.a_label(current_asmdata.CurrAsmList,right.location.truelabel);
  1006. if is_pasbool(left.resultdef) then
  1007. begin
  1008. {$ifndef cpu64bitalu}
  1009. if left.location.size in [OS_64,OS_S64] then
  1010. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
  1011. else
  1012. {$endif not cpu64bitalu}
  1013. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
  1014. end
  1015. else
  1016. begin
  1017. {$ifndef cpu64bitalu}
  1018. if left.location.size in [OS_64,OS_S64] then
  1019. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
  1020. else
  1021. {$endif not cpu64bitalu}
  1022. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
  1023. end;
  1024. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  1025. hlcg.a_label(current_asmdata.CurrAsmList,right.location.falselabel);
  1026. {$ifndef cpu64bitalu}
  1027. if left.location.size in [OS_64,OS_S64] then
  1028. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
  1029. else
  1030. {$endif not cpu64bitalu}
  1031. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
  1032. hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
  1033. end;
  1034. {$ifdef cpuflags}
  1035. LOC_FLAGS :
  1036. begin
  1037. if is_pasbool(left.resultdef) then
  1038. begin
  1039. case left.location.loc of
  1040. LOC_REGISTER,LOC_CREGISTER:
  1041. {$ifndef cpu64bitalu}
  1042. if left.location.size in [OS_S64,OS_64] then
  1043. begin
  1044. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
  1045. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1046. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
  1047. end
  1048. else
  1049. {$endif not cpu64bitalu}
  1050. begin
  1051. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  1052. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1053. end;
  1054. LOC_REFERENCE:
  1055. { i8086 and i386 have hacks in their code generators so that they can
  1056. deal with 64 bit locations in this parcticular case }
  1057. {$if not defined(cpu64bitalu) and not defined(x86)}
  1058. if left.location.size in [OS_S64,OS_64] then
  1059. begin
  1060. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1061. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1062. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1063. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1064. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1065. cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
  1066. end
  1067. else
  1068. {$endif not cpu64bitalu}
  1069. begin
  1070. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  1071. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1072. end;
  1073. LOC_CSUBSETREG,LOC_SUBSETREG,LOC_SUBSETREF:
  1074. begin
  1075. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1076. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1077. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1078. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1079. end;
  1080. else
  1081. internalerror(200203273);
  1082. end;
  1083. end
  1084. else
  1085. begin
  1086. {$ifndef cpu64bitalu}
  1087. if left.location.size in [OS_S64,OS_64] then
  1088. begin
  1089. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1090. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1091. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1092. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1093. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1094. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
  1095. r64,r64);
  1096. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
  1097. end
  1098. else
  1099. {$endif not cpu64bitalu}
  1100. begin
  1101. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1102. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1103. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1104. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  1105. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1106. end
  1107. end;
  1108. end;
  1109. {$endif cpuflags}
  1110. end;
  1111. end;
  1112. if releaseright then
  1113. location_freetemp(current_asmdata.CurrAsmList,right.location);
  1114. end;
  1115. {*****************************************************************************
  1116. SecondArrayConstruct
  1117. *****************************************************************************}
  1118. const
  1119. vtInteger = 0;
  1120. vtBoolean = 1;
  1121. vtChar = 2;
  1122. vtExtended = 3;
  1123. vtString = 4;
  1124. vtPointer = 5;
  1125. vtPChar = 6;
  1126. vtObject = 7;
  1127. vtClass = 8;
  1128. vtWideChar = 9;
  1129. vtPWideChar = 10;
  1130. vtAnsiString32 = 11;
  1131. vtCurrency = 12;
  1132. vtVariant = 13;
  1133. vtInterface = 14;
  1134. vtWideString = 15;
  1135. vtInt64 = 16;
  1136. vtQWord = 17;
  1137. vtUnicodeString = 18;
  1138. vtAnsiString16 = 19;
  1139. vtAnsiString64 = 20;
  1140. procedure tcgarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  1141. begin
  1142. { do nothing by default }
  1143. end;
  1144. procedure tcgarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  1145. begin
  1146. ref.alignment:=newalignment(ref.alignment,elesize);
  1147. inc(ref.offset,elesize);
  1148. end;
  1149. procedure tcgarrayconstructornode.pass_generate_code;
  1150. var
  1151. hp : tarrayconstructornode;
  1152. href,
  1153. fref : treference;
  1154. lt : tdef;
  1155. paraloc : tcgparalocation;
  1156. varvtypefield,
  1157. varfield : tfieldvarsym;
  1158. vtype : longint;
  1159. eledef: tdef;
  1160. elesize : longint;
  1161. tmpreg : tregister;
  1162. vaddr : boolean;
  1163. freetemp,
  1164. dovariant: boolean;
  1165. begin
  1166. if is_packed_array(resultdef) then
  1167. internalerror(200608042);
  1168. dovariant:=
  1169. ((nf_forcevaria in flags) or is_variant_array(resultdef)) and
  1170. not(target_info.system in systems_managed_vm);
  1171. eledef:=tarraydef(resultdef).elementdef;
  1172. elesize:=eledef.size;
  1173. if dovariant then
  1174. varvtypefield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VTYPE'))
  1175. else
  1176. varvtypefield:=nil;
  1177. { alignment is filled in by tg.gethltemp below }
  1178. location_reset_ref(location,LOC_CREFERENCE,OS_NO,0,[]);
  1179. fillchar(paraloc,sizeof(paraloc),0);
  1180. { Allocate always a temp, also if no elements are required, to
  1181. be sure that location is valid (PFV) }
  1182. { on the JVM platform, an array can have 0 elements; since the length
  1183. of the array is part of the array itself, make sure we allocate one
  1184. of the proper length to avoid getting unexpected results later --
  1185. allocating a temp of size 0 also forces it to be size 4 on regular
  1186. targets }
  1187. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  1188. href:=location.reference;
  1189. makearrayref(href,eledef);
  1190. { Process nodes in array constructor }
  1191. hp:=self;
  1192. while assigned(hp) do
  1193. begin
  1194. if assigned(hp.left) then
  1195. begin
  1196. freetemp:=true;
  1197. secondpass(hp.left);
  1198. if (hp.left.location.loc=LOC_JUMP)<>
  1199. (hp.left.expectloc=LOC_JUMP) then
  1200. internalerror(2007103101);
  1201. { Move flags and jump in register }
  1202. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  1203. hlcg.location_force_reg(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef,hp.left.resultdef,false);
  1204. if dovariant then
  1205. begin
  1206. { find the correct vtype value }
  1207. vtype:=$ff;
  1208. varfield:=nil;
  1209. vaddr:=false;
  1210. lt:=hp.left.resultdef;
  1211. case lt.typ of
  1212. enumdef,
  1213. orddef :
  1214. begin
  1215. if is_64bit(lt) then
  1216. begin
  1217. case torddef(lt).ordtype of
  1218. scurrency:
  1219. begin
  1220. vtype:=vtCurrency;
  1221. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1222. end;
  1223. s64bit:
  1224. begin
  1225. vtype:=vtInt64;
  1226. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINT64'));
  1227. end;
  1228. u64bit:
  1229. begin
  1230. vtype:=vtQWord;
  1231. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VQWORD'));
  1232. end;
  1233. end;
  1234. freetemp:=false;
  1235. vaddr:=true;
  1236. end
  1237. else if (lt.typ=enumdef) or
  1238. is_integer(lt) then
  1239. begin
  1240. vtype:=vtInteger;
  1241. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1242. end
  1243. else
  1244. if is_boolean(lt) then
  1245. begin
  1246. vtype:=vtBoolean;
  1247. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1248. end
  1249. else
  1250. if (lt.typ=orddef) then
  1251. begin
  1252. case torddef(lt).ordtype of
  1253. uchar:
  1254. begin
  1255. vtype:=vtChar;
  1256. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1257. end;
  1258. uwidechar:
  1259. begin
  1260. vtype:=vtWideChar;
  1261. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1262. end;
  1263. end;
  1264. end;
  1265. end;
  1266. floatdef :
  1267. begin
  1268. if is_currency(lt) then
  1269. begin
  1270. vtype:=vtCurrency;
  1271. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1272. end
  1273. else
  1274. begin
  1275. vtype:=vtExtended;
  1276. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VEXTENDED'));
  1277. end;
  1278. freetemp:=false;
  1279. vaddr:=true;
  1280. end;
  1281. procvardef,
  1282. pointerdef :
  1283. begin
  1284. if is_pchar(lt) then
  1285. begin
  1286. vtype:=vtPChar;
  1287. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPCHAR'));
  1288. end
  1289. else if is_pwidechar(lt) then
  1290. begin
  1291. vtype:=vtPWideChar;
  1292. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPWIDECHAR'));
  1293. end
  1294. else
  1295. begin
  1296. vtype:=vtPointer;
  1297. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPOINTER'));
  1298. end;
  1299. end;
  1300. variantdef :
  1301. begin
  1302. vtype:=vtVariant;
  1303. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VVARIANT'));
  1304. vaddr:=true;
  1305. freetemp:=false;
  1306. end;
  1307. classrefdef :
  1308. begin
  1309. vtype:=vtClass;
  1310. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCLASS'));
  1311. end;
  1312. objectdef :
  1313. if is_interface(lt) then
  1314. begin
  1315. vtype:=vtInterface;
  1316. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTERFACE'));
  1317. end
  1318. { vtObject really means a class based on TObject }
  1319. else if is_class(lt) then
  1320. begin
  1321. vtype:=vtObject;
  1322. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VOBJECT'));
  1323. end
  1324. else
  1325. internalerror(200505171);
  1326. stringdef :
  1327. begin
  1328. if is_shortstring(lt) then
  1329. begin
  1330. vtype:=vtString;
  1331. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VSTRING'));
  1332. vaddr:=true;
  1333. freetemp:=false;
  1334. end
  1335. else
  1336. if is_ansistring(lt) then
  1337. begin
  1338. vtype:=vtAnsiString;
  1339. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VANSISTRING'));
  1340. freetemp:=false;
  1341. end
  1342. else
  1343. if is_widestring(lt) then
  1344. begin
  1345. vtype:=vtWideString;
  1346. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VWIDESTRING'));
  1347. freetemp:=false;
  1348. end
  1349. else
  1350. if is_unicodestring(lt) then
  1351. begin
  1352. vtype:=vtUnicodeString;
  1353. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VUNICODESTRING'));
  1354. freetemp:=false;
  1355. end;
  1356. end;
  1357. end;
  1358. if vtype=$ff then
  1359. internalerror(14357);
  1360. if not assigned(varfield) then
  1361. internalerror(2015102901);
  1362. { write changing field update href to the next element }
  1363. fref:=href;
  1364. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varfield,fref);
  1365. if vaddr then
  1366. begin
  1367. hlcg.location_force_mem(current_asmdata.CurrAsmList,hp.left.location,lt);
  1368. tmpreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt));
  1369. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.resultdef,cpointerdef.getreusable(lt),hp.left.location.reference,tmpreg);
  1370. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt),varfield.vardef,tmpreg,fref);
  1371. end
  1372. else
  1373. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.resultdef,varfield.vardef,hp.left.location,fref);
  1374. { update href to the vtype field and write it }
  1375. fref:=href;
  1376. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varvtypefield,fref);
  1377. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,varvtypefield.vardef,vtype,fref);
  1378. { goto next array element }
  1379. advancearrayoffset(href,elesize);
  1380. end
  1381. else
  1382. { normal array constructor of the same type }
  1383. begin
  1384. if is_managed_type(resultdef) then
  1385. freetemp:=false;
  1386. case hp.left.location.loc of
  1387. LOC_MMREGISTER,
  1388. LOC_CMMREGISTER:
  1389. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,
  1390. hp.left.location.register,href,mms_movescalar);
  1391. LOC_FPUREGISTER,
  1392. LOC_CFPUREGISTER :
  1393. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,hp.left.location.register,href);
  1394. LOC_REFERENCE,
  1395. LOC_CREFERENCE :
  1396. begin
  1397. if is_shortstring(hp.left.resultdef) then
  1398. hlcg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1399. Tstringdef(hp.left.resultdef))
  1400. else
  1401. hlcg.g_concatcopy(current_asmdata.CurrAsmList,eledef,hp.left.location.reference,href);
  1402. end;
  1403. else
  1404. begin
  1405. {$ifndef cpuhighleveltarget}
  1406. {$ifdef cpu64bitalu}
  1407. if hp.left.location.size in [OS_128,OS_S128] then
  1408. cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1409. else
  1410. {$else cpu64bitalu}
  1411. if hp.left.location.size in [OS_64,OS_S64] then
  1412. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1413. else
  1414. {$endif cpu64bitalu}
  1415. {$endif not cpuhighleveltarget}
  1416. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
  1417. end;
  1418. end;
  1419. advancearrayoffset(href,elesize);
  1420. end;
  1421. if freetemp then
  1422. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1423. end;
  1424. { load next entry }
  1425. hp:=tarrayconstructornode(hp.right);
  1426. end;
  1427. end;
  1428. {*****************************************************************************
  1429. SecondRTTI
  1430. *****************************************************************************}
  1431. procedure tcgrttinode.pass_generate_code;
  1432. var
  1433. indirect : boolean;
  1434. begin
  1435. indirect := (tf_supports_packages in target_info.flags) and
  1436. (target_info.system in systems_indirect_var_imports) and
  1437. (cs_imported_data in current_settings.localswitches) and
  1438. (rttidef.owner.moduleid<>current_module.moduleid);
  1439. location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint),[]);
  1440. case rttidatatype of
  1441. rdt_normal:
  1442. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype,indirect);
  1443. rdt_ord2str:
  1444. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype,indirect);
  1445. rdt_str2ord:
  1446. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype,indirect);
  1447. end;
  1448. end;
  1449. begin
  1450. cloadnode:=tcgloadnode;
  1451. cassignmentnode:=tcgassignmentnode;
  1452. carrayconstructornode:=tcgarrayconstructornode;
  1453. crttinode:=tcgrttinode;
  1454. end.