ncgld.pas 57 KB

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