ncgld.pas 72 KB

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