ncgld.pas 58 KB

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