ncgld.pas 67 KB

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