ncgld.pas 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297
  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. {$if not defined(jvm) or not defined(nounsupported)}
  379. { Nested variable }
  380. if assigned(left) then
  381. begin
  382. secondpass(left);
  383. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  384. internalerror(200309286);
  385. if vs.localloc.loc<>LOC_REFERENCE then
  386. internalerror(200409241);
  387. reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset,vs.localloc.reference.alignment);
  388. end
  389. else
  390. {$endif}
  391. location:=vs.localloc;
  392. { handle call by reference variables when they are not
  393. already copied to local copies. Also ignore the reference
  394. when we need to load the self pointer for objects }
  395. if is_addr_param_load then
  396. begin
  397. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  398. hregister:=location.register
  399. else
  400. begin
  401. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  402. { we need to load only an address }
  403. location.size:=OS_ADDR;
  404. cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
  405. end;
  406. { assume packed records may always be unaligned }
  407. if not(resultdef.typ in [recorddef,objectdef]) or
  408. (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
  409. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment)
  410. else
  411. location_reset_ref(location,LOC_REFERENCE,newsize,1);
  412. location.reference.base:=hregister;
  413. end;
  414. { make const a LOC_CREFERENCE }
  415. if (vs.varspez=vs_const) and
  416. (location.loc=LOC_REFERENCE) then
  417. location.loc:=LOC_CREFERENCE;
  418. end;
  419. procsym:
  420. begin
  421. {$ifdef jvm}
  422. {$ifndef nounsupported}
  423. location_reset(location,LOC_REGISTER,OS_ADDR);
  424. location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
  425. hlcg.a_load_const_reg(current_asmdata.CurrAsmList,java_jlobject,0,location.register);
  426. exit;
  427. {$endif nounsupported}
  428. {$endif jvm}
  429. if not assigned(procdef) then
  430. internalerror(200312011);
  431. if assigned(left) then
  432. begin
  433. {$if sizeof(pint) = 4}
  434. location_reset_ref(location,LOC_CREFERENCE,OS_64,sizeof(pint));
  435. {$else} {$if sizeof(pint) = 8}
  436. location_reset_ref(location,LOC_CREFERENCE,OS_128,sizeof(pint));
  437. {$else}
  438. internalerror(20020520);
  439. {$endif} {$endif}
  440. tg.gethltemp(current_asmdata.CurrAsmList,methodpointertype,methodpointertype.size,tt_normal,location.reference);
  441. secondpass(left);
  442. { load class instance/classrefdef address }
  443. if left.location.loc=LOC_CONSTANT then
  444. location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
  445. case left.location.loc of
  446. LOC_CREGISTER,
  447. LOC_REGISTER:
  448. begin
  449. { this is not possible for objects }
  450. if is_object(left.resultdef) then
  451. internalerror(200304234);
  452. hregister:=left.location.register;
  453. end;
  454. LOC_CREFERENCE,
  455. LOC_REFERENCE:
  456. begin
  457. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  458. if not is_object(left.resultdef) then
  459. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  460. else
  461. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
  462. location_freetemp(current_asmdata.CurrAsmList,left.location);
  463. end;
  464. else
  465. internalerror(200610311);
  466. end;
  467. { store the class instance or classredef address }
  468. href:=location.reference;
  469. inc(href.offset,sizeof(pint));
  470. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
  471. { virtual method ? }
  472. if (po_virtualmethod in procdef.procoptions) and
  473. not(nf_inherited in flags) and
  474. not is_objectpascal_helper(procdef.struct) then
  475. begin
  476. if (not assigned(current_procinfo) or
  477. wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
  478. tobjectdef(procdef.struct).register_vmt_call(procdef.extnumber);
  479. {$ifdef vtentry}
  480. if not is_interface(procdef.struct) then
  481. begin
  482. inc(current_asmdata.NextVTEntryNr);
  483. current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+procdef._class.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0));
  484. end;
  485. {$endif vtentry}
  486. { a classrefdef already points to the VMT }
  487. if (left.resultdef.typ<>classrefdef) then
  488. begin
  489. { load vmt pointer }
  490. reference_reset_base(href,hregister,tobjectdef(left.resultdef).vmt_offset,sizeof(pint));
  491. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  492. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  493. end;
  494. { load method address }
  495. reference_reset_base(href,hregister,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
  496. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  497. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  498. { ... and store it }
  499. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  500. end
  501. else
  502. begin
  503. { load address of the function }
  504. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0,sizeof(pint));
  505. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  506. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  507. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  508. end;
  509. end
  510. else
  511. begin
  512. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  513. if (po_external in pd.procoptions) then
  514. location.reference.base :=
  515. cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname,
  516. po_weakexternal in pd.procoptions);
  517. {!!!!! Be aware, work on virtual methods too }
  518. if (location.reference.base = NR_NO) then
  519. if not(po_weakexternal in pd.procoptions) then
  520. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname)
  521. else
  522. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname);
  523. end;
  524. end;
  525. labelsym :
  526. if assigned(tlabelsym(symtableentry).asmblocklabel) then
  527. location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
  528. else
  529. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  530. else internalerror(200510032);
  531. end;
  532. end;
  533. {*****************************************************************************
  534. SecondAssignment
  535. *****************************************************************************}
  536. procedure tcgassignmentnode.pass_generate_code;
  537. var
  538. otlabel,hlabel,oflabel : tasmlabel;
  539. href : treference;
  540. releaseright : boolean;
  541. alignmentrequirement,
  542. len : aint;
  543. r : tregister;
  544. oldflowcontrol : tflowcontrol;
  545. begin
  546. location_reset(location,LOC_VOID,OS_NO);
  547. otlabel:=current_procinfo.CurrTrueLabel;
  548. oflabel:=current_procinfo.CurrFalseLabel;
  549. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  550. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  551. {
  552. in most cases we can process first the right node which contains
  553. the most complex code. Exceptions for this are:
  554. - result is in flags, loading left will then destroy the flags
  555. - result is a jump, loading left must be already done before the jump is made
  556. - result need reference count, when left points to a value used in
  557. right then decreasing the refcnt on left can possibly release
  558. the memory before right increased the refcnt, result is that an
  559. empty value is assigned
  560. But not when the result is in the flags, then
  561. loading the left node afterwards can destroy the flags.
  562. }
  563. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  564. (is_managed_type(right.resultdef) or
  565. (node_complexity(right)>node_complexity(left))) then
  566. begin
  567. secondpass(right);
  568. { increment source reference counter, this is
  569. useless for constants }
  570. if is_managed_type(right.resultdef) and
  571. not is_constnode(right) then
  572. begin
  573. hlcg.location_force_mem(current_asmdata.CurrAsmList,right.location,right.resultdef);
  574. hlcg.location_get_data_ref(current_asmdata.CurrAsmList,right.resultdef,right.location,href,false,sizeof(pint));
  575. hlcg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  576. end;
  577. if codegenerror then
  578. exit;
  579. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  580. { can be false }
  581. secondpass(left);
  582. { decrement destination reference counter }
  583. if is_managed_type(left.resultdef) then
  584. begin
  585. hlcg.location_get_data_ref(current_asmdata.CurrAsmList,left.resultdef,left.location,href,false,sizeof(pint));
  586. hlcg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  587. end;
  588. if codegenerror then
  589. exit;
  590. end
  591. else
  592. begin
  593. { calculate left sides }
  594. secondpass(left);
  595. { decrement destination reference counter }
  596. if is_managed_type(left.resultdef) then
  597. begin
  598. hlcg.location_get_data_ref(current_asmdata.CurrAsmList,left.resultdef,left.location,href,false,sizeof(pint));
  599. hlcg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  600. end;
  601. if codegenerror then
  602. exit;
  603. { tell the SSA/SSL code that the left side was handled first so
  604. ni SSL is done
  605. }
  606. oldflowcontrol:=flowcontrol;
  607. include(flowcontrol,fc_lefthandled);
  608. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  609. { can be false }
  610. secondpass(right);
  611. flowcontrol:=oldflowcontrol;
  612. { increment source reference counter, this is
  613. useless for string constants}
  614. if is_managed_type(right.resultdef) and
  615. (right.nodetype<>stringconstn) then
  616. begin
  617. hlcg.location_force_mem(current_asmdata.CurrAsmList,right.location,right.resultdef);
  618. hlcg.location_get_data_ref(current_asmdata.CurrAsmList,left.resultdef,right.location,href,false,sizeof(pint));
  619. hlcg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  620. end;
  621. if codegenerror then
  622. exit;
  623. end;
  624. releaseright:=true;
  625. { shortstring assignments are handled separately }
  626. if is_shortstring(left.resultdef) then
  627. begin
  628. {
  629. we can get here only in the following situations
  630. for the right node:
  631. - empty constant string
  632. - char
  633. }
  634. { The addn is replaced by a blockn or calln that already returns
  635. a shortstring }
  636. if is_shortstring(right.resultdef) and
  637. (right.nodetype in [blockn,calln]) then
  638. begin
  639. { nothing to do }
  640. end
  641. { empty constant string }
  642. else if (right.nodetype=stringconstn) and
  643. (tstringconstnode(right).len=0) then
  644. begin
  645. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u8inttype,0,left.location.reference);
  646. end
  647. { char loading }
  648. else if is_char(right.resultdef) then
  649. begin
  650. if right.nodetype=ordconstn then
  651. begin
  652. if (target_info.endian = endian_little) then
  653. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,(tordconstnode(right).value.svalue shl 8) or 1,
  654. setalignment(left.location.reference,1))
  655. else
  656. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,tordconstnode(right).value.svalue or (1 shl 8),
  657. setalignment(left.location.reference,1));
  658. end
  659. else
  660. begin
  661. href:=left.location.reference;
  662. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u8inttype,1,href);
  663. inc(href.offset,1);
  664. case right.location.loc of
  665. LOC_REGISTER,
  666. LOC_CREGISTER :
  667. begin
  668. {$ifndef cpuhighleveltarget}
  669. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  670. {$else not cpuhighleveltarget}
  671. r:=hlcg.getintregister(current_asmdata.CurrAsmList,u8inttype);
  672. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,u8inttype,u8inttype,right.location.register,r);
  673. {$endif cpuhighleveltarget}
  674. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,r,href);
  675. end;
  676. LOC_REFERENCE,
  677. LOC_CREFERENCE :
  678. hlcg.a_load_ref_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,right.location.reference,href);
  679. else
  680. internalerror(200205111);
  681. end;
  682. end;
  683. end
  684. else
  685. internalerror(2002042410);
  686. end
  687. { try to reuse memory locations instead of copying }
  688. { copy to a memory location ... }
  689. else if (right.location.loc = LOC_REFERENCE) and
  690. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  691. begin
  692. { if it worked, we're done }
  693. end
  694. else
  695. begin
  696. { SSA support }
  697. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
  698. maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
  699. case right.location.loc of
  700. LOC_CONSTANT :
  701. begin
  702. {$ifndef cpu64bitalu}
  703. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  704. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  705. else
  706. {$endif not cpu64bitalu}
  707. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
  708. end;
  709. LOC_REFERENCE,
  710. LOC_CREFERENCE :
  711. begin
  712. case left.location.loc of
  713. LOC_REGISTER,
  714. LOC_CREGISTER :
  715. begin
  716. {$ifndef cpu64bitalu}
  717. if left.location.size in [OS_64,OS_S64] then
  718. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  719. else
  720. {$endif not cpu64bitalu}
  721. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
  722. end;
  723. LOC_FPUREGISTER,
  724. LOC_CFPUREGISTER :
  725. begin
  726. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  727. right.resultdef,left.resultdef,
  728. right.location.reference,
  729. left.location.register);
  730. end;
  731. LOC_REFERENCE,
  732. LOC_CREFERENCE :
  733. begin
  734. if (left.resultdef.typ=floatdef) and
  735. (right.resultdef.typ=floatdef) and
  736. (left.location.size<>right.location.size) then
  737. begin
  738. hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  739. right.resultdef,left.resultdef,
  740. right.location.reference,left.location.reference)
  741. end
  742. else
  743. begin
  744. { TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  745. { Use unaligned copy when the offset is not aligned }
  746. len:=left.resultdef.size;
  747. { data smaller than an aint has less alignment requirements }
  748. alignmentrequirement:=min(len,sizeof(aint));
  749. if (right.location.reference.offset mod alignmentrequirement<>0) or
  750. (left.location.reference.offset mod alignmentrequirement<>0) or
  751. (right.resultdef.alignment<alignmentrequirement) or
  752. ((right.location.reference.alignment<>0) and
  753. (right.location.reference.alignment<alignmentrequirement)) or
  754. ((left.location.reference.alignment<>0) and
  755. (left.location.reference.alignment<alignmentrequirement)) then
  756. hlcg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference)
  757. else
  758. hlcg.g_concatcopy(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference);
  759. end;
  760. end;
  761. LOC_MMREGISTER,
  762. LOC_CMMREGISTER:
  763. begin
  764. {$ifdef x86}
  765. if (right.resultdef.typ=floatdef) and
  766. not use_vectorfpu(right.resultdef) then
  767. begin
  768. { perform size conversion if needed (the mm-code cannot }
  769. { convert an extended into a double/single, since sse }
  770. { doesn't support extended) }
  771. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  772. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  773. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  774. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  775. if releaseright then
  776. location_freetemp(current_asmdata.CurrAsmList,right.location);
  777. releaseright:=true;
  778. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
  779. right.location.reference:=href;
  780. end;
  781. {$endif}
  782. cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  783. right.location.size,
  784. left.location.size,
  785. right.location.reference,
  786. left.location.register,mms_movescalar);
  787. end;
  788. LOC_SUBSETREG,
  789. LOC_CSUBSETREG:
  790. cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
  791. LOC_SUBSETREF,
  792. LOC_CSUBSETREF:
  793. {$ifndef cpu64bitalu}
  794. if right.location.size in [OS_64,OS_S64] then
  795. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  796. else
  797. {$endif not cpu64bitalu}
  798. cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
  799. else
  800. internalerror(200203284);
  801. end;
  802. end;
  803. {$ifdef SUPPORT_MMX}
  804. LOC_CMMXREGISTER,
  805. LOC_MMXREGISTER:
  806. begin
  807. if left.location.loc=LOC_CMMXREGISTER then
  808. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  809. else
  810. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  811. end;
  812. {$endif SUPPORT_MMX}
  813. LOC_MMREGISTER,
  814. LOC_CMMREGISTER:
  815. begin
  816. if left.resultdef.typ=arraydef then
  817. begin
  818. end
  819. else
  820. begin
  821. case left.location.loc of
  822. LOC_CMMREGISTER,
  823. LOC_MMREGISTER:
  824. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar);
  825. LOC_REFERENCE,
  826. LOC_CREFERENCE:
  827. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  828. else
  829. internalerror(2009112601);
  830. end;
  831. end;
  832. end;
  833. LOC_REGISTER,
  834. LOC_CREGISTER :
  835. begin
  836. {$ifndef cpu64bitalu}
  837. { also OS_F64 in case of mmreg -> intreg }
  838. if left.location.size in [OS_64,OS_S64,OS_F64] then
  839. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  840. right.location.register64,left.location)
  841. else
  842. {$endif not cpu64bitalu}
  843. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
  844. end;
  845. LOC_FPUREGISTER,
  846. LOC_CFPUREGISTER :
  847. begin
  848. { we can't do direct moves between fpu and mm registers }
  849. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  850. begin
  851. {$ifdef x86}
  852. if not use_vectorfpu(right.resultdef) then
  853. begin
  854. { perform size conversion if needed (the mm-code cannot convert an }
  855. { extended into a double/single, since sse doesn't support extended) }
  856. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef, left.resultdef.size,tt_normal,href);
  857. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  858. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
  859. right.location.reference:=href;
  860. end;
  861. {$endif}
  862. location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
  863. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  864. right.location.size,left.location.size,
  865. right.location.register,left.location.register,mms_movescalar);
  866. end
  867. else
  868. hlcg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  869. right.resultdef,left.resultdef,
  870. right.location.register,left.location);
  871. end;
  872. LOC_SUBSETREG,
  873. LOC_CSUBSETREG:
  874. begin
  875. cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  876. right.location.size,right.location.sreg,left.location);
  877. end;
  878. LOC_SUBSETREF,
  879. LOC_CSUBSETREF:
  880. begin
  881. {$ifndef cpu64bitalu}
  882. if right.location.size in [OS_64,OS_S64] then
  883. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  884. else
  885. {$endif not cpu64bitalu}
  886. cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  887. right.location.size,right.location.sref,left.location);
  888. end;
  889. LOC_JUMP :
  890. begin
  891. current_asmdata.getjumplabel(hlabel);
  892. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  893. if is_pasbool(left.resultdef) then
  894. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
  895. else
  896. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
  897. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  898. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  899. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
  900. hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
  901. end;
  902. {$ifdef cpuflags}
  903. LOC_FLAGS :
  904. begin
  905. if is_pasbool(left.resultdef) then
  906. begin
  907. case left.location.loc of
  908. LOC_REGISTER,LOC_CREGISTER:
  909. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  910. LOC_REFERENCE:
  911. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  912. LOC_SUBSETREG,LOC_SUBSETREF:
  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_load_reg_loc(current_asmdata.CurrAsmList,left.location.size,r,left.location);
  917. end;
  918. else
  919. internalerror(200203273);
  920. end;
  921. end
  922. else
  923. begin
  924. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  925. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  926. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  927. cg.a_load_reg_loc(current_asmdata.CurrAsmList,left.location.size,r,left.location);
  928. end;
  929. end;
  930. {$endif cpuflags}
  931. end;
  932. end;
  933. if releaseright then
  934. location_freetemp(current_asmdata.CurrAsmList,right.location);
  935. current_procinfo.CurrTrueLabel:=otlabel;
  936. current_procinfo.CurrFalseLabel:=oflabel;
  937. end;
  938. {*****************************************************************************
  939. SecondArrayConstruct
  940. *****************************************************************************}
  941. const
  942. vtInteger = 0;
  943. vtBoolean = 1;
  944. vtChar = 2;
  945. vtExtended = 3;
  946. vtString = 4;
  947. vtPointer = 5;
  948. vtPChar = 6;
  949. vtObject = 7;
  950. vtClass = 8;
  951. vtWideChar = 9;
  952. vtPWideChar = 10;
  953. vtAnsiString32 = 11;
  954. vtCurrency = 12;
  955. vtVariant = 13;
  956. vtInterface = 14;
  957. vtWideString = 15;
  958. vtInt64 = 16;
  959. vtQWord = 17;
  960. vtUnicodeString = 18;
  961. vtAnsiString16 = 19;
  962. vtAnsiString64 = 20;
  963. procedure tcgarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  964. begin
  965. { do nothing by default }
  966. end;
  967. procedure tcgarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  968. begin
  969. inc(ref.offset,elesize);
  970. end;
  971. procedure tcgarrayconstructornode.pass_generate_code;
  972. var
  973. hp : tarrayconstructornode;
  974. href : treference;
  975. lt : tdef;
  976. paraloc : tcgparalocation;
  977. otlabel,
  978. oflabel : tasmlabel;
  979. vtype : longint;
  980. eledef: tdef;
  981. elesize : longint;
  982. tmpreg : tregister;
  983. vaddr : boolean;
  984. freetemp,
  985. dovariant : boolean;
  986. begin
  987. if is_packed_array(resultdef) then
  988. internalerror(200608042);
  989. dovariant:=(nf_forcevaria in flags) or is_variant_array(resultdef);
  990. if dovariant then
  991. begin
  992. eledef:=search_system_type('TVARREC').typedef;
  993. elesize:=eledef.size;
  994. end
  995. else
  996. begin
  997. eledef:=tarraydef(resultdef).elementdef;
  998. elesize:=tarraydef(resultdef).elesize;
  999. end;
  1000. { alignment is filled in by tg.gethltemp below }
  1001. location_reset_ref(location,LOC_CREFERENCE,OS_NO,0);
  1002. fillchar(paraloc,sizeof(paraloc),0);
  1003. { Allocate always a temp, also if no elements are required, to
  1004. be sure that location is valid (PFV) }
  1005. if tarraydef(resultdef).highrange=-1 then
  1006. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,elesize,tt_normal,location.reference)
  1007. else
  1008. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  1009. href:=location.reference;
  1010. makearrayref(href,eledef);
  1011. { Process nodes in array constructor }
  1012. hp:=self;
  1013. while assigned(hp) do
  1014. begin
  1015. if assigned(hp.left) then
  1016. begin
  1017. freetemp:=true;
  1018. if (hp.left.expectloc=LOC_JUMP) then
  1019. begin
  1020. otlabel:=current_procinfo.CurrTrueLabel;
  1021. oflabel:=current_procinfo.CurrFalseLabel;
  1022. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  1023. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  1024. end;
  1025. secondpass(hp.left);
  1026. { Move flags and jump in register }
  1027. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  1028. hlcg.location_force_reg(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef,hp.left.resultdef,false);
  1029. if (hp.left.location.loc=LOC_JUMP) then
  1030. begin
  1031. if (hp.left.expectloc<>LOC_JUMP) then
  1032. internalerror(2007103101);
  1033. current_procinfo.CurrTrueLabel:=otlabel;
  1034. current_procinfo.CurrFalseLabel:=oflabel;
  1035. end;
  1036. if dovariant then
  1037. begin
  1038. {$if not defined(jvm) or defined(nounsupported)}
  1039. { find the correct vtype value }
  1040. vtype:=$ff;
  1041. vaddr:=false;
  1042. lt:=hp.left.resultdef;
  1043. case lt.typ of
  1044. enumdef,
  1045. orddef :
  1046. begin
  1047. if is_64bit(lt) then
  1048. begin
  1049. case torddef(lt).ordtype of
  1050. scurrency:
  1051. vtype:=vtCurrency;
  1052. s64bit:
  1053. vtype:=vtInt64;
  1054. u64bit:
  1055. vtype:=vtQWord;
  1056. end;
  1057. freetemp:=false;
  1058. vaddr:=true;
  1059. end
  1060. else if (lt.typ=enumdef) or
  1061. is_integer(lt) then
  1062. vtype:=vtInteger
  1063. else
  1064. if is_boolean(lt) then
  1065. vtype:=vtBoolean
  1066. else
  1067. if (lt.typ=orddef) then
  1068. begin
  1069. case torddef(lt).ordtype of
  1070. uchar:
  1071. vtype:=vtChar;
  1072. uwidechar:
  1073. vtype:=vtWideChar;
  1074. end;
  1075. end;
  1076. end;
  1077. floatdef :
  1078. begin
  1079. if is_currency(lt) then
  1080. vtype:=vtCurrency
  1081. else
  1082. vtype:=vtExtended;
  1083. freetemp:=false;
  1084. vaddr:=true;
  1085. end;
  1086. procvardef,
  1087. pointerdef :
  1088. begin
  1089. if is_pchar(lt) then
  1090. vtype:=vtPChar
  1091. else if is_pwidechar(lt) then
  1092. vtype:=vtPWideChar
  1093. else
  1094. vtype:=vtPointer;
  1095. end;
  1096. variantdef :
  1097. begin
  1098. vtype:=vtVariant;
  1099. vaddr:=true;
  1100. freetemp:=false;
  1101. end;
  1102. classrefdef :
  1103. vtype:=vtClass;
  1104. objectdef :
  1105. if is_interface(lt) then
  1106. vtype:=vtInterface
  1107. { vtObject really means a class based on TObject }
  1108. else if is_class(lt) then
  1109. vtype:=vtObject
  1110. else
  1111. internalerror(200505171);
  1112. stringdef :
  1113. begin
  1114. if is_shortstring(lt) then
  1115. begin
  1116. vtype:=vtString;
  1117. vaddr:=true;
  1118. freetemp:=false;
  1119. end
  1120. else
  1121. if is_ansistring(lt) then
  1122. begin
  1123. vtype:=vtAnsiString;
  1124. freetemp:=false;
  1125. end
  1126. else
  1127. if is_widestring(lt) then
  1128. begin
  1129. vtype:=vtWideString;
  1130. freetemp:=false;
  1131. end
  1132. else
  1133. if is_unicodestring(lt) then
  1134. begin
  1135. vtype:=vtUnicodeString;
  1136. freetemp:=false;
  1137. end;
  1138. end;
  1139. end;
  1140. if vtype=$ff then
  1141. internalerror(14357);
  1142. { write changing field update href to the next element }
  1143. inc(href.offset,sizeof(pint));
  1144. if vaddr then
  1145. begin
  1146. location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
  1147. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  1148. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  1149. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  1150. end
  1151. else
  1152. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
  1153. { update href to the vtype field and write it }
  1154. dec(href.offset,sizeof(pint));
  1155. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  1156. { goto next array element }
  1157. advancearrayoffset(href,sizeof(pint)*2);
  1158. {$endif not jvm or nounsupported}
  1159. end
  1160. else
  1161. { normal array constructor of the same type }
  1162. begin
  1163. if is_managed_type(resultdef) then
  1164. freetemp:=false;
  1165. case hp.left.location.loc of
  1166. LOC_MMREGISTER,
  1167. LOC_CMMREGISTER:
  1168. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
  1169. hp.left.location.register,href,mms_movescalar);
  1170. LOC_FPUREGISTER,
  1171. LOC_CFPUREGISTER :
  1172. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,hp.left.location.register,href);
  1173. LOC_REFERENCE,
  1174. LOC_CREFERENCE :
  1175. begin
  1176. if is_shortstring(hp.left.resultdef) then
  1177. hlcg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1178. Tstringdef(hp.left.resultdef))
  1179. else
  1180. hlcg.g_concatcopy(current_asmdata.CurrAsmList,eledef,hp.left.location.reference,href);
  1181. end;
  1182. else
  1183. begin
  1184. {$ifndef cpu64bitalu}
  1185. if hp.left.location.size in [OS_64,OS_S64] then
  1186. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1187. else
  1188. {$endif not cpu64bitalu}
  1189. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
  1190. end;
  1191. end;
  1192. advancearrayoffset(href,elesize);
  1193. end;
  1194. if freetemp then
  1195. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1196. end;
  1197. { load next entry }
  1198. hp:=tarrayconstructornode(hp.right);
  1199. end;
  1200. end;
  1201. {*****************************************************************************
  1202. SecondRTTI
  1203. *****************************************************************************}
  1204. procedure tcgrttinode.pass_generate_code;
  1205. begin
  1206. location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint));
  1207. case rttidatatype of
  1208. rdt_normal:
  1209. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  1210. rdt_ord2str:
  1211. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype);
  1212. rdt_str2ord:
  1213. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype);
  1214. end;
  1215. end;
  1216. begin
  1217. cloadnode:=tcgloadnode;
  1218. cassignmentnode:=tcgassignmentnode;
  1219. carrayconstructornode:=tcgarrayconstructornode;
  1220. crttinode:=tcgrttinode;
  1221. end.