ncgld.pas 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537
  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. }
  668. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  669. (node_complexity(right)>node_complexity(left)) then
  670. begin
  671. secondpass(right);
  672. if codegenerror then
  673. exit;
  674. secondpass(left);
  675. if codegenerror then
  676. exit;
  677. end
  678. else
  679. begin
  680. { calculate left sides }
  681. secondpass(left);
  682. if codegenerror then
  683. exit;
  684. { tell the SSA/SSL code that the left side was handled first so
  685. ni SSL is done
  686. }
  687. oldflowcontrol:=flowcontrol;
  688. include(flowcontrol,fc_lefthandled);
  689. secondpass(right);
  690. flowcontrol:=oldflowcontrol;
  691. if codegenerror then
  692. exit;
  693. end;
  694. releaseright:=
  695. (left.nodetype<>temprefn) or
  696. not(ti_const in ttemprefnode(left).tempflags);
  697. { shortstring assignments are handled separately }
  698. if is_shortstring(left.resultdef) then
  699. begin
  700. {
  701. we can get here only in the following situations
  702. for the right node:
  703. - empty constant string
  704. - char
  705. }
  706. { The addn is replaced by a blockn or calln that already returns
  707. a shortstring }
  708. if is_shortstring(right.resultdef) and
  709. (right.nodetype in [blockn,calln]) then
  710. begin
  711. { verify that we indeed have nothing to do }
  712. if not(nf_assign_done_in_right in flags) then
  713. internalerror(2015042201);
  714. end
  715. { empty constant string }
  716. else if (right.nodetype=stringconstn) and
  717. (tstringconstnode(right).len=0) then
  718. begin
  719. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),tpointerdef(charpointertype),left.location.reference);
  720. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,cansichartype,0,left.location.reference);
  721. end
  722. { char loading }
  723. else if is_char(right.resultdef) then
  724. begin
  725. if right.nodetype=ordconstn then
  726. begin
  727. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),cpointerdef.getreusable(u16inttype),left.location.reference);
  728. if (target_info.endian = endian_little) then
  729. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,(tordconstnode(right).value.svalue shl 8) or 1,
  730. setalignment(left.location.reference,1))
  731. else
  732. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,tordconstnode(right).value.svalue or (1 shl 8),
  733. setalignment(left.location.reference,1));
  734. end
  735. else
  736. begin
  737. href:=left.location.reference;
  738. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),tpointerdef(charpointertype),href);
  739. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,cansichartype,1,href);
  740. inc(href.offset,1);
  741. href.alignment:=1;
  742. case right.location.loc of
  743. LOC_REGISTER,
  744. LOC_CREGISTER :
  745. begin
  746. {$ifndef cpuhighleveltarget}
  747. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  748. {$else not cpuhighleveltarget}
  749. r:=hlcg.getintregister(current_asmdata.CurrAsmList,u8inttype);
  750. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,cansichartype,u8inttype,right.location.register,r);
  751. {$endif cpuhighleveltarget}
  752. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,r,href);
  753. end;
  754. LOC_REFERENCE,
  755. LOC_CREFERENCE :
  756. hlcg.a_load_ref_ref(current_asmdata.CurrAsmList,cansichartype,cansichartype,right.location.reference,href);
  757. else
  758. internalerror(200205111);
  759. end;
  760. end;
  761. end
  762. else
  763. internalerror(2002042410);
  764. end
  765. { try to reuse memory locations instead of copying }
  766. { copy to a memory location ... }
  767. else if (right.location.loc = LOC_REFERENCE) and
  768. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  769. begin
  770. { if it worked, we're done }
  771. end
  772. else
  773. begin
  774. { SSA support }
  775. hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
  776. hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,right,true);
  777. case right.location.loc of
  778. LOC_CONSTANT :
  779. begin
  780. {$ifndef cpu64bitalu}
  781. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  782. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  783. else
  784. {$endif not cpu64bitalu}
  785. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
  786. end;
  787. LOC_REFERENCE,
  788. LOC_CREFERENCE :
  789. begin
  790. case left.location.loc of
  791. LOC_REGISTER,
  792. LOC_CREGISTER :
  793. begin
  794. {$ifndef cpuhighleveltarget}
  795. {$ifdef cpu64bitalu}
  796. if left.location.size in [OS_128,OS_S128] then
  797. cg128.a_load128_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register128)
  798. else
  799. {$else cpu64bitalu}
  800. if left.location.size in [OS_64,OS_S64] then
  801. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  802. else
  803. {$endif cpu64bitalu}
  804. {$endif not cpuhighleveltarget}
  805. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
  806. end;
  807. LOC_FPUREGISTER,
  808. LOC_CFPUREGISTER :
  809. begin
  810. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  811. right.resultdef,left.resultdef,
  812. right.location.reference,
  813. left.location.register);
  814. end;
  815. LOC_REFERENCE,
  816. LOC_CREFERENCE :
  817. begin
  818. if (left.resultdef.typ=floatdef) and
  819. (right.resultdef.typ=floatdef) and
  820. (left.location.size<>right.location.size) then
  821. begin
  822. { assume that all float types can be handed by the
  823. fpu if one can be handled by the fpu }
  824. if not use_vectorfpu(left.resultdef) or
  825. not use_vectorfpu(right.resultdef) then
  826. hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  827. right.resultdef,left.resultdef,
  828. right.location.reference,left.location.reference)
  829. else
  830. hlcg.a_loadmm_ref_ref(current_asmdata.CurrAsmList,
  831. right.resultdef,left.resultdef,
  832. right.location.reference,left.location.reference,mms_movescalar)
  833. end
  834. else
  835. begin
  836. { TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  837. { Use unaligned copy when the offset is not aligned }
  838. len:=left.resultdef.size;
  839. { can be 0 in case of formaldef on JVM target }
  840. if len=0 then
  841. len:=sizeof(pint);
  842. { data smaller than an aint has less alignment requirements }
  843. { max(1,...) avoids div by zero in case of an empty record }
  844. alignmentrequirement:=min(max(1,len),sizeof(aint));
  845. if (right.location.reference.offset mod alignmentrequirement<>0) or
  846. (left.location.reference.offset mod alignmentrequirement<>0) or
  847. (right.resultdef.alignment<alignmentrequirement) or
  848. ((right.location.reference.alignment<>0) and
  849. (right.location.reference.alignment<alignmentrequirement)) or
  850. ((left.location.reference.alignment<>0) and
  851. (left.location.reference.alignment<alignmentrequirement)) then
  852. hlcg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference)
  853. else
  854. hlcg.g_concatcopy(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference);
  855. end;
  856. end;
  857. LOC_MMREGISTER,
  858. LOC_CMMREGISTER:
  859. begin
  860. {$if defined(x86) and not defined(llvm)}
  861. if (right.resultdef.typ=floatdef) and
  862. not use_vectorfpu(right.resultdef) then
  863. begin
  864. { perform size conversion if needed (the mm-code cannot }
  865. { convert an extended into a double/single, since sse }
  866. { doesn't support extended) }
  867. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  868. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  869. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  870. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  871. if releaseright then
  872. location_freetemp(current_asmdata.CurrAsmList,right.location);
  873. releaseright:=true;
  874. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0,[]);
  875. right.location.reference:=href;
  876. right.resultdef:=left.resultdef;
  877. end;
  878. {$endif}
  879. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  880. right.resultdef,
  881. left.resultdef,
  882. right.location.reference,
  883. left.location.register,mms_movescalar);
  884. end;
  885. LOC_SUBSETREG,
  886. LOC_CSUBSETREG:
  887. hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
  888. LOC_SUBSETREF,
  889. LOC_CSUBSETREF:
  890. {$ifndef cpu64bitalu}
  891. if right.location.size in [OS_64,OS_S64] then
  892. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  893. else
  894. {$endif not cpu64bitalu}
  895. hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
  896. else
  897. internalerror(200203284);
  898. end;
  899. end;
  900. {$ifdef SUPPORT_MMX}
  901. LOC_CMMXREGISTER,
  902. LOC_MMXREGISTER:
  903. begin
  904. if left.location.loc=LOC_CMMXREGISTER then
  905. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  906. else
  907. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  908. end;
  909. {$endif SUPPORT_MMX}
  910. LOC_MMREGISTER,
  911. LOC_CMMREGISTER:
  912. begin
  913. if (is_vector(left.resultdef)) then
  914. shuffle := nil
  915. else
  916. shuffle := mms_movescalar;
  917. case left.location.loc of
  918. LOC_CMMREGISTER,
  919. LOC_MMREGISTER:
  920. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.register, shuffle);
  921. LOC_REFERENCE,
  922. LOC_CREFERENCE:
  923. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.reference, shuffle);
  924. else
  925. internalerror(2009112601);
  926. end;
  927. end;
  928. LOC_REGISTER,
  929. LOC_CREGISTER :
  930. begin
  931. {$ifndef cpuhighleveltarget}
  932. {$ifdef cpu64bitalu}
  933. if left.location.size in [OS_128,OS_S128] then
  934. cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
  935. right.location.register128,left.location)
  936. else
  937. {$else cpu64bitalu}
  938. { also OS_F64 in case of mmreg -> intreg }
  939. if left.location.size in [OS_64,OS_S64,OS_F64] then
  940. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  941. right.location.register64,left.location)
  942. else
  943. {$endif cpu64bitalu}
  944. {$endif not cpuhighleveltarget}
  945. {$ifdef i8086}
  946. { prefer a_load_loc_ref, because it supports i8086-specific types
  947. that use registerhi (like 6-byte method pointers)
  948. (todo: maybe we should add a_load_loc_loc?) }
  949. if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  950. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.reference)
  951. else
  952. {$endif i8086}
  953. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
  954. end;
  955. LOC_FPUREGISTER,
  956. LOC_CFPUREGISTER :
  957. begin
  958. { we can't do direct moves between fpu and mm registers }
  959. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  960. begin
  961. {$if defined(x86) and not defined(llvm)}
  962. if not use_vectorfpu(right.resultdef) then
  963. begin
  964. { perform size conversion if needed (the mm-code cannot convert an }
  965. { extended into a double/single, since sse doesn't support extended) }
  966. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  967. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  968. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0,[]);
  969. right.location.reference:=href;
  970. right.resultdef:=left.resultdef;
  971. end;
  972. {$endif}
  973. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,false);
  974. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  975. right.resultdef,left.resultdef,
  976. right.location.register,left.location.register,mms_movescalar);
  977. end
  978. else
  979. hlcg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  980. right.resultdef,left.resultdef,
  981. right.location.register,left.location);
  982. end;
  983. LOC_SUBSETREG,
  984. LOC_CSUBSETREG:
  985. begin
  986. hlcg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  987. right.resultdef,left.resultdef,right.location.sreg,left.location);
  988. end;
  989. LOC_SUBSETREF,
  990. LOC_CSUBSETREF:
  991. begin
  992. {$ifndef cpu64bitalu}
  993. if right.location.size in [OS_64,OS_S64] then
  994. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  995. else
  996. {$endif not cpu64bitalu}
  997. hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  998. right.resultdef,left.resultdef,right.location.sref,left.location);
  999. end;
  1000. LOC_JUMP :
  1001. begin
  1002. current_asmdata.getjumplabel(hlabel);
  1003. hlcg.a_label(current_asmdata.CurrAsmList,right.location.truelabel);
  1004. if is_pasbool(left.resultdef) then
  1005. begin
  1006. {$ifndef cpu64bitalu}
  1007. if left.location.size in [OS_64,OS_S64] then
  1008. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
  1009. else
  1010. {$endif not cpu64bitalu}
  1011. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
  1012. end
  1013. else
  1014. begin
  1015. {$ifndef cpu64bitalu}
  1016. if left.location.size in [OS_64,OS_S64] then
  1017. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
  1018. else
  1019. {$endif not cpu64bitalu}
  1020. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
  1021. end;
  1022. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  1023. hlcg.a_label(current_asmdata.CurrAsmList,right.location.falselabel);
  1024. {$ifndef cpu64bitalu}
  1025. if left.location.size in [OS_64,OS_S64] then
  1026. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
  1027. else
  1028. {$endif not cpu64bitalu}
  1029. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
  1030. hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
  1031. end;
  1032. {$ifdef cpuflags}
  1033. LOC_FLAGS :
  1034. begin
  1035. if is_pasbool(left.resultdef) then
  1036. begin
  1037. case left.location.loc of
  1038. LOC_REGISTER,LOC_CREGISTER:
  1039. {$ifndef cpu64bitalu}
  1040. if left.location.size in [OS_S64,OS_64] then
  1041. begin
  1042. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
  1043. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1044. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
  1045. end
  1046. else
  1047. {$endif not cpu64bitalu}
  1048. begin
  1049. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  1050. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1051. end;
  1052. LOC_REFERENCE:
  1053. { i8086 and i386 have hacks in their code generators so that they can
  1054. deal with 64 bit locations in this parcticular case }
  1055. {$if not defined(cpu64bitalu) and not defined(x86)}
  1056. if left.location.size in [OS_S64,OS_64] then
  1057. begin
  1058. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1059. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1060. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1061. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1062. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1063. cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
  1064. end
  1065. else
  1066. {$endif not cpu64bitalu}
  1067. begin
  1068. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  1069. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1070. end;
  1071. LOC_CSUBSETREG,LOC_SUBSETREG,LOC_SUBSETREF:
  1072. begin
  1073. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1074. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1075. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1076. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1077. end;
  1078. else
  1079. internalerror(200203273);
  1080. end;
  1081. end
  1082. else
  1083. begin
  1084. {$ifndef cpu64bitalu}
  1085. if left.location.size in [OS_S64,OS_64] then
  1086. begin
  1087. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1088. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1089. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1090. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1091. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1092. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
  1093. r64,r64);
  1094. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
  1095. end
  1096. else
  1097. {$endif not cpu64bitalu}
  1098. begin
  1099. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1100. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1101. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1102. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  1103. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1104. end
  1105. end;
  1106. end;
  1107. {$endif cpuflags}
  1108. end;
  1109. end;
  1110. if releaseright then
  1111. location_freetemp(current_asmdata.CurrAsmList,right.location);
  1112. end;
  1113. {*****************************************************************************
  1114. SecondArrayConstruct
  1115. *****************************************************************************}
  1116. const
  1117. vtInteger = 0;
  1118. vtBoolean = 1;
  1119. vtChar = 2;
  1120. vtExtended = 3;
  1121. vtString = 4;
  1122. vtPointer = 5;
  1123. vtPChar = 6;
  1124. vtObject = 7;
  1125. vtClass = 8;
  1126. vtWideChar = 9;
  1127. vtPWideChar = 10;
  1128. vtAnsiString32 = 11;
  1129. vtCurrency = 12;
  1130. vtVariant = 13;
  1131. vtInterface = 14;
  1132. vtWideString = 15;
  1133. vtInt64 = 16;
  1134. vtQWord = 17;
  1135. vtUnicodeString = 18;
  1136. vtAnsiString16 = 19;
  1137. vtAnsiString64 = 20;
  1138. procedure tcgarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  1139. begin
  1140. { do nothing by default }
  1141. end;
  1142. procedure tcgarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  1143. begin
  1144. ref.alignment:=newalignment(ref.alignment,elesize);
  1145. inc(ref.offset,elesize);
  1146. end;
  1147. procedure tcgarrayconstructornode.pass_generate_code;
  1148. var
  1149. hp : tarrayconstructornode;
  1150. href,
  1151. fref : treference;
  1152. lt : tdef;
  1153. paraloc : tcgparalocation;
  1154. varvtypefield,
  1155. varfield : tfieldvarsym;
  1156. vtype : longint;
  1157. eledef: tdef;
  1158. elesize : longint;
  1159. tmpreg : tregister;
  1160. vaddr : boolean;
  1161. freetemp,
  1162. dovariant: boolean;
  1163. begin
  1164. if is_packed_array(resultdef) then
  1165. internalerror(200608042);
  1166. dovariant:=
  1167. ((nf_forcevaria in flags) or is_variant_array(resultdef)) and
  1168. not(target_info.system in systems_managed_vm);
  1169. eledef:=tarraydef(resultdef).elementdef;
  1170. elesize:=eledef.size;
  1171. if dovariant then
  1172. varvtypefield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VTYPE'))
  1173. else
  1174. varvtypefield:=nil;
  1175. { alignment is filled in by tg.gethltemp below }
  1176. location_reset_ref(location,LOC_CREFERENCE,OS_NO,0,[]);
  1177. fillchar(paraloc,sizeof(paraloc),0);
  1178. { Allocate always a temp, also if no elements are required, to
  1179. be sure that location is valid (PFV) }
  1180. { on the JVM platform, an array can have 0 elements; since the length
  1181. of the array is part of the array itself, make sure we allocate one
  1182. of the proper length to avoid getting unexpected results later --
  1183. allocating a temp of size 0 also forces it to be size 4 on regular
  1184. targets }
  1185. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  1186. href:=location.reference;
  1187. makearrayref(href,eledef);
  1188. { Process nodes in array constructor }
  1189. hp:=self;
  1190. while assigned(hp) do
  1191. begin
  1192. if assigned(hp.left) then
  1193. begin
  1194. freetemp:=true;
  1195. secondpass(hp.left);
  1196. if (hp.left.location.loc=LOC_JUMP)<>
  1197. (hp.left.expectloc=LOC_JUMP) then
  1198. internalerror(2007103101);
  1199. { Move flags and jump in register }
  1200. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  1201. hlcg.location_force_reg(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef,hp.left.resultdef,false);
  1202. if dovariant then
  1203. begin
  1204. { find the correct vtype value }
  1205. vtype:=$ff;
  1206. varfield:=nil;
  1207. vaddr:=false;
  1208. lt:=hp.left.resultdef;
  1209. case lt.typ of
  1210. enumdef,
  1211. orddef :
  1212. begin
  1213. if is_64bit(lt) then
  1214. begin
  1215. case torddef(lt).ordtype of
  1216. scurrency:
  1217. begin
  1218. vtype:=vtCurrency;
  1219. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1220. end;
  1221. s64bit:
  1222. begin
  1223. vtype:=vtInt64;
  1224. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINT64'));
  1225. end;
  1226. u64bit:
  1227. begin
  1228. vtype:=vtQWord;
  1229. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VQWORD'));
  1230. end;
  1231. end;
  1232. freetemp:=false;
  1233. vaddr:=true;
  1234. end
  1235. else if (lt.typ=enumdef) or
  1236. is_integer(lt) then
  1237. begin
  1238. vtype:=vtInteger;
  1239. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1240. end
  1241. else
  1242. if is_boolean(lt) then
  1243. begin
  1244. vtype:=vtBoolean;
  1245. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1246. end
  1247. else
  1248. if (lt.typ=orddef) then
  1249. begin
  1250. case torddef(lt).ordtype of
  1251. uchar:
  1252. begin
  1253. vtype:=vtChar;
  1254. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1255. end;
  1256. uwidechar:
  1257. begin
  1258. vtype:=vtWideChar;
  1259. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1260. end;
  1261. end;
  1262. end;
  1263. end;
  1264. floatdef :
  1265. begin
  1266. if is_currency(lt) then
  1267. begin
  1268. vtype:=vtCurrency;
  1269. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1270. end
  1271. else
  1272. begin
  1273. vtype:=vtExtended;
  1274. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VEXTENDED'));
  1275. end;
  1276. freetemp:=false;
  1277. vaddr:=true;
  1278. end;
  1279. procvardef,
  1280. pointerdef :
  1281. begin
  1282. if is_pchar(lt) then
  1283. begin
  1284. vtype:=vtPChar;
  1285. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPCHAR'));
  1286. end
  1287. else if is_pwidechar(lt) then
  1288. begin
  1289. vtype:=vtPWideChar;
  1290. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPWIDECHAR'));
  1291. end
  1292. else
  1293. begin
  1294. vtype:=vtPointer;
  1295. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPOINTER'));
  1296. end;
  1297. end;
  1298. variantdef :
  1299. begin
  1300. vtype:=vtVariant;
  1301. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VVARIANT'));
  1302. vaddr:=true;
  1303. freetemp:=false;
  1304. end;
  1305. classrefdef :
  1306. begin
  1307. vtype:=vtClass;
  1308. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCLASS'));
  1309. end;
  1310. objectdef :
  1311. if is_interface(lt) then
  1312. begin
  1313. vtype:=vtInterface;
  1314. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTERFACE'));
  1315. end
  1316. { vtObject really means a class based on TObject }
  1317. else if is_class(lt) then
  1318. begin
  1319. vtype:=vtObject;
  1320. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VOBJECT'));
  1321. end
  1322. else
  1323. internalerror(200505171);
  1324. stringdef :
  1325. begin
  1326. if is_shortstring(lt) then
  1327. begin
  1328. vtype:=vtString;
  1329. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VSTRING'));
  1330. vaddr:=true;
  1331. freetemp:=false;
  1332. end
  1333. else
  1334. if is_ansistring(lt) then
  1335. begin
  1336. vtype:=vtAnsiString;
  1337. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VANSISTRING'));
  1338. freetemp:=false;
  1339. end
  1340. else
  1341. if is_widestring(lt) then
  1342. begin
  1343. vtype:=vtWideString;
  1344. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VWIDESTRING'));
  1345. freetemp:=false;
  1346. end
  1347. else
  1348. if is_unicodestring(lt) then
  1349. begin
  1350. vtype:=vtUnicodeString;
  1351. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VUNICODESTRING'));
  1352. freetemp:=false;
  1353. end;
  1354. end;
  1355. end;
  1356. if vtype=$ff then
  1357. internalerror(14357);
  1358. if not assigned(varfield) then
  1359. internalerror(2015102901);
  1360. { write changing field update href to the next element }
  1361. fref:=href;
  1362. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varfield,fref);
  1363. if vaddr then
  1364. begin
  1365. hlcg.location_force_mem(current_asmdata.CurrAsmList,hp.left.location,lt);
  1366. tmpreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt));
  1367. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.resultdef,cpointerdef.getreusable(lt),hp.left.location.reference,tmpreg);
  1368. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt),varfield.vardef,tmpreg,fref);
  1369. end
  1370. else
  1371. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.resultdef,varfield.vardef,hp.left.location,fref);
  1372. { update href to the vtype field and write it }
  1373. fref:=href;
  1374. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varvtypefield,fref);
  1375. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,varvtypefield.vardef,vtype,fref);
  1376. { goto next array element }
  1377. advancearrayoffset(href,elesize);
  1378. end
  1379. else
  1380. { normal array constructor of the same type }
  1381. begin
  1382. if is_managed_type(resultdef) then
  1383. freetemp:=false;
  1384. case hp.left.location.loc of
  1385. LOC_MMREGISTER,
  1386. LOC_CMMREGISTER:
  1387. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,
  1388. hp.left.location.register,href,mms_movescalar);
  1389. LOC_FPUREGISTER,
  1390. LOC_CFPUREGISTER :
  1391. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,hp.left.location.register,href);
  1392. LOC_REFERENCE,
  1393. LOC_CREFERENCE :
  1394. begin
  1395. if is_shortstring(hp.left.resultdef) then
  1396. hlcg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1397. Tstringdef(hp.left.resultdef))
  1398. else
  1399. hlcg.g_concatcopy(current_asmdata.CurrAsmList,eledef,hp.left.location.reference,href);
  1400. end;
  1401. else
  1402. begin
  1403. {$ifndef cpuhighleveltarget}
  1404. {$ifdef cpu64bitalu}
  1405. if hp.left.location.size in [OS_128,OS_S128] then
  1406. cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1407. else
  1408. {$else cpu64bitalu}
  1409. if hp.left.location.size in [OS_64,OS_S64] then
  1410. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1411. else
  1412. {$endif cpu64bitalu}
  1413. {$endif not cpuhighleveltarget}
  1414. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
  1415. end;
  1416. end;
  1417. advancearrayoffset(href,elesize);
  1418. end;
  1419. if freetemp then
  1420. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1421. end;
  1422. { load next entry }
  1423. hp:=tarrayconstructornode(hp.right);
  1424. end;
  1425. end;
  1426. {*****************************************************************************
  1427. SecondRTTI
  1428. *****************************************************************************}
  1429. procedure tcgrttinode.pass_generate_code;
  1430. var
  1431. indirect : boolean;
  1432. begin
  1433. indirect := (tf_supports_packages in target_info.flags) and
  1434. (target_info.system in systems_indirect_var_imports) and
  1435. (cs_imported_data in current_settings.localswitches) and
  1436. (rttidef.owner.moduleid<>current_module.moduleid);
  1437. location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint),[]);
  1438. case rttidatatype of
  1439. rdt_normal:
  1440. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype,indirect);
  1441. rdt_ord2str:
  1442. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype,indirect);
  1443. rdt_str2ord:
  1444. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype,indirect);
  1445. end;
  1446. end;
  1447. begin
  1448. cloadnode:=tcgloadnode;
  1449. cassignmentnode:=tcgassignmentnode;
  1450. carrayconstructornode:=tcgarrayconstructornode;
  1451. crttinode:=tcgrttinode;
  1452. end.