ncgld.pas 72 KB

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