ncgld.pas 53 KB

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