ncgld.pas 73 KB

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