ncgld.pas 59 KB

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