ncgld.pas 79 KB

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