ncgld.pas 72 KB

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