ncgld.pas 75 KB

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