ncgld.pas 64 KB

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