ncgld.pas 76 KB

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