ncgld.pas 61 KB

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