ncgld.pas 74 KB

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