ncgld.pas 63 KB

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