ncgld.pas 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for nodes that handle loads and assignments which
  4. are the same for all (most) processors
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgld;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,
  23. symtype,symsym,
  24. aasmdata,
  25. node,nld,cgutils;
  26. type
  27. tcgloadnode = class(tloadnode)
  28. protected
  29. procedure generate_nested_access(vs: tsym);virtual;
  30. procedure generate_absaddr_access(vs: tabsolutevarsym); virtual;
  31. procedure generate_threadvar_access(gvs: tstaticvarsym); virtual;
  32. function use_indirect_symbol(gvs: tstaticvarsym): boolean;
  33. public
  34. procedure pass_generate_code;override;
  35. procedure changereflocation(const ref: treference);
  36. end;
  37. tcgassignmentnode = class(tassignmentnode)
  38. protected
  39. function maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;virtual;
  40. public
  41. procedure pass_generate_code;override;
  42. end;
  43. tcgarrayconstructornode = class(tarrayconstructornode)
  44. protected
  45. procedure makearrayref(var ref: treference; eledef: tdef);virtual;
  46. procedure advancearrayoffset(var ref: treference; elesize: asizeint);virtual;
  47. public
  48. procedure pass_generate_code;override;
  49. end;
  50. tcgrttinode = class(trttinode)
  51. procedure pass_generate_code;override;
  52. end;
  53. implementation
  54. uses
  55. cutils,
  56. systems,
  57. verbose,globals,constexp,fmodule,
  58. nutils,
  59. symtable,symconst,symdef,defutil,paramgr,ncon,nbas,ncgrtti,
  60. aasmbase,
  61. cgbase,pass_2,
  62. procinfo,
  63. cpubase,parabase,
  64. tgobj,
  65. cgobj,hlcgobj,
  66. ncgbas,ncgflw,
  67. wpobase;
  68. {*****************************************************************************
  69. SSA (for memory temps) support
  70. *****************************************************************************}
  71. type
  72. preplacerefrec = ^treplacerefrec;
  73. treplacerefrec = record
  74. old, new: preference;
  75. ressym: tsym;
  76. end;
  77. function doreplaceref(var n: tnode; para: pointer): foreachnoderesult;
  78. var
  79. rr: preplacerefrec absolute para;
  80. begin
  81. result := fen_false;
  82. case n.nodetype of
  83. loadn:
  84. begin
  85. { regular variable }
  86. if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
  87. not assigned(tloadnode(n).left) and
  88. { not function result, or no exit in function }
  89. (((tloadnode(n).symtableentry <> rr^.ressym) and
  90. not(vo_is_funcret in tabstractvarsym(tloadnode(n).symtableentry).varoptions)) or
  91. not(fc_exit in flowcontrol)) and
  92. { stored in memory... }
  93. (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_REFERENCE]) and
  94. { ... at the place we are looking for }
  95. references_equal(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.reference,rr^.old^) and
  96. { its address cannot have escaped the current routine }
  97. not(tabstractvarsym(tloadnode(n).symtableentry).addr_taken) and
  98. { it is not accessed in nested procedures }
  99. not(tabstractvarsym(tloadnode(n).symtableentry).different_scope) then
  100. begin
  101. { relocate variable }
  102. tcgloadnode(n).changereflocation(rr^.new^);
  103. result := fen_norecurse_true;
  104. end;
  105. end;
  106. temprefn:
  107. begin
  108. if (ti_valid in ttemprefnode(n).tempflags) and
  109. { memory temp... }
  110. (ttemprefnode(n).tempinfo^.location.loc in [LOC_REFERENCE]) and
  111. { ... at the place we are looking for }
  112. references_equal(ttemprefnode(n).tempinfo^.location.reference,rr^.old^) and
  113. { its address cannot have escaped the current routine }
  114. not(ti_addr_taken in ttemprefnode(n).tempflags) then
  115. begin
  116. { relocate the temp }
  117. tcgtemprefnode(n).changelocation(rr^.new^);
  118. result := fen_norecurse_true;
  119. end;
  120. end;
  121. { Subscriptn must be rejected, otherwise we may replace an
  122. an entire record with a temp for its first field, mantis #13948)
  123. Exception: the field's size is the same as the entire record
  124. The same goes for array indexing
  125. }
  126. subscriptn,
  127. vecn:
  128. if not(tunarynode(n).left.resultdef.typ in [recorddef,objectdef,arraydef,stringdef]) or
  129. { make sure we don't try to call resultdef.size for types that
  130. don't have a compile-time size such as open arrays }
  131. is_special_array(tunarynode(n).left.resultdef) or
  132. (tunarynode(n).left.resultdef.size<>tunarynode(n).resultdef.size) then
  133. result := fen_norecurse_false;
  134. { optimize the searching a bit }
  135. derefn,addrn,
  136. calln,inlinen,casen,
  137. addn,subn,muln,
  138. andn,orn,xorn,
  139. ltn,lten,gtn,gten,equaln,unequaln,
  140. slashn,divn,shrn,shln,notn,
  141. inn,
  142. asn,isn:
  143. result := fen_norecurse_false;
  144. end;
  145. end;
  146. function tcgassignmentnode.maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;
  147. var
  148. rr: treplacerefrec;
  149. begin
  150. result := false;
  151. { only do for -O2 or higher (breaks debugging since }
  152. { variables move to different memory locations) }
  153. if not(cs_opt_level2 in current_settings.optimizerswitches) or
  154. { must be a copy to a memory location ... }
  155. (n.location.loc <> LOC_REFERENCE) or
  156. { not inside a control flow statement and no goto's in sight }
  157. ([fc_inflowcontrol,fc_gotolabel] * flowcontrol <> []) or
  158. { not for refcounted types, because those locations are }
  159. { still used later on in initialisation/finalisation code }
  160. is_managed_type(n.resultdef) or
  161. { source and destination are temps (= not global variables) }
  162. { and both point to the start of a temp, and the source is a }
  163. { non-persistent temp (otherwise we need some kind of copy- }
  164. { on-write support in case later on both are still used) }
  165. not tg.isstartoftemp(newref) or
  166. not tg.isstartoftemp(n.location.reference) or
  167. (tg.gettypeoftemp(newref) <> tt_normal) or
  168. not (tg.gettypeoftemp(n.location.reference) in [tt_normal,tt_persistent]) or
  169. { and both have the same size }
  170. (tg.sizeoftemp(current_asmdata.CurrAsmList,newref) <> tg.sizeoftemp(current_asmdata.CurrAsmList,n.location.reference)) then
  171. exit;
  172. { find the source of the old reference (loadnode or tempnode) }
  173. { and replace it with the new reference }
  174. rr.old := @n.location.reference;
  175. rr.new := @newref;
  176. rr.ressym := nil;
  177. if assigned(current_procinfo.procdef.funcretsym) and
  178. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
  179. if (current_procinfo.procdef.proctypeoption=potype_constructor) then
  180. rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
  181. else
  182. rr.ressym:=current_procinfo.procdef.funcretsym;
  183. { if source not found, don't do anything }
  184. if not foreachnodestatic(n,@doreplaceref,@rr) then
  185. exit;
  186. n.location.reference := newref;
  187. result:=true;
  188. end;
  189. {*****************************************************************************
  190. SecondLoad
  191. *****************************************************************************}
  192. procedure tcgloadnode.changereflocation(const ref: treference);
  193. var
  194. oldtemptype: ttemptype;
  195. begin
  196. if (location.loc<>LOC_REFERENCE) then
  197. internalerror(2007020812);
  198. if not tg.istemp(location.reference) then
  199. internalerror(2007020813);
  200. oldtemptype:=tg.gettypeoftemp(location.reference);
  201. if (oldtemptype = tt_persistent) then
  202. tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,tt_normal);
  203. tg.ungettemp(current_asmdata.CurrAsmList,location.reference);
  204. location.reference:=ref;
  205. tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,oldtemptype);
  206. tabstractnormalvarsym(symtableentry).localloc:=location;
  207. end;
  208. procedure tcgloadnode.generate_nested_access(vs: tsym);
  209. var
  210. { paramter declared as tsym to reduce interface unit dependencies }
  211. lvs: tabstractnormalvarsym absolute vs;
  212. begin
  213. secondpass(left);
  214. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  215. internalerror(200309286);
  216. if lvs.localloc.loc<>LOC_REFERENCE then
  217. internalerror(200409241);
  218. hlcg.reference_reset_base(location.reference,left.resultdef,left.location.register,lvs.localloc.reference.offset,ctempposinvalid,lvs.localloc.reference.alignment,lvs.localloc.reference.volatility);
  219. end;
  220. procedure tcgloadnode.generate_absaddr_access(vs: tabsolutevarsym);
  221. begin
  222. location.reference.offset:=asizeint(vs.addroffset);
  223. location.reference.volatility:=[vol_read,vol_write];
  224. end;
  225. procedure tcgloadnode.generate_threadvar_access(gvs: tstaticvarsym);
  226. var
  227. respara,
  228. paraloc1 : tcgpara;
  229. fieldptrdef,
  230. pvd : tdef;
  231. endrelocatelab,
  232. norelocatelab : tasmlabel;
  233. tvref,
  234. href : treference;
  235. hregister, hreg_tv_rec : tregister;
  236. tv_rec : trecorddef;
  237. tv_index_field,
  238. tv_non_mt_data_field: tsym;
  239. tmpresloc: tlocation;
  240. issystemunit,
  241. indirect : boolean;
  242. size_opt : boolean;
  243. begin
  244. if (tf_section_threadvars in target_info.flags) then
  245. begin
  246. if gvs.localloc.loc=LOC_INVALID then
  247. if not(vo_is_weak_external in gvs.varoptions) then
  248. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,location.reference.alignment,[])
  249. else
  250. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,location.reference.alignment,[])
  251. else
  252. location:=gvs.localloc;
  253. end
  254. else
  255. begin
  256. {
  257. Thread var loading is optimized to first check if
  258. a relocate function is available. When the function
  259. is available it is called to retrieve the address.
  260. Otherwise the address is loaded with the symbol
  261. }
  262. tv_rec:=get_threadvar_record(resultdef,tv_index_field,tv_non_mt_data_field);
  263. fieldptrdef:=cpointerdef.getreusable(resultdef);
  264. current_asmdata.getjumplabel(norelocatelab);
  265. current_asmdata.getjumplabel(endrelocatelab);
  266. { make sure hregister can't allocate the register necessary for the parameter }
  267. pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
  268. if pvd.typ<>procvardef then
  269. internalerror(2012120901);
  270. { FPC_THREADVAR_RELOCATE is nil? }
  271. issystemunit:=not current_module.is_unit or
  272. (
  273. assigned(current_module.globalsymtable) and
  274. (current_module.globalsymtable=systemunit)
  275. ) or
  276. (
  277. not assigned(current_module.globalsymtable) and
  278. (current_module.localsymtable=systemunit)
  279. );
  280. indirect:=(tf_supports_packages in target_info.flags) and
  281. (target_info.system in systems_indirect_var_imports) and
  282. (cs_imported_data in current_settings.localswitches) and
  283. not issystemunit;
  284. if not(vo_is_weak_external in gvs.varoptions) then
  285. reference_reset_symbol(tvref,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,sizeof(pint),[])
  286. else
  287. reference_reset_symbol(tvref,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,sizeof(pint),[]);
  288. { Enable size optimization with -Os or PIC code is generated and PIC uses GOT }
  289. size_opt:=(cs_opt_size in current_settings.optimizerswitches)
  290. or ((cs_create_pic in current_settings.moduleswitches) and (tf_pic_uses_got in target_info.flags));
  291. hreg_tv_rec:=NR_INVALID;
  292. if size_opt then
  293. begin
  294. { Load a pointer to the thread var record into a register. }
  295. { This register will be used in both multithreaded and non-multithreaded cases. }
  296. hreg_tv_rec:=hlcg.getaddressregister(current_asmdata.CurrAsmList,fieldptrdef);
  297. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,tvref,hreg_tv_rec);
  298. end;
  299. paraloc1.init;
  300. paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
  301. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
  302. reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE',AT_DATA,indirect),0,pvd.alignment,[]);
  303. if not issystemunit then
  304. current_module.add_extern_asmsym('FPC_THREADVAR_RELOCATE',AB_EXTERNAL,AT_DATA);
  305. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,pvd,pvd,href,hregister);
  306. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,pvd,OC_EQ,0,hregister,norelocatelab);
  307. { no, call it with the index of the threadvar as parameter }
  308. href:=tvref;
  309. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
  310. tv_rec,
  311. tfieldvarsym(tv_index_field),href);
  312. if size_opt then
  313. hlcg.reference_reset_base(href,tfieldvarsym(tv_index_field).vardef,hreg_tv_rec,href.offset,href.temppos,href.alignment,[]);
  314. hlcg.a_load_ref_cgpara(current_asmdata.CurrAsmList,tfieldvarsym(tv_index_field).vardef,href,paraloc1);
  315. { Dealloc the threadvar record register before calling the helper function to allow }
  316. { the register allocator to assign non-mandatory real registers for hreg_tv_rec. }
  317. if size_opt then
  318. cg.a_reg_dealloc(current_asmdata.CurrAsmList,hreg_tv_rec);
  319. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  320. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  321. { result is the address of the threadvar }
  322. respara:=hlcg.a_call_reg(current_asmdata.CurrAsmList,tprocvardef(pvd),hregister,[@paraloc1]);
  323. paraloc1.done;
  324. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  325. { load the address of the result in hregister }
  326. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,fieldptrdef);
  327. location_reset(tmpresloc,LOC_REGISTER,def_cgsize(fieldptrdef));
  328. tmpresloc.register:=hregister;
  329. hlcg.gen_load_cgpara_loc(current_asmdata.CurrAsmList,fieldptrdef,respara,tmpresloc,true);
  330. respara.resetiftemp;
  331. hlcg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
  332. { no relocation needed, load the address of the variable only, the
  333. layout of a threadvar is:
  334. 0 - Threadvar index
  335. sizeof(pint) - Threadvar value in single threading }
  336. hlcg.a_label(current_asmdata.CurrAsmList,norelocatelab);
  337. href:=tvref;
  338. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
  339. tv_rec,
  340. tfieldvarsym(tv_non_mt_data_field),href);
  341. { load in the same "hregister" as above, so after this sequence
  342. the address of the threadvar is always in hregister }
  343. if size_opt then
  344. hlcg.reference_reset_base(href,fieldptrdef,hreg_tv_rec,href.offset,href.temppos,href.alignment,[]);
  345. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,href,hregister);
  346. hlcg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
  347. hlcg.reference_reset_base(location.reference,fieldptrdef,hregister,0,ctempposinvalid,resultdef.alignment,[]);
  348. end;
  349. end;
  350. function tcgloadnode.use_indirect_symbol(gvs:tstaticvarsym):boolean;
  351. begin
  352. { we are using a direct reference if any of the following is true:
  353. - the target does not support packages
  354. - the target does not use indirect references
  355. - the variable is declared as (weak) external
  356. - G- is set
  357. - the variable is located inside the same unit }
  358. result:=(tf_supports_packages in target_info.flags) and
  359. (target_info.system in systems_indirect_var_imports) and
  360. (gvs.varoptions*[vo_is_external,vo_is_weak_external]=[]) and
  361. (gvs.owner.symtabletype in [globalsymtable,staticsymtable]) and
  362. (cs_imported_data in current_settings.localswitches) and
  363. not sym_is_owned_by(gvs,current_module.globalsymtable) and
  364. (
  365. (current_module.globalsymtable=current_module.localsymtable) or
  366. not sym_is_owned_by(gvs,current_module.localsymtable)
  367. );
  368. end;
  369. procedure tcgloadnode.pass_generate_code;
  370. var
  371. hregister : tregister;
  372. vs : tabstractnormalvarsym;
  373. gvs : tstaticvarsym;
  374. vmtdef : tpointerdef;
  375. vmtentry: tfieldvarsym;
  376. pd : tprocdef;
  377. href : treference;
  378. newsize : tcgsize;
  379. vd : tdef;
  380. alignment: longint;
  381. indirect : boolean;
  382. name : TSymStr;
  383. begin
  384. { we don't know the size of all arrays }
  385. newsize:=def_cgsize(resultdef);
  386. { alignment is overridden per case below }
  387. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment,[]);
  388. case symtableentry.typ of
  389. absolutevarsym :
  390. begin
  391. { this is only for toasm and toaddr }
  392. case tabsolutevarsym(symtableentry).abstyp of
  393. toaddr :
  394. generate_absaddr_access(tabsolutevarsym(symtableentry));
  395. toasm :
  396. location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname,AT_DATA);
  397. else
  398. internalerror(200310283);
  399. end;
  400. end;
  401. constsym:
  402. begin
  403. if tconstsym(symtableentry).consttyp=constresourcestring then
  404. begin
  405. location_reset_ref(location,LOC_CREFERENCE,def_cgsize(cansistringtype),cansistringtype.size,[]);
  406. indirect:=(tf_supports_packages in target_info.flags) and
  407. (target_info.system in systems_indirect_var_imports) and
  408. (cs_imported_data in current_settings.localswitches) and
  409. (symtableentry.owner.moduleid<>current_module.moduleid);
  410. name:=make_mangledname('RESSTR',symtableentry.owner,symtableentry.name);
  411. location.reference.symbol:=current_asmdata.RefAsmSymbol(name,AT_DATA,indirect);
  412. if symtableentry.owner.moduleid<>current_module.moduleid then
  413. current_module.addimportedsym(symtableentry);
  414. vd:=search_system_type('TRESOURCESTRINGRECORD').typedef;
  415. hlcg.g_set_addr_nonbitpacked_field_ref(
  416. current_asmdata.CurrAsmList,
  417. trecorddef(vd),
  418. tfieldvarsym(search_struct_member(trecorddef(vd),'CURRENTVALUE')),
  419. location.reference);
  420. end
  421. else
  422. internalerror(22798);
  423. end;
  424. staticvarsym :
  425. begin
  426. gvs:=tstaticvarsym(symtableentry);
  427. if (vo_is_dll_var in gvs.varoptions) then
  428. { DLL variable }
  429. begin
  430. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  431. if not(vo_is_weak_external in gvs.varoptions) then
  432. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname,AT_DATA)
  433. else
  434. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(tstaticvarsym(symtableentry).mangledname,AT_DATA);
  435. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
  436. reference_reset_base(location.reference,hregister,0,ctempposinvalid,location.reference.alignment,[]);
  437. end
  438. { Thread variable }
  439. else if (vo_is_thread_var in gvs.varoptions) then
  440. generate_threadvar_access(gvs)
  441. { Normal (or external) variable }
  442. else
  443. begin
  444. if gvs.localloc.loc=LOC_INVALID then
  445. begin
  446. { static data is currently always volatile }
  447. if not(vo_is_weak_external in gvs.varoptions) then
  448. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,location.reference.alignment,[])
  449. else
  450. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,location.reference.alignment,[])
  451. end
  452. else
  453. location:=gvs.localloc;
  454. end;
  455. { make const a LOC_CREFERENCE }
  456. if (gvs.varspez=vs_const) and
  457. (location.loc=LOC_REFERENCE) then
  458. location.loc:=LOC_CREFERENCE;
  459. end;
  460. paravarsym,
  461. localvarsym :
  462. begin
  463. vs:=tabstractnormalvarsym(symtableentry);
  464. { Nested variable }
  465. if assigned(left) then
  466. generate_nested_access(vs)
  467. else
  468. location:=vs.localloc;
  469. { handle call by reference variables when they are not
  470. already copied to local copies. Also ignore the reference
  471. when we need to load the self pointer for objects }
  472. if is_addr_param_load then
  473. begin
  474. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  475. hregister:=location.register
  476. else
  477. begin
  478. vd:=cpointerdef.getreusable(resultdef);
  479. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vd);
  480. { we need to load only an address }
  481. location.size:=int_cgsize(vd.size);
  482. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,vd,vd,location,hregister);
  483. end;
  484. { assume packed records may always be unaligned }
  485. if not(resultdef.typ in [recorddef,objectdef]) or
  486. (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
  487. begin
  488. alignment:=min(min(min(resultdef.alignment,current_settings.alignment.localalignmax),current_settings.alignment.constalignmax),current_settings.alignment.varalignmax);
  489. location_reset_ref(location,LOC_REFERENCE,newsize,alignment,[]);
  490. end
  491. else
  492. location_reset_ref(location,LOC_REFERENCE,newsize,1,[]);
  493. hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,ctempposinvalid,location.reference.alignment,[]);
  494. end;
  495. { make const a LOC_CREFERENCE }
  496. if (vs.varspez=vs_const) and
  497. (location.loc=LOC_REFERENCE) then
  498. location.loc:=LOC_CREFERENCE;
  499. end;
  500. procsym:
  501. begin
  502. if not assigned(procdef) then
  503. internalerror(200312011);
  504. if assigned(left) and
  505. (resultdef.typ in [symconst.procdef,procvardef]) and
  506. not tabstractprocdef(resultdef).is_addressonly then
  507. begin
  508. location_reset(location,LOC_CREGISTER,int_cgsize(voidpointertype.size*2));
  509. {$if defined(CPU8BITALU) and defined(CPU16BITADDR)}
  510. { cpus with 16 bit address registers don't use registerhi here, so allocate already here a register for all purposes }
  511. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,s32inttype);
  512. {$endif defined(CPU8BITALU) and defined(CPU16BITADDR)}
  513. secondpass(left);
  514. { load class instance/classrefdef address }
  515. if left.location.loc=LOC_CONSTANT then
  516. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  517. { vd will contain the type of the self pointer (self in
  518. case of a class/classref, address of self in case of
  519. an object }
  520. vd:=nil;
  521. case left.location.loc of
  522. LOC_CREGISTER,
  523. LOC_REGISTER:
  524. begin
  525. { this is not possible for objects }
  526. if is_object(left.resultdef) then
  527. internalerror(200304234);
  528. {$if defined(CPU8BITALU) and defined(CPU16BITADDR)}
  529. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location.register,cg.GetNextReg(cg.GetNextReg(location.register)));
  530. {$else defined(CPU8BITALU) and defined(CPU16BITADDR)}
  531. location.registerhi:=left.location.register;
  532. {$endif defined(CPU8BITALU) and defined(CPU16BITADDR)}
  533. vd:=left.resultdef;
  534. end;
  535. LOC_CREFERENCE,
  536. LOC_REFERENCE:
  537. begin
  538. if is_implicit_pointer_object_type(left.resultdef) or
  539. (left.resultdef.typ=classrefdef) 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));
  630. {$endif not(defined(CPU8BITALU) and defined(CPU16BITADDR))}
  631. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,procdef,cprocvardef.getreusableprocaddr(procdef),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 : aint;
  676. r : tregister;
  677. {$if not defined(cpu64bitalu)}
  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(nf_assign_done_in_right in flags) 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. {$ifndef cpu64bitalu}
  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}
  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) then
  855. begin
  856. { assume that all float types can be handed by the
  857. fpu if one can be handled by the fpu }
  858. if not use_vectorfpu(left.resultdef) or
  859. not use_vectorfpu(right.resultdef) then
  860. hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  861. right.resultdef,left.resultdef,
  862. right.location.reference,left.location.reference)
  863. else
  864. hlcg.a_loadmm_ref_ref(current_asmdata.CurrAsmList,
  865. right.resultdef,left.resultdef,
  866. right.location.reference,left.location.reference,mms_movescalar)
  867. end
  868. else
  869. begin
  870. { TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  871. { Use unaligned copy when the offset is not aligned }
  872. len:=left.resultdef.size;
  873. { can be 0 in case of formaldef on JVM target }
  874. if len=0 then
  875. len:=sizeof(pint);
  876. { data smaller than an aint has less alignment requirements }
  877. { max(1,...) avoids div by zero in case of an empty record }
  878. alignmentrequirement:=min(max(1,len),sizeof(aint));
  879. if (right.location.reference.offset mod alignmentrequirement<>0) or
  880. (left.location.reference.offset mod alignmentrequirement<>0) or
  881. (right.resultdef.alignment<alignmentrequirement) or
  882. ((right.location.reference.alignment<>0) and
  883. (right.location.reference.alignment<alignmentrequirement)) or
  884. ((left.location.reference.alignment<>0) and
  885. (left.location.reference.alignment<alignmentrequirement)) then
  886. hlcg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference)
  887. else
  888. hlcg.g_concatcopy(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference);
  889. end;
  890. end;
  891. LOC_MMREGISTER,
  892. LOC_CMMREGISTER:
  893. begin
  894. {$if defined(x86) and not defined(llvm)}
  895. if (right.resultdef.typ=floatdef) and
  896. not use_vectorfpu(right.resultdef) then
  897. begin
  898. { perform size conversion if needed (the mm-code cannot }
  899. { convert an extended into a double/single, since sse }
  900. { doesn't support extended) }
  901. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  902. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  903. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  904. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  905. if releaseright then
  906. location_freetemp(current_asmdata.CurrAsmList,right.location);
  907. releaseright:=true;
  908. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0,[]);
  909. right.location.reference:=href;
  910. right.resultdef:=left.resultdef;
  911. end;
  912. {$endif}
  913. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  914. right.resultdef,
  915. left.resultdef,
  916. right.location.reference,
  917. left.location.register,mms_movescalar);
  918. end;
  919. LOC_SUBSETREG,
  920. LOC_CSUBSETREG:
  921. hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
  922. LOC_SUBSETREF,
  923. LOC_CSUBSETREF:
  924. {$ifndef cpu64bitalu}
  925. if right.location.size in [OS_64,OS_S64] then
  926. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  927. else
  928. {$endif not cpu64bitalu}
  929. hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
  930. else
  931. internalerror(200203284);
  932. end;
  933. end;
  934. {$ifdef SUPPORT_MMX}
  935. LOC_CMMXREGISTER,
  936. LOC_MMXREGISTER:
  937. begin
  938. if left.location.loc=LOC_CMMXREGISTER then
  939. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  940. else
  941. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  942. end;
  943. {$endif SUPPORT_MMX}
  944. LOC_MMREGISTER,
  945. LOC_CMMREGISTER:
  946. begin
  947. if (is_vector(left.resultdef)) then
  948. shuffle := nil
  949. else
  950. shuffle := mms_movescalar;
  951. case left.location.loc of
  952. LOC_CMMREGISTER,
  953. LOC_MMREGISTER:
  954. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.register, shuffle);
  955. LOC_REFERENCE,
  956. LOC_CREFERENCE:
  957. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.reference, shuffle);
  958. else
  959. internalerror(2009112601);
  960. end;
  961. end;
  962. LOC_REGISTER,
  963. LOC_CREGISTER :
  964. begin
  965. {$ifndef cpuhighleveltarget}
  966. {$ifdef cpu64bitalu}
  967. if left.location.size in [OS_128,OS_S128] then
  968. cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
  969. right.location.register128,left.location)
  970. else
  971. {$else cpu64bitalu}
  972. { also OS_F64 in case of mmreg -> intreg }
  973. if left.location.size in [OS_64,OS_S64,OS_F64] then
  974. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  975. right.location.register64,left.location)
  976. else
  977. {$endif cpu64bitalu}
  978. {$endif not cpuhighleveltarget}
  979. {$ifdef i8086}
  980. { prefer a_load_loc_ref, because it supports i8086-specific types
  981. that use registerhi (like 6-byte method pointers)
  982. (todo: maybe we should add a_load_loc_loc?) }
  983. if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  984. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.reference)
  985. else
  986. {$endif i8086}
  987. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
  988. end;
  989. LOC_FPUREGISTER,
  990. LOC_CFPUREGISTER :
  991. begin
  992. { we can't do direct moves between fpu and mm registers }
  993. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  994. begin
  995. {$if defined(x86) and not defined(llvm)}
  996. if not use_vectorfpu(right.resultdef) then
  997. begin
  998. { perform size conversion if needed (the mm-code cannot convert an }
  999. { extended into a double/single, since sse doesn't support extended) }
  1000. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  1001. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  1002. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0,[]);
  1003. right.location.reference:=href;
  1004. right.resultdef:=left.resultdef;
  1005. end;
  1006. {$endif}
  1007. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,false);
  1008. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  1009. right.resultdef,left.resultdef,
  1010. right.location.register,left.location.register,mms_movescalar);
  1011. end
  1012. else
  1013. hlcg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  1014. right.resultdef,left.resultdef,
  1015. right.location.register,left.location);
  1016. end;
  1017. LOC_SUBSETREG,
  1018. LOC_CSUBSETREG:
  1019. begin
  1020. hlcg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  1021. right.resultdef,left.resultdef,right.location.sreg,left.location);
  1022. end;
  1023. LOC_SUBSETREF,
  1024. LOC_CSUBSETREF:
  1025. begin
  1026. {$ifndef cpu64bitalu}
  1027. if right.location.size in [OS_64,OS_S64] then
  1028. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  1029. else
  1030. {$endif not cpu64bitalu}
  1031. hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  1032. right.resultdef,left.resultdef,right.location.sref,left.location);
  1033. end;
  1034. LOC_JUMP :
  1035. begin
  1036. current_asmdata.getjumplabel(hlabel);
  1037. hlcg.a_label(current_asmdata.CurrAsmList,right.location.truelabel);
  1038. if is_pasbool(left.resultdef) then
  1039. begin
  1040. {$ifndef cpu64bitalu}
  1041. if left.location.size in [OS_64,OS_S64] then
  1042. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
  1043. else
  1044. {$endif not cpu64bitalu}
  1045. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
  1046. end
  1047. else
  1048. begin
  1049. {$ifndef cpu64bitalu}
  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}
  1054. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
  1055. end;
  1056. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  1057. hlcg.a_label(current_asmdata.CurrAsmList,right.location.falselabel);
  1058. {$ifndef cpu64bitalu}
  1059. if left.location.size in [OS_64,OS_S64] then
  1060. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
  1061. else
  1062. {$endif not cpu64bitalu}
  1063. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
  1064. hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
  1065. end;
  1066. {$ifdef cpuflags}
  1067. LOC_FLAGS :
  1068. begin
  1069. if is_pasbool(left.resultdef) then
  1070. begin
  1071. case left.location.loc of
  1072. LOC_REGISTER,LOC_CREGISTER:
  1073. {$ifndef cpu64bitalu}
  1074. if left.location.size in [OS_S64,OS_64] then
  1075. begin
  1076. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
  1077. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1078. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
  1079. end
  1080. else
  1081. {$endif not cpu64bitalu}
  1082. begin
  1083. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  1084. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1085. end;
  1086. LOC_REFERENCE:
  1087. { i8086 and i386 have hacks in their code generators so that they can
  1088. deal with 64 bit locations in this parcticular case }
  1089. {$if not defined(cpu64bitalu) and not defined(x86)}
  1090. if left.location.size in [OS_S64,OS_64] then
  1091. begin
  1092. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1093. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1094. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1095. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1096. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1097. cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
  1098. end
  1099. else
  1100. {$endif not cpu64bitalu}
  1101. begin
  1102. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  1103. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1104. end;
  1105. LOC_CSUBSETREG,LOC_SUBSETREG,LOC_SUBSETREF:
  1106. begin
  1107. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1108. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1109. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1110. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1111. end;
  1112. else
  1113. internalerror(200203273);
  1114. end;
  1115. end
  1116. else
  1117. begin
  1118. {$ifndef cpu64bitalu}
  1119. if left.location.size in [OS_S64,OS_64] then
  1120. begin
  1121. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1122. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1123. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1124. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1125. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1126. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
  1127. r64,r64);
  1128. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
  1129. end
  1130. else
  1131. {$endif not cpu64bitalu}
  1132. begin
  1133. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1134. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1135. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1136. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  1137. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1138. end
  1139. end;
  1140. end;
  1141. {$endif cpuflags}
  1142. end;
  1143. end;
  1144. if releaseright then
  1145. location_freetemp(current_asmdata.CurrAsmList,right.location);
  1146. end;
  1147. {*****************************************************************************
  1148. SecondArrayConstruct
  1149. *****************************************************************************}
  1150. const
  1151. vtInteger = 0;
  1152. vtBoolean = 1;
  1153. vtChar = 2;
  1154. vtExtended = 3;
  1155. vtString = 4;
  1156. vtPointer = 5;
  1157. vtPChar = 6;
  1158. vtObject = 7;
  1159. vtClass = 8;
  1160. vtWideChar = 9;
  1161. vtPWideChar = 10;
  1162. vtAnsiString32 = 11;
  1163. vtCurrency = 12;
  1164. vtVariant = 13;
  1165. vtInterface = 14;
  1166. vtWideString = 15;
  1167. vtInt64 = 16;
  1168. vtQWord = 17;
  1169. vtUnicodeString = 18;
  1170. vtAnsiString16 = 19;
  1171. vtAnsiString64 = 20;
  1172. procedure tcgarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  1173. begin
  1174. { do nothing by default }
  1175. end;
  1176. procedure tcgarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  1177. begin
  1178. ref.alignment:=newalignment(ref.alignment,elesize);
  1179. inc(ref.offset,elesize);
  1180. end;
  1181. procedure tcgarrayconstructornode.pass_generate_code;
  1182. var
  1183. hp : tarrayconstructornode;
  1184. href,
  1185. fref : treference;
  1186. lt : tdef;
  1187. paraloc : tcgparalocation;
  1188. varvtypefield,
  1189. varfield : tfieldvarsym;
  1190. vtype : longint;
  1191. eledef: tdef;
  1192. elesize : longint;
  1193. tmpreg : tregister;
  1194. vaddr : boolean;
  1195. freetemp,
  1196. dovariant: boolean;
  1197. begin
  1198. if is_packed_array(resultdef) then
  1199. internalerror(200608042);
  1200. dovariant:=
  1201. ((nf_forcevaria in flags) or is_variant_array(resultdef)) and
  1202. not(target_info.system in systems_managed_vm);
  1203. eledef:=tarraydef(resultdef).elementdef;
  1204. elesize:=eledef.size;
  1205. if dovariant then
  1206. varvtypefield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VTYPE'))
  1207. else
  1208. varvtypefield:=nil;
  1209. { alignment is filled in by tg.gethltemp below }
  1210. location_reset_ref(location,LOC_CREFERENCE,OS_NO,0,[]);
  1211. fillchar(paraloc,sizeof(paraloc),0);
  1212. { Allocate always a temp, also if no elements are required, to
  1213. be sure that location is valid (PFV) }
  1214. { on the JVM platform, an array can have 0 elements; since the length
  1215. of the array is part of the array itself, make sure we allocate one
  1216. of the proper length to avoid getting unexpected results later --
  1217. allocating a temp of size 0 also forces it to be size 4 on regular
  1218. targets }
  1219. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  1220. href:=location.reference;
  1221. makearrayref(href,eledef);
  1222. { Process nodes in array constructor }
  1223. hp:=self;
  1224. while assigned(hp) do
  1225. begin
  1226. if assigned(hp.left) then
  1227. begin
  1228. freetemp:=true;
  1229. secondpass(hp.left);
  1230. if (hp.left.location.loc=LOC_JUMP)<>
  1231. (hp.left.expectloc=LOC_JUMP) then
  1232. internalerror(2007103101);
  1233. { Move flags and jump in register }
  1234. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  1235. hlcg.location_force_reg(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef,hp.left.resultdef,false);
  1236. if dovariant then
  1237. begin
  1238. { find the correct vtype value }
  1239. vtype:=$ff;
  1240. varfield:=nil;
  1241. vaddr:=false;
  1242. lt:=hp.left.resultdef;
  1243. case lt.typ of
  1244. enumdef,
  1245. orddef :
  1246. begin
  1247. if is_64bit(lt) then
  1248. begin
  1249. case torddef(lt).ordtype of
  1250. scurrency:
  1251. begin
  1252. vtype:=vtCurrency;
  1253. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1254. end;
  1255. s64bit:
  1256. begin
  1257. vtype:=vtInt64;
  1258. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINT64'));
  1259. end;
  1260. u64bit:
  1261. begin
  1262. vtype:=vtQWord;
  1263. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VQWORD'));
  1264. end;
  1265. end;
  1266. freetemp:=false;
  1267. vaddr:=true;
  1268. end
  1269. else if (lt.typ=enumdef) or
  1270. is_integer(lt) then
  1271. begin
  1272. vtype:=vtInteger;
  1273. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1274. end
  1275. else
  1276. if is_boolean(lt) then
  1277. begin
  1278. vtype:=vtBoolean;
  1279. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1280. end
  1281. else
  1282. if (lt.typ=orddef) then
  1283. begin
  1284. case torddef(lt).ordtype of
  1285. uchar:
  1286. begin
  1287. vtype:=vtChar;
  1288. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1289. end;
  1290. uwidechar:
  1291. begin
  1292. vtype:=vtWideChar;
  1293. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1294. end;
  1295. end;
  1296. end;
  1297. end;
  1298. floatdef :
  1299. begin
  1300. if is_currency(lt) then
  1301. begin
  1302. vtype:=vtCurrency;
  1303. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1304. end
  1305. else
  1306. begin
  1307. vtype:=vtExtended;
  1308. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VEXTENDED'));
  1309. end;
  1310. freetemp:=false;
  1311. vaddr:=true;
  1312. end;
  1313. procvardef,
  1314. pointerdef :
  1315. begin
  1316. if is_pchar(lt) then
  1317. begin
  1318. vtype:=vtPChar;
  1319. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPCHAR'));
  1320. end
  1321. else if is_pwidechar(lt) then
  1322. begin
  1323. vtype:=vtPWideChar;
  1324. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPWIDECHAR'));
  1325. end
  1326. else
  1327. begin
  1328. vtype:=vtPointer;
  1329. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPOINTER'));
  1330. end;
  1331. end;
  1332. variantdef :
  1333. begin
  1334. vtype:=vtVariant;
  1335. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VVARIANT'));
  1336. vaddr:=true;
  1337. freetemp:=false;
  1338. end;
  1339. classrefdef :
  1340. begin
  1341. vtype:=vtClass;
  1342. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCLASS'));
  1343. end;
  1344. objectdef :
  1345. if is_interface(lt) then
  1346. begin
  1347. vtype:=vtInterface;
  1348. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTERFACE'));
  1349. end
  1350. { vtObject really means a class based on TObject }
  1351. else if is_class(lt) then
  1352. begin
  1353. vtype:=vtObject;
  1354. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VOBJECT'));
  1355. end
  1356. else
  1357. internalerror(200505171);
  1358. stringdef :
  1359. begin
  1360. if is_shortstring(lt) then
  1361. begin
  1362. vtype:=vtString;
  1363. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VSTRING'));
  1364. vaddr:=true;
  1365. freetemp:=false;
  1366. end
  1367. else
  1368. if is_ansistring(lt) then
  1369. begin
  1370. vtype:=vtAnsiString;
  1371. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VANSISTRING'));
  1372. freetemp:=false;
  1373. end
  1374. else
  1375. if is_widestring(lt) then
  1376. begin
  1377. vtype:=vtWideString;
  1378. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VWIDESTRING'));
  1379. freetemp:=false;
  1380. end
  1381. else
  1382. if is_unicodestring(lt) then
  1383. begin
  1384. vtype:=vtUnicodeString;
  1385. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VUNICODESTRING'));
  1386. freetemp:=false;
  1387. end;
  1388. end;
  1389. end;
  1390. if vtype=$ff then
  1391. internalerror(14357);
  1392. if not assigned(varfield) then
  1393. internalerror(2015102901);
  1394. { write changing field update href to the next element }
  1395. fref:=href;
  1396. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varfield,fref);
  1397. if vaddr then
  1398. begin
  1399. hlcg.location_force_mem(current_asmdata.CurrAsmList,hp.left.location,lt);
  1400. tmpreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt));
  1401. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.resultdef,cpointerdef.getreusable(lt),hp.left.location.reference,tmpreg);
  1402. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt),varfield.vardef,tmpreg,fref);
  1403. end
  1404. else
  1405. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.resultdef,varfield.vardef,hp.left.location,fref);
  1406. { update href to the vtype field and write it }
  1407. fref:=href;
  1408. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varvtypefield,fref);
  1409. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,varvtypefield.vardef,vtype,fref);
  1410. { goto next array element }
  1411. advancearrayoffset(href,elesize);
  1412. end
  1413. else
  1414. { normal array constructor of the same type }
  1415. begin
  1416. if is_managed_type(resultdef) then
  1417. freetemp:=false;
  1418. case hp.left.location.loc of
  1419. LOC_MMREGISTER,
  1420. LOC_CMMREGISTER:
  1421. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,
  1422. hp.left.location.register,href,mms_movescalar);
  1423. LOC_FPUREGISTER,
  1424. LOC_CFPUREGISTER :
  1425. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,hp.left.location.register,href);
  1426. LOC_REFERENCE,
  1427. LOC_CREFERENCE :
  1428. begin
  1429. if is_shortstring(hp.left.resultdef) then
  1430. hlcg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1431. Tstringdef(hp.left.resultdef))
  1432. else
  1433. hlcg.g_concatcopy(current_asmdata.CurrAsmList,eledef,hp.left.location.reference,href);
  1434. end;
  1435. else
  1436. begin
  1437. {$ifndef cpuhighleveltarget}
  1438. {$ifdef cpu64bitalu}
  1439. if hp.left.location.size in [OS_128,OS_S128] then
  1440. cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1441. else
  1442. {$else cpu64bitalu}
  1443. if hp.left.location.size in [OS_64,OS_S64] then
  1444. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1445. else
  1446. {$endif cpu64bitalu}
  1447. {$endif not cpuhighleveltarget}
  1448. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
  1449. end;
  1450. end;
  1451. advancearrayoffset(href,elesize);
  1452. end;
  1453. if freetemp then
  1454. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1455. end;
  1456. { load next entry }
  1457. hp:=tarrayconstructornode(hp.right);
  1458. end;
  1459. end;
  1460. {*****************************************************************************
  1461. SecondRTTI
  1462. *****************************************************************************}
  1463. procedure tcgrttinode.pass_generate_code;
  1464. var
  1465. indirect : boolean;
  1466. begin
  1467. indirect := (tf_supports_packages in target_info.flags) and
  1468. (target_info.system in systems_indirect_var_imports) and
  1469. (cs_imported_data in current_settings.localswitches) and
  1470. (rttidef.owner.moduleid<>current_module.moduleid);
  1471. location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint),[]);
  1472. case rttidatatype of
  1473. rdt_normal:
  1474. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype,indirect);
  1475. rdt_ord2str:
  1476. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype,indirect);
  1477. rdt_str2ord:
  1478. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype,indirect);
  1479. end;
  1480. end;
  1481. begin
  1482. cloadnode:=tcgloadnode;
  1483. cassignmentnode:=tcgassignmentnode;
  1484. carrayconstructornode:=tcgarrayconstructornode;
  1485. crttinode:=tcgrttinode;
  1486. end.