ncgld.pas 60 KB

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