ncgld.pas 79 KB

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