ncgld.pas 79 KB

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