ncgld.pas 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  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,symsym,
  24. aasmdata,
  25. node,nld,cgutils;
  26. type
  27. tcgloadnode = class(tloadnode)
  28. protected
  29. procedure generate_nested_access(vs: tsym);virtual;
  30. procedure generate_absaddr_access(vs: tabsolutevarsym); virtual;
  31. procedure generate_threadvar_access(gvs: tstaticvarsym); virtual;
  32. function use_indirect_symbol(gvs: tstaticvarsym): boolean;
  33. public
  34. procedure pass_generate_code;override;
  35. procedure changereflocation(const ref: treference);
  36. end;
  37. tcgassignmentnode = class(tassignmentnode)
  38. protected
  39. function maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;virtual;
  40. public
  41. procedure pass_generate_code;override;
  42. end;
  43. tcgarrayconstructornode = class(tarrayconstructornode)
  44. protected
  45. procedure makearrayref(var ref: treference; eledef: tdef);virtual;
  46. procedure advancearrayoffset(var ref: treference; elesize: asizeint);virtual;
  47. public
  48. procedure pass_generate_code;override;
  49. end;
  50. tcgrttinode = class(trttinode)
  51. procedure pass_generate_code;override;
  52. end;
  53. implementation
  54. uses
  55. cutils,
  56. systems,
  57. verbose,globals,constexp,fmodule,
  58. nutils,
  59. symtable,symconst,symdef,defutil,paramgr,ncon,nbas,ncgrtti,
  60. aasmbase,
  61. cgbase,pass_2,
  62. procinfo,
  63. cpubase,parabase,
  64. tgobj,
  65. cgobj,hlcgobj,
  66. ncgbas,ncgflw,
  67. wpobase;
  68. {*****************************************************************************
  69. SSA (for memory temps) support
  70. *****************************************************************************}
  71. type
  72. preplacerefrec = ^treplacerefrec;
  73. treplacerefrec = record
  74. old, new: preference;
  75. ressym: tsym;
  76. end;
  77. function doreplaceref(var n: tnode; para: pointer): foreachnoderesult;
  78. var
  79. rr: preplacerefrec absolute para;
  80. begin
  81. result := fen_false;
  82. case n.nodetype of
  83. loadn:
  84. begin
  85. { regular variable }
  86. if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
  87. not assigned(tloadnode(n).left) and
  88. { not function result, or no exit in function }
  89. (((tloadnode(n).symtableentry <> rr^.ressym) and
  90. not(vo_is_funcret in tabstractvarsym(tloadnode(n).symtableentry).varoptions)) or
  91. not(fc_exit in flowcontrol)) and
  92. { stored in memory... }
  93. (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_REFERENCE]) and
  94. { ... at the place we are looking for }
  95. references_equal(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.reference,rr^.old^) and
  96. { its address cannot have escaped the current routine }
  97. not(tabstractvarsym(tloadnode(n).symtableentry).addr_taken) then
  98. begin
  99. { relocate variable }
  100. tcgloadnode(n).changereflocation(rr^.new^);
  101. result := fen_norecurse_true;
  102. end;
  103. end;
  104. temprefn:
  105. begin
  106. if (ti_valid in ttemprefnode(n).tempflags) and
  107. { memory temp... }
  108. (ttemprefnode(n).tempinfo^.location.loc in [LOC_REFERENCE]) and
  109. { ... at the place we are looking for }
  110. references_equal(ttemprefnode(n).tempinfo^.location.reference,rr^.old^) and
  111. { its address cannot have escaped the current routine }
  112. not(ti_addr_taken in ttemprefnode(n).tempflags) then
  113. begin
  114. { relocate the temp }
  115. tcgtemprefnode(n).changelocation(rr^.new^);
  116. result := fen_norecurse_true;
  117. end;
  118. end;
  119. { Subscriptn must be rejected, otherwise we may replace an
  120. an entire record with a temp for its first field, mantis #13948)
  121. Exception: the field's size is the same as the entire record
  122. The same goes for array indexing
  123. }
  124. subscriptn,
  125. vecn:
  126. if not(tunarynode(n).left.resultdef.typ in [recorddef,objectdef,arraydef,stringdef]) or
  127. { make sure we don't try to call resultdef.size for types that
  128. don't have a compile-time size such as open arrays }
  129. is_special_array(tunarynode(n).left.resultdef) or
  130. (tunarynode(n).left.resultdef.size<>tunarynode(n).resultdef.size) then
  131. result := fen_norecurse_false;
  132. { optimize the searching a bit }
  133. derefn,addrn,
  134. calln,inlinen,casen,
  135. addn,subn,muln,
  136. andn,orn,xorn,
  137. ltn,lten,gtn,gten,equaln,unequaln,
  138. slashn,divn,shrn,shln,notn,
  139. inn,
  140. asn,isn:
  141. result := fen_norecurse_false;
  142. end;
  143. end;
  144. function tcgassignmentnode.maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;
  145. var
  146. rr: treplacerefrec;
  147. begin
  148. result := false;
  149. { only do for -O2 or higher (breaks debugging since }
  150. { variables move to different memory locations) }
  151. if not(cs_opt_level2 in current_settings.optimizerswitches) or
  152. { must be a copy to a memory location ... }
  153. (n.location.loc <> LOC_REFERENCE) or
  154. { not inside a control flow statement and no goto's in sight }
  155. ([fc_inflowcontrol,fc_gotolabel] * flowcontrol <> []) or
  156. { not for refcounted types, because those locations are }
  157. { still used later on in initialisation/finalisation code }
  158. is_managed_type(n.resultdef) or
  159. { source and destination are temps (= not global variables) }
  160. not tg.istemp(n.location.reference) or
  161. not tg.istemp(newref) or
  162. { and both point to the start of a temp, and the source is a }
  163. { non-persistent temp (otherwise we need some kind of copy- }
  164. { on-write support in case later on both are still used) }
  165. (tg.gettypeoftemp(newref) <> tt_normal) or
  166. not (tg.gettypeoftemp(n.location.reference) in [tt_normal,tt_persistent]) or
  167. { and both have the same size }
  168. (tg.sizeoftemp(current_asmdata.CurrAsmList,newref) <> tg.sizeoftemp(current_asmdata.CurrAsmList,n.location.reference)) then
  169. exit;
  170. { find the source of the old reference (loadnode or tempnode) }
  171. { and replace it with the new reference }
  172. rr.old := @n.location.reference;
  173. rr.new := @newref;
  174. rr.ressym := nil;
  175. if assigned(current_procinfo.procdef.funcretsym) and
  176. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
  177. if (current_procinfo.procdef.proctypeoption=potype_constructor) then
  178. rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
  179. else
  180. rr.ressym:=current_procinfo.procdef.funcretsym;
  181. { if source not found, don't do anything }
  182. if not foreachnodestatic(n,@doreplaceref,@rr) then
  183. exit;
  184. n.location.reference := newref;
  185. result:=true;
  186. end;
  187. {*****************************************************************************
  188. SecondLoad
  189. *****************************************************************************}
  190. procedure tcgloadnode.changereflocation(const ref: treference);
  191. var
  192. oldtemptype: ttemptype;
  193. begin
  194. if (location.loc<>LOC_REFERENCE) then
  195. internalerror(2007020812);
  196. if not tg.istemp(location.reference) then
  197. internalerror(2007020813);
  198. oldtemptype:=tg.gettypeoftemp(location.reference);
  199. if (oldtemptype = tt_persistent) then
  200. tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,tt_normal);
  201. tg.ungettemp(current_asmdata.CurrAsmList,location.reference);
  202. location.reference:=ref;
  203. tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,oldtemptype);
  204. tabstractnormalvarsym(symtableentry).localloc:=location;
  205. end;
  206. procedure tcgloadnode.generate_nested_access(vs: tsym);
  207. var
  208. { paramter declared as tsym to reduce interface unit dependencies }
  209. lvs: tabstractnormalvarsym absolute vs;
  210. begin
  211. secondpass(left);
  212. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  213. internalerror(200309286);
  214. if lvs.localloc.loc<>LOC_REFERENCE then
  215. internalerror(200409241);
  216. hlcg.reference_reset_base(location.reference,left.resultdef,left.location.register,lvs.localloc.reference.offset,lvs.localloc.reference.alignment,lvs.localloc.reference.volatility);
  217. end;
  218. procedure tcgloadnode.generate_absaddr_access(vs: tabsolutevarsym);
  219. begin
  220. location.reference.offset:=asizeint(vs.addroffset);
  221. location.reference.volatility:=[vol_read,vol_write];
  222. end;
  223. procedure tcgloadnode.generate_threadvar_access(gvs: tstaticvarsym);
  224. var
  225. respara,
  226. paraloc1 : tcgpara;
  227. fieldptrdef,
  228. pvd : tdef;
  229. endrelocatelab,
  230. norelocatelab : tasmlabel;
  231. tvref,
  232. href : treference;
  233. hregister, hreg_tv_rec : tregister;
  234. tv_rec : trecorddef;
  235. tv_index_field,
  236. tv_non_mt_data_field: tsym;
  237. tmpresloc: tlocation;
  238. issystemunit,
  239. indirect : boolean;
  240. size_opt : boolean;
  241. begin
  242. if (tf_section_threadvars in target_info.flags) then
  243. begin
  244. if gvs.localloc.loc=LOC_INVALID then
  245. if not(vo_is_weak_external in gvs.varoptions) then
  246. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,location.reference.alignment,[])
  247. else
  248. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,location.reference.alignment,[])
  249. else
  250. location:=gvs.localloc;
  251. end
  252. else
  253. begin
  254. {
  255. Thread var loading is optimized to first check if
  256. a relocate function is available. When the function
  257. is available it is called to retrieve the address.
  258. Otherwise the address is loaded with the symbol
  259. }
  260. tv_rec:=get_threadvar_record(resultdef,tv_index_field,tv_non_mt_data_field);
  261. fieldptrdef:=cpointerdef.getreusable(resultdef);
  262. current_asmdata.getjumplabel(norelocatelab);
  263. current_asmdata.getjumplabel(endrelocatelab);
  264. { make sure hregister can't allocate the register necessary for the parameter }
  265. pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
  266. if pvd.typ<>procvardef then
  267. internalerror(2012120901);
  268. { FPC_THREADVAR_RELOCATE is nil? }
  269. issystemunit:=not current_module.is_unit or
  270. (
  271. assigned(current_module.globalsymtable) and
  272. (current_module.globalsymtable=systemunit)
  273. ) or
  274. (
  275. not assigned(current_module.globalsymtable) and
  276. (current_module.localsymtable=systemunit)
  277. );
  278. indirect:=(tf_supports_packages in target_info.flags) and
  279. (target_info.system in systems_indirect_var_imports) and
  280. (cs_imported_data in current_settings.localswitches) and
  281. not issystemunit;
  282. if not(vo_is_weak_external in gvs.varoptions) then
  283. reference_reset_symbol(tvref,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,sizeof(pint),[])
  284. else
  285. reference_reset_symbol(tvref,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,sizeof(pint),[]);
  286. { Enable size optimization with -Os or PIC code is generated and PIC uses GOT }
  287. size_opt:=(cs_opt_size in current_settings.optimizerswitches)
  288. or ((cs_create_pic in current_settings.moduleswitches) and (tf_pic_uses_got in target_info.flags));
  289. hreg_tv_rec:=NR_INVALID;
  290. if size_opt then
  291. begin
  292. { Load a pointer to the thread var record into a register. }
  293. { This register will be used in both multithreaded and non-multithreaded cases. }
  294. hreg_tv_rec:=hlcg.getaddressregister(current_asmdata.CurrAsmList,fieldptrdef);
  295. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,tvref,hreg_tv_rec);
  296. end;
  297. paraloc1.init;
  298. paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
  299. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
  300. reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE',AT_DATA,indirect),0,pvd.alignment,[]);
  301. if not issystemunit then
  302. current_module.add_extern_asmsym('FPC_THREADVAR_RELOCATE',AB_EXTERNAL,AT_DATA);
  303. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,pvd,pvd,href,hregister);
  304. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,pvd,OC_EQ,0,hregister,norelocatelab);
  305. { no, call it with the index of the threadvar as parameter }
  306. href:=tvref;
  307. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
  308. tv_rec,
  309. tfieldvarsym(tv_index_field),href);
  310. if size_opt then
  311. hlcg.reference_reset_base(href,tfieldvarsym(tv_index_field).vardef,hreg_tv_rec,href.offset,href.alignment,[]);
  312. hlcg.a_load_ref_cgpara(current_asmdata.CurrAsmList,tfieldvarsym(tv_index_field).vardef,href,paraloc1);
  313. { Dealloc the threadvar record register before calling the helper function to allow }
  314. { the register allocator to assign non-mandatory real registers for hreg_tv_rec. }
  315. if size_opt then
  316. cg.a_reg_dealloc(current_asmdata.CurrAsmList,hreg_tv_rec);
  317. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  318. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  319. { result is the address of the threadvar }
  320. respara:=hlcg.a_call_reg(current_asmdata.CurrAsmList,tprocvardef(pvd),hregister,[@paraloc1]);
  321. paraloc1.done;
  322. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  323. { load the address of the result in hregister }
  324. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,fieldptrdef);
  325. location_reset(tmpresloc,LOC_REGISTER,def_cgsize(fieldptrdef));
  326. tmpresloc.register:=hregister;
  327. hlcg.gen_load_cgpara_loc(current_asmdata.CurrAsmList,fieldptrdef,respara,tmpresloc,true);
  328. respara.resetiftemp;
  329. hlcg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
  330. { no relocation needed, load the address of the variable only, the
  331. layout of a threadvar is:
  332. 0 - Threadvar index
  333. sizeof(pint) - Threadvar value in single threading }
  334. hlcg.a_label(current_asmdata.CurrAsmList,norelocatelab);
  335. href:=tvref;
  336. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
  337. tv_rec,
  338. tfieldvarsym(tv_non_mt_data_field),href);
  339. { load in the same "hregister" as above, so after this sequence
  340. the address of the threadvar is always in hregister }
  341. if size_opt then
  342. hlcg.reference_reset_base(href,fieldptrdef,hreg_tv_rec,href.offset,href.alignment,[]);
  343. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,href,hregister);
  344. hlcg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
  345. hlcg.reference_reset_base(location.reference,fieldptrdef,hregister,0,location.reference.alignment,[]);
  346. end;
  347. end;
  348. function tcgloadnode.use_indirect_symbol(gvs:tstaticvarsym):boolean;
  349. begin
  350. { we are using a direct reference if any of the following is true:
  351. - the target does not support packages
  352. - the target does not use indirect references
  353. - the variable is declared as (weak) external
  354. - G- is set
  355. - the variable is located inside the same unit }
  356. result:=(tf_supports_packages in target_info.flags) and
  357. (target_info.system in systems_indirect_var_imports) and
  358. (gvs.varoptions*[vo_is_external,vo_is_weak_external]=[]) and
  359. (gvs.owner.symtabletype in [globalsymtable,staticsymtable]) and
  360. (cs_imported_data in current_settings.localswitches) and
  361. not sym_is_owned_by(gvs,current_module.globalsymtable) and
  362. (
  363. (current_module.globalsymtable=current_module.localsymtable) or
  364. not sym_is_owned_by(gvs,current_module.localsymtable)
  365. );
  366. end;
  367. procedure tcgloadnode.pass_generate_code;
  368. var
  369. hregister : tregister;
  370. vs : tabstractnormalvarsym;
  371. gvs : tstaticvarsym;
  372. vmtdef : tpointerdef;
  373. vmtentry: tfieldvarsym;
  374. pd : tprocdef;
  375. href : treference;
  376. newsize : tcgsize;
  377. vd : tdef;
  378. indirect : boolean;
  379. name : TSymStr;
  380. begin
  381. { we don't know the size of all arrays }
  382. newsize:=def_cgsize(resultdef);
  383. { alignment is overridden per case below }
  384. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment,[]);
  385. case symtableentry.typ of
  386. absolutevarsym :
  387. begin
  388. { this is only for toasm and toaddr }
  389. case tabsolutevarsym(symtableentry).abstyp of
  390. toaddr :
  391. generate_absaddr_access(tabsolutevarsym(symtableentry));
  392. toasm :
  393. location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname,AT_DATA);
  394. else
  395. internalerror(200310283);
  396. end;
  397. end;
  398. constsym:
  399. begin
  400. if tconstsym(symtableentry).consttyp=constresourcestring then
  401. begin
  402. location_reset_ref(location,LOC_CREFERENCE,def_cgsize(cansistringtype),cansistringtype.size,[]);
  403. indirect:=(tf_supports_packages in target_info.flags) and
  404. (target_info.system in systems_indirect_var_imports) and
  405. (cs_imported_data in current_settings.localswitches) and
  406. (symtableentry.owner.moduleid<>current_module.moduleid);
  407. name:=make_mangledname('RESSTR',symtableentry.owner,symtableentry.name);
  408. location.reference.symbol:=current_asmdata.RefAsmSymbol(name,AT_DATA,indirect);
  409. if symtableentry.owner.moduleid<>current_module.moduleid then
  410. current_module.addimportedsym(symtableentry);
  411. vd:=search_system_type('TRESOURCESTRINGRECORD').typedef;
  412. hlcg.g_set_addr_nonbitpacked_field_ref(
  413. current_asmdata.CurrAsmList,
  414. trecorddef(vd),
  415. tfieldvarsym(search_struct_member(trecorddef(vd),'CURRENTVALUE')),
  416. location.reference);
  417. end
  418. else
  419. internalerror(22798);
  420. end;
  421. staticvarsym :
  422. begin
  423. gvs:=tstaticvarsym(symtableentry);
  424. if (vo_is_dll_var in gvs.varoptions) then
  425. { DLL variable }
  426. begin
  427. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  428. if not(vo_is_weak_external in gvs.varoptions) then
  429. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname,AT_DATA)
  430. else
  431. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(tstaticvarsym(symtableentry).mangledname,AT_DATA);
  432. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
  433. reference_reset_base(location.reference,hregister,0,location.reference.alignment,[]);
  434. end
  435. { Thread variable }
  436. else if (vo_is_thread_var in gvs.varoptions) then
  437. generate_threadvar_access(gvs)
  438. { Normal (or external) variable }
  439. else
  440. begin
  441. if gvs.localloc.loc=LOC_INVALID then
  442. begin
  443. { static data is currently always volatile }
  444. if not(vo_is_weak_external in gvs.varoptions) then
  445. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA,use_indirect_symbol(gvs)),0,location.reference.alignment,[])
  446. else
  447. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,location.reference.alignment,[])
  448. end
  449. else
  450. location:=gvs.localloc;
  451. end;
  452. { make const a LOC_CREFERENCE }
  453. if (gvs.varspez=vs_const) and
  454. (location.loc=LOC_REFERENCE) then
  455. location.loc:=LOC_CREFERENCE;
  456. end;
  457. paravarsym,
  458. localvarsym :
  459. begin
  460. vs:=tabstractnormalvarsym(symtableentry);
  461. { Nested variable }
  462. if assigned(left) then
  463. generate_nested_access(vs)
  464. else
  465. location:=vs.localloc;
  466. { handle call by reference variables when they are not
  467. already copied to local copies. Also ignore the reference
  468. when we need to load the self pointer for objects }
  469. if is_addr_param_load then
  470. begin
  471. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  472. hregister:=location.register
  473. else
  474. begin
  475. vd:=cpointerdef.getreusable(resultdef);
  476. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vd);
  477. { we need to load only an address }
  478. location.size:=int_cgsize(vd.size);
  479. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,vd,vd,location,hregister);
  480. end;
  481. { assume packed records may always be unaligned }
  482. if not(resultdef.typ in [recorddef,objectdef]) or
  483. (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
  484. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment,[])
  485. else
  486. location_reset_ref(location,LOC_REFERENCE,newsize,1,[]);
  487. hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,location.reference.alignment,[]);
  488. end;
  489. { make const a LOC_CREFERENCE }
  490. if (vs.varspez=vs_const) and
  491. (location.loc=LOC_REFERENCE) then
  492. location.loc:=LOC_CREFERENCE;
  493. end;
  494. procsym:
  495. begin
  496. if not assigned(procdef) then
  497. internalerror(200312011);
  498. if assigned(left) and
  499. (resultdef.typ in [symconst.procdef,procvardef]) and
  500. not tabstractprocdef(resultdef).is_addressonly then
  501. begin
  502. location_reset(location,LOC_CREGISTER,int_cgsize(voidpointertype.size*2));
  503. secondpass(left);
  504. { load class instance/classrefdef address }
  505. if left.location.loc=LOC_CONSTANT then
  506. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  507. { vd will contain the type of the self pointer (self in
  508. case of a class/classref, address of self in case of
  509. an object }
  510. vd:=nil;
  511. case left.location.loc of
  512. LOC_CREGISTER,
  513. LOC_REGISTER:
  514. begin
  515. { this is not possible for objects }
  516. if is_object(left.resultdef) then
  517. internalerror(200304234);
  518. location.registerhi:=left.location.register;
  519. vd:=left.resultdef;
  520. end;
  521. LOC_CREFERENCE,
  522. LOC_REFERENCE:
  523. begin
  524. if is_implicit_pointer_object_type(left.resultdef) or
  525. (left.resultdef.typ=classrefdef) then
  526. begin
  527. vd:=left.resultdef;
  528. location.registerhi:=hlcg.getaddressregister(current_asmdata.CurrAsmList,left.resultdef);
  529. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location.reference,location.registerhi)
  530. end
  531. else
  532. begin
  533. vd:=cpointerdef.getreusable(left.resultdef);
  534. location.registerhi:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vd);
  535. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,vd,left.location.reference,location.registerhi);
  536. end;
  537. location_freetemp(current_asmdata.CurrAsmList,left.location);
  538. end;
  539. else
  540. internalerror(200610311);
  541. end;
  542. { virtual method ? }
  543. if (po_virtualmethod in procdef.procoptions) and
  544. not(loadnf_inherited in loadnodeflags) and
  545. not is_objectpascal_helper(procdef.struct) then
  546. begin
  547. if (not assigned(current_procinfo) or
  548. wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
  549. tobjectdef(procdef.struct).register_vmt_call(procdef.extnumber);
  550. {$ifdef vtentry}
  551. if not is_interface(procdef.struct) then
  552. begin
  553. inc(current_asmdata.NextVTEntryNr);
  554. current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+procdef._class.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0,voidpointerdef));
  555. end;
  556. {$endif vtentry}
  557. if (left.resultdef.typ=objectdef) and
  558. assigned(tobjectdef(left.resultdef).vmt_field) then
  559. begin
  560. { vmt pointer is a pointer to the vmt record }
  561. hlcg.reference_reset_base(href,vd,location.registerhi,0,vd.alignment,[]);
  562. vmtdef:=cpointerdef.getreusable(tobjectdef(left.resultdef).vmt_def);
  563. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,tobjectdef(left.resultdef),tfieldvarsym(tobjectdef(left.resultdef).vmt_field),href);
  564. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtdef);
  565. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,tfieldvarsym(tobjectdef(left.resultdef).vmt_field).vardef,vmtdef,href,hregister);
  566. end
  567. else if left.resultdef.typ=classrefdef then
  568. begin
  569. { classrefdef is a pointer to the vmt already }
  570. hregister:=location.registerhi;
  571. vmtdef:=cpointerdef.getreusable(tobjectdef(tclassrefdef(left.resultdef).pointeddef).vmt_def);
  572. hlcg.g_ptrtypecast_reg(current_asmdata.CurrAsmList,left.resultdef,vmtdef,hregister);
  573. end
  574. else if is_any_interface_kind(left.resultdef) then
  575. begin
  576. { an interface is a pointer to a pointer to a vmt }
  577. hlcg.reference_reset_base(href,vd,location.registerhi,0,vd.alignment,[]);
  578. vmtdef:=cpointerdef.getreusable(tobjectdef(left.resultdef).vmt_def);
  579. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtdef);
  580. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,vmtdef,vmtdef,href,hregister);
  581. end
  582. else
  583. internalerror(2015112501);
  584. { load method address }
  585. vmtentry:=tabstractrecordsymtable(trecorddef(vmtdef.pointeddef).symtable).findfieldbyoffset(
  586. tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber));
  587. hlcg.reference_reset_base(href,vmtdef,hregister,0,vmtdef.alignment,[]);
  588. location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtentry.vardef);
  589. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,tabstractrecorddef(vmtdef.pointeddef),vmtentry,href);
  590. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,vmtentry.vardef,vmtentry.vardef,href,location.register);
  591. end
  592. else
  593. begin
  594. { load address of the function }
  595. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION),0,procdef.address_type.alignment,[]);
  596. location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef));
  597. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,procdef,cprocvardef.getreusableprocaddr(procdef),href,location.register);
  598. end;
  599. { to get methodpointers stored correctly, code and self register must be swapped on
  600. big endian targets }
  601. if target_info.endian=endian_big then
  602. begin
  603. hregister:=location.register;
  604. location.register:=location.registerhi;
  605. location.registerhi:=hregister;
  606. end;
  607. end
  608. else
  609. begin
  610. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  611. { def_cgsize does not work for tprocdef, so we use pd.address_type }
  612. location.size:=def_cgsize(pd.address_type);
  613. if not(po_weakexternal in pd.procoptions) then
  614. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION)
  615. else
  616. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname,AT_FUNCTION);
  617. end;
  618. end;
  619. labelsym :
  620. if assigned(tlabelsym(symtableentry).asmblocklabel) then
  621. location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
  622. else
  623. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  624. else internalerror(200510032);
  625. end;
  626. end;
  627. {*****************************************************************************
  628. SecondAssignment
  629. *****************************************************************************}
  630. procedure tcgassignmentnode.pass_generate_code;
  631. var
  632. shuffle : pmmshuffle;
  633. hlabel : tasmlabel;
  634. href : treference;
  635. releaseright : boolean;
  636. alignmentrequirement,
  637. len : aint;
  638. r : tregister;
  639. {$if not defined(cpu64bitalu)}
  640. r64 : tregister64;
  641. {$endif}
  642. oldflowcontrol : tflowcontrol;
  643. begin
  644. { previously, managed types were handled in firstpass
  645. newer FPCs however can identify situations when
  646. assignments of managed types require no special code and the
  647. value could be just copied so this could should be able also to handle
  648. managed types without any special "managing code"}
  649. location_reset(location,LOC_VOID,OS_NO);
  650. {
  651. in most cases we can process first the right node which contains
  652. the most complex code. Exceptions for this are:
  653. - result is in flags, loading left will then destroy the flags
  654. - result is a jump, loading left must be already done before the jump is made
  655. - result need reference count, when left points to a value used in
  656. right then decreasing the refcnt on left can possibly release
  657. the memory before right increased the refcnt, result is that an
  658. empty value is assigned
  659. But not when the result is in the flags, then
  660. loading the left node afterwards can destroy the flags.
  661. }
  662. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  663. (node_complexity(right)>node_complexity(left)) then
  664. begin
  665. secondpass(right);
  666. if codegenerror then
  667. exit;
  668. secondpass(left);
  669. if codegenerror then
  670. exit;
  671. end
  672. else
  673. begin
  674. { calculate left sides }
  675. secondpass(left);
  676. if codegenerror then
  677. exit;
  678. { tell the SSA/SSL code that the left side was handled first so
  679. ni SSL is done
  680. }
  681. oldflowcontrol:=flowcontrol;
  682. include(flowcontrol,fc_lefthandled);
  683. secondpass(right);
  684. flowcontrol:=oldflowcontrol;
  685. if codegenerror then
  686. exit;
  687. end;
  688. releaseright:=
  689. (left.nodetype<>temprefn) or
  690. not(ti_const in ttemprefnode(left).tempflags);
  691. { shortstring assignments are handled separately }
  692. if is_shortstring(left.resultdef) then
  693. begin
  694. {
  695. we can get here only in the following situations
  696. for the right node:
  697. - empty constant string
  698. - char
  699. }
  700. { The addn is replaced by a blockn or calln that already returns
  701. a shortstring }
  702. if is_shortstring(right.resultdef) and
  703. (right.nodetype in [blockn,calln]) then
  704. begin
  705. { verify that we indeed have nothing to do }
  706. if not(nf_assign_done_in_right in flags) then
  707. internalerror(2015042201);
  708. end
  709. { empty constant string }
  710. else if (right.nodetype=stringconstn) and
  711. (tstringconstnode(right).len=0) then
  712. begin
  713. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),tpointerdef(charpointertype),left.location.reference);
  714. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,cansichartype,0,left.location.reference);
  715. end
  716. { char loading }
  717. else if is_char(right.resultdef) then
  718. begin
  719. if right.nodetype=ordconstn then
  720. begin
  721. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),cpointerdef.getreusable(u16inttype),left.location.reference);
  722. if (target_info.endian = endian_little) then
  723. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,(tordconstnode(right).value.svalue shl 8) or 1,
  724. setalignment(left.location.reference,1))
  725. else
  726. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,tordconstnode(right).value.svalue or (1 shl 8),
  727. setalignment(left.location.reference,1));
  728. end
  729. else
  730. begin
  731. href:=left.location.reference;
  732. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),tpointerdef(charpointertype),href);
  733. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,cansichartype,1,href);
  734. inc(href.offset,1);
  735. href.alignment:=1;
  736. case right.location.loc of
  737. LOC_REGISTER,
  738. LOC_CREGISTER :
  739. begin
  740. {$ifndef cpuhighleveltarget}
  741. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  742. {$else not cpuhighleveltarget}
  743. r:=hlcg.getintregister(current_asmdata.CurrAsmList,u8inttype);
  744. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,cansichartype,u8inttype,right.location.register,r);
  745. {$endif cpuhighleveltarget}
  746. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,r,href);
  747. end;
  748. LOC_REFERENCE,
  749. LOC_CREFERENCE :
  750. hlcg.a_load_ref_ref(current_asmdata.CurrAsmList,cansichartype,cansichartype,right.location.reference,href);
  751. else
  752. internalerror(200205111);
  753. end;
  754. end;
  755. end
  756. else
  757. internalerror(2002042410);
  758. end
  759. { try to reuse memory locations instead of copying }
  760. { copy to a memory location ... }
  761. else if (right.location.loc = LOC_REFERENCE) and
  762. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  763. begin
  764. { if it worked, we're done }
  765. end
  766. else
  767. begin
  768. { SSA support }
  769. hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
  770. hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,right,true);
  771. case right.location.loc of
  772. LOC_CONSTANT :
  773. begin
  774. {$ifndef cpu64bitalu}
  775. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  776. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  777. else
  778. {$endif not cpu64bitalu}
  779. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
  780. end;
  781. LOC_REFERENCE,
  782. LOC_CREFERENCE :
  783. begin
  784. case left.location.loc of
  785. LOC_REGISTER,
  786. LOC_CREGISTER :
  787. begin
  788. {$ifndef cpuhighleveltarget}
  789. {$ifdef cpu64bitalu}
  790. if left.location.size in [OS_128,OS_S128] then
  791. cg128.a_load128_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register128)
  792. else
  793. {$else cpu64bitalu}
  794. if left.location.size in [OS_64,OS_S64] then
  795. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  796. else
  797. {$endif cpu64bitalu}
  798. {$endif not cpuhighleveltarget}
  799. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
  800. end;
  801. LOC_FPUREGISTER,
  802. LOC_CFPUREGISTER :
  803. begin
  804. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  805. right.resultdef,left.resultdef,
  806. right.location.reference,
  807. left.location.register);
  808. end;
  809. LOC_REFERENCE,
  810. LOC_CREFERENCE :
  811. begin
  812. if (left.resultdef.typ=floatdef) and
  813. (right.resultdef.typ=floatdef) and
  814. (left.location.size<>right.location.size) then
  815. begin
  816. { assume that all float types can be handed by the
  817. fpu if one can be handled by the fpu }
  818. if not use_vectorfpu(left.resultdef) or
  819. not use_vectorfpu(right.resultdef) then
  820. hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  821. right.resultdef,left.resultdef,
  822. right.location.reference,left.location.reference)
  823. else
  824. hlcg.a_loadmm_ref_ref(current_asmdata.CurrAsmList,
  825. right.resultdef,left.resultdef,
  826. right.location.reference,left.location.reference,mms_movescalar)
  827. end
  828. else
  829. begin
  830. { TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  831. { Use unaligned copy when the offset is not aligned }
  832. len:=left.resultdef.size;
  833. { can be 0 in case of formaldef on JVM target }
  834. if len=0 then
  835. len:=sizeof(pint);
  836. { data smaller than an aint has less alignment requirements }
  837. { max(1,...) avoids div by zero in case of an empty record }
  838. alignmentrequirement:=min(max(1,len),sizeof(aint));
  839. if (right.location.reference.offset mod alignmentrequirement<>0) or
  840. (left.location.reference.offset mod alignmentrequirement<>0) or
  841. (right.resultdef.alignment<alignmentrequirement) or
  842. ((right.location.reference.alignment<>0) and
  843. (right.location.reference.alignment<alignmentrequirement)) or
  844. ((left.location.reference.alignment<>0) and
  845. (left.location.reference.alignment<alignmentrequirement)) then
  846. hlcg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference)
  847. else
  848. hlcg.g_concatcopy(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference);
  849. end;
  850. end;
  851. LOC_MMREGISTER,
  852. LOC_CMMREGISTER:
  853. begin
  854. {$if defined(x86) and not defined(llvm)}
  855. if (right.resultdef.typ=floatdef) and
  856. not use_vectorfpu(right.resultdef) then
  857. begin
  858. { perform size conversion if needed (the mm-code cannot }
  859. { convert an extended into a double/single, since sse }
  860. { doesn't support extended) }
  861. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  862. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  863. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  864. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  865. if releaseright then
  866. location_freetemp(current_asmdata.CurrAsmList,right.location);
  867. releaseright:=true;
  868. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0,[]);
  869. right.location.reference:=href;
  870. right.resultdef:=left.resultdef;
  871. end;
  872. {$endif}
  873. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  874. right.resultdef,
  875. left.resultdef,
  876. right.location.reference,
  877. left.location.register,mms_movescalar);
  878. end;
  879. LOC_SUBSETREG,
  880. LOC_CSUBSETREG:
  881. hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
  882. LOC_SUBSETREF,
  883. LOC_CSUBSETREF:
  884. {$ifndef cpu64bitalu}
  885. if right.location.size in [OS_64,OS_S64] then
  886. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  887. else
  888. {$endif not cpu64bitalu}
  889. hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
  890. else
  891. internalerror(200203284);
  892. end;
  893. end;
  894. {$ifdef SUPPORT_MMX}
  895. LOC_CMMXREGISTER,
  896. LOC_MMXREGISTER:
  897. begin
  898. if left.location.loc=LOC_CMMXREGISTER then
  899. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  900. else
  901. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  902. end;
  903. {$endif SUPPORT_MMX}
  904. LOC_MMREGISTER,
  905. LOC_CMMREGISTER:
  906. begin
  907. if (is_vector(left.resultdef)) then
  908. shuffle := nil
  909. else
  910. shuffle := mms_movescalar;
  911. case left.location.loc of
  912. LOC_CMMREGISTER,
  913. LOC_MMREGISTER:
  914. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.register, shuffle);
  915. LOC_REFERENCE,
  916. LOC_CREFERENCE:
  917. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.reference, shuffle);
  918. else
  919. internalerror(2009112601);
  920. end;
  921. end;
  922. LOC_REGISTER,
  923. LOC_CREGISTER :
  924. begin
  925. {$ifndef cpuhighleveltarget}
  926. {$ifdef cpu64bitalu}
  927. if left.location.size in [OS_128,OS_S128] then
  928. cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
  929. right.location.register128,left.location)
  930. else
  931. {$else cpu64bitalu}
  932. { also OS_F64 in case of mmreg -> intreg }
  933. if left.location.size in [OS_64,OS_S64,OS_F64] then
  934. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  935. right.location.register64,left.location)
  936. else
  937. {$endif cpu64bitalu}
  938. {$endif not cpuhighleveltarget}
  939. {$ifdef i8086}
  940. { prefer a_load_loc_ref, because it supports i8086-specific types
  941. that use registerhi (like 6-byte method pointers)
  942. (todo: maybe we should add a_load_loc_loc?) }
  943. if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  944. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.reference)
  945. else
  946. {$endif i8086}
  947. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
  948. end;
  949. LOC_FPUREGISTER,
  950. LOC_CFPUREGISTER :
  951. begin
  952. { we can't do direct moves between fpu and mm registers }
  953. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  954. begin
  955. {$if defined(x86) and not defined(llvm)}
  956. if not use_vectorfpu(right.resultdef) then
  957. begin
  958. { perform size conversion if needed (the mm-code cannot convert an }
  959. { extended into a double/single, since sse doesn't support extended) }
  960. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  961. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  962. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0,[]);
  963. right.location.reference:=href;
  964. right.resultdef:=left.resultdef;
  965. end;
  966. {$endif}
  967. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,false);
  968. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  969. right.resultdef,left.resultdef,
  970. right.location.register,left.location.register,mms_movescalar);
  971. end
  972. else
  973. hlcg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  974. right.resultdef,left.resultdef,
  975. right.location.register,left.location);
  976. end;
  977. LOC_SUBSETREG,
  978. LOC_CSUBSETREG:
  979. begin
  980. hlcg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  981. right.resultdef,left.resultdef,right.location.sreg,left.location);
  982. end;
  983. LOC_SUBSETREF,
  984. LOC_CSUBSETREF:
  985. begin
  986. {$ifndef cpu64bitalu}
  987. if right.location.size in [OS_64,OS_S64] then
  988. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  989. else
  990. {$endif not cpu64bitalu}
  991. hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  992. right.resultdef,left.resultdef,right.location.sref,left.location);
  993. end;
  994. LOC_JUMP :
  995. begin
  996. current_asmdata.getjumplabel(hlabel);
  997. hlcg.a_label(current_asmdata.CurrAsmList,right.location.truelabel);
  998. if is_pasbool(left.resultdef) then
  999. begin
  1000. {$ifndef cpu64bitalu}
  1001. if left.location.size in [OS_64,OS_S64] then
  1002. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
  1003. else
  1004. {$endif not cpu64bitalu}
  1005. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
  1006. end
  1007. else
  1008. begin
  1009. {$ifndef cpu64bitalu}
  1010. if left.location.size in [OS_64,OS_S64] then
  1011. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
  1012. else
  1013. {$endif not cpu64bitalu}
  1014. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
  1015. end;
  1016. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  1017. hlcg.a_label(current_asmdata.CurrAsmList,right.location.falselabel);
  1018. {$ifndef cpu64bitalu}
  1019. if left.location.size in [OS_64,OS_S64] then
  1020. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
  1021. else
  1022. {$endif not cpu64bitalu}
  1023. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
  1024. hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
  1025. end;
  1026. {$ifdef cpuflags}
  1027. LOC_FLAGS :
  1028. begin
  1029. if is_pasbool(left.resultdef) then
  1030. begin
  1031. case left.location.loc of
  1032. LOC_REGISTER,LOC_CREGISTER:
  1033. {$ifndef cpu64bitalu}
  1034. if left.location.size in [OS_S64,OS_64] then
  1035. begin
  1036. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
  1037. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1038. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
  1039. end
  1040. else
  1041. {$endif not cpu64bitalu}
  1042. begin
  1043. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  1044. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1045. end;
  1046. LOC_REFERENCE:
  1047. { i8086 and i386 have hacks in their code generators so that they can
  1048. deal with 64 bit locations in this parcticular case }
  1049. {$if not defined(cpu64bitalu) and not defined(x86)}
  1050. if left.location.size in [OS_S64,OS_64] then
  1051. begin
  1052. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1053. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1054. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1055. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1056. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1057. cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
  1058. end
  1059. else
  1060. {$endif not cpu64bitalu}
  1061. begin
  1062. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  1063. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1064. end;
  1065. LOC_SUBSETREG,LOC_SUBSETREF:
  1066. begin
  1067. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1068. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1069. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1070. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1071. end;
  1072. else
  1073. internalerror(200203273);
  1074. end;
  1075. end
  1076. else
  1077. begin
  1078. {$ifndef cpu64bitalu}
  1079. if left.location.size in [OS_S64,OS_64] then
  1080. begin
  1081. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1082. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1083. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1084. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1085. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1086. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
  1087. r64,r64);
  1088. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
  1089. end
  1090. else
  1091. {$endif not cpu64bitalu}
  1092. begin
  1093. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1094. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1095. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1096. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  1097. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1098. end
  1099. end;
  1100. end;
  1101. {$endif cpuflags}
  1102. end;
  1103. end;
  1104. if releaseright then
  1105. location_freetemp(current_asmdata.CurrAsmList,right.location);
  1106. end;
  1107. {*****************************************************************************
  1108. SecondArrayConstruct
  1109. *****************************************************************************}
  1110. const
  1111. vtInteger = 0;
  1112. vtBoolean = 1;
  1113. vtChar = 2;
  1114. vtExtended = 3;
  1115. vtString = 4;
  1116. vtPointer = 5;
  1117. vtPChar = 6;
  1118. vtObject = 7;
  1119. vtClass = 8;
  1120. vtWideChar = 9;
  1121. vtPWideChar = 10;
  1122. vtAnsiString32 = 11;
  1123. vtCurrency = 12;
  1124. vtVariant = 13;
  1125. vtInterface = 14;
  1126. vtWideString = 15;
  1127. vtInt64 = 16;
  1128. vtQWord = 17;
  1129. vtUnicodeString = 18;
  1130. vtAnsiString16 = 19;
  1131. vtAnsiString64 = 20;
  1132. procedure tcgarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  1133. begin
  1134. { do nothing by default }
  1135. end;
  1136. procedure tcgarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  1137. begin
  1138. ref.alignment:=newalignment(ref.alignment,elesize);
  1139. inc(ref.offset,elesize);
  1140. end;
  1141. procedure tcgarrayconstructornode.pass_generate_code;
  1142. var
  1143. hp : tarrayconstructornode;
  1144. href,
  1145. fref : treference;
  1146. lt : tdef;
  1147. paraloc : tcgparalocation;
  1148. varvtypefield,
  1149. varfield : tfieldvarsym;
  1150. vtype : longint;
  1151. eledef: tdef;
  1152. elesize : longint;
  1153. tmpreg : tregister;
  1154. vaddr : boolean;
  1155. freetemp,
  1156. dovariant: boolean;
  1157. begin
  1158. if is_packed_array(resultdef) then
  1159. internalerror(200608042);
  1160. dovariant:=
  1161. ((nf_forcevaria in flags) or is_variant_array(resultdef)) and
  1162. not(target_info.system in systems_managed_vm);
  1163. eledef:=tarraydef(resultdef).elementdef;
  1164. elesize:=eledef.size;
  1165. if dovariant then
  1166. varvtypefield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VTYPE'))
  1167. else
  1168. varvtypefield:=nil;
  1169. { alignment is filled in by tg.gethltemp below }
  1170. location_reset_ref(location,LOC_CREFERENCE,OS_NO,0,[]);
  1171. fillchar(paraloc,sizeof(paraloc),0);
  1172. { Allocate always a temp, also if no elements are required, to
  1173. be sure that location is valid (PFV) }
  1174. { on the JVM platform, an array can have 0 elements; since the length
  1175. of the array is part of the array itself, make sure we allocate one
  1176. of the proper length to avoid getting unexpected results later --
  1177. allocating a temp of size 0 also forces it to be size 4 on regular
  1178. targets }
  1179. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  1180. href:=location.reference;
  1181. makearrayref(href,eledef);
  1182. { Process nodes in array constructor }
  1183. hp:=self;
  1184. while assigned(hp) do
  1185. begin
  1186. if assigned(hp.left) then
  1187. begin
  1188. freetemp:=true;
  1189. secondpass(hp.left);
  1190. if (hp.left.location.loc=LOC_JUMP)<>
  1191. (hp.left.expectloc=LOC_JUMP) then
  1192. internalerror(2007103101);
  1193. { Move flags and jump in register }
  1194. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  1195. hlcg.location_force_reg(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef,hp.left.resultdef,false);
  1196. if dovariant then
  1197. begin
  1198. { find the correct vtype value }
  1199. vtype:=$ff;
  1200. varfield:=nil;
  1201. vaddr:=false;
  1202. lt:=hp.left.resultdef;
  1203. case lt.typ of
  1204. enumdef,
  1205. orddef :
  1206. begin
  1207. if is_64bit(lt) then
  1208. begin
  1209. case torddef(lt).ordtype of
  1210. scurrency:
  1211. begin
  1212. vtype:=vtCurrency;
  1213. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1214. end;
  1215. s64bit:
  1216. begin
  1217. vtype:=vtInt64;
  1218. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINT64'));
  1219. end;
  1220. u64bit:
  1221. begin
  1222. vtype:=vtQWord;
  1223. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VQWORD'));
  1224. end;
  1225. end;
  1226. freetemp:=false;
  1227. vaddr:=true;
  1228. end
  1229. else if (lt.typ=enumdef) or
  1230. is_integer(lt) then
  1231. begin
  1232. vtype:=vtInteger;
  1233. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1234. end
  1235. else
  1236. if is_boolean(lt) then
  1237. begin
  1238. vtype:=vtBoolean;
  1239. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1240. end
  1241. else
  1242. if (lt.typ=orddef) then
  1243. begin
  1244. case torddef(lt).ordtype of
  1245. uchar:
  1246. begin
  1247. vtype:=vtChar;
  1248. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1249. end;
  1250. uwidechar:
  1251. begin
  1252. vtype:=vtWideChar;
  1253. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1254. end;
  1255. end;
  1256. end;
  1257. end;
  1258. floatdef :
  1259. begin
  1260. if is_currency(lt) then
  1261. begin
  1262. vtype:=vtCurrency;
  1263. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1264. end
  1265. else
  1266. begin
  1267. vtype:=vtExtended;
  1268. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VEXTENDED'));
  1269. end;
  1270. freetemp:=false;
  1271. vaddr:=true;
  1272. end;
  1273. procvardef,
  1274. pointerdef :
  1275. begin
  1276. if is_pchar(lt) then
  1277. begin
  1278. vtype:=vtPChar;
  1279. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPCHAR'));
  1280. end
  1281. else if is_pwidechar(lt) then
  1282. begin
  1283. vtype:=vtPWideChar;
  1284. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPWIDECHAR'));
  1285. end
  1286. else
  1287. begin
  1288. vtype:=vtPointer;
  1289. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPOINTER'));
  1290. end;
  1291. end;
  1292. variantdef :
  1293. begin
  1294. vtype:=vtVariant;
  1295. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VVARIANT'));
  1296. vaddr:=true;
  1297. freetemp:=false;
  1298. end;
  1299. classrefdef :
  1300. begin
  1301. vtype:=vtClass;
  1302. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCLASS'));
  1303. end;
  1304. objectdef :
  1305. if is_interface(lt) then
  1306. begin
  1307. vtype:=vtInterface;
  1308. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTERFACE'));
  1309. end
  1310. { vtObject really means a class based on TObject }
  1311. else if is_class(lt) then
  1312. begin
  1313. vtype:=vtObject;
  1314. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VOBJECT'));
  1315. end
  1316. else
  1317. internalerror(200505171);
  1318. stringdef :
  1319. begin
  1320. if is_shortstring(lt) then
  1321. begin
  1322. vtype:=vtString;
  1323. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VSTRING'));
  1324. vaddr:=true;
  1325. freetemp:=false;
  1326. end
  1327. else
  1328. if is_ansistring(lt) then
  1329. begin
  1330. vtype:=vtAnsiString;
  1331. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VANSISTRING'));
  1332. freetemp:=false;
  1333. end
  1334. else
  1335. if is_widestring(lt) then
  1336. begin
  1337. vtype:=vtWideString;
  1338. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VWIDESTRING'));
  1339. freetemp:=false;
  1340. end
  1341. else
  1342. if is_unicodestring(lt) then
  1343. begin
  1344. vtype:=vtUnicodeString;
  1345. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VUNICODESTRING'));
  1346. freetemp:=false;
  1347. end;
  1348. end;
  1349. end;
  1350. if vtype=$ff then
  1351. internalerror(14357);
  1352. if not assigned(varfield) then
  1353. internalerror(2015102901);
  1354. { write changing field update href to the next element }
  1355. fref:=href;
  1356. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varfield,fref);
  1357. if vaddr then
  1358. begin
  1359. hlcg.location_force_mem(current_asmdata.CurrAsmList,hp.left.location,lt);
  1360. tmpreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt));
  1361. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.resultdef,cpointerdef.getreusable(lt),hp.left.location.reference,tmpreg);
  1362. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt),varfield.vardef,tmpreg,fref);
  1363. end
  1364. else
  1365. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.resultdef,varfield.vardef,hp.left.location,fref);
  1366. { update href to the vtype field and write it }
  1367. fref:=href;
  1368. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varvtypefield,fref);
  1369. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,varvtypefield.vardef,vtype,fref);
  1370. { goto next array element }
  1371. advancearrayoffset(href,elesize);
  1372. end
  1373. else
  1374. { normal array constructor of the same type }
  1375. begin
  1376. if is_managed_type(resultdef) then
  1377. freetemp:=false;
  1378. case hp.left.location.loc of
  1379. LOC_MMREGISTER,
  1380. LOC_CMMREGISTER:
  1381. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,
  1382. hp.left.location.register,href,mms_movescalar);
  1383. LOC_FPUREGISTER,
  1384. LOC_CFPUREGISTER :
  1385. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,hp.left.location.register,href);
  1386. LOC_REFERENCE,
  1387. LOC_CREFERENCE :
  1388. begin
  1389. if is_shortstring(hp.left.resultdef) then
  1390. hlcg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1391. Tstringdef(hp.left.resultdef))
  1392. else
  1393. hlcg.g_concatcopy(current_asmdata.CurrAsmList,eledef,hp.left.location.reference,href);
  1394. end;
  1395. else
  1396. begin
  1397. {$ifndef cpuhighleveltarget}
  1398. {$ifdef cpu64bitalu}
  1399. if hp.left.location.size in [OS_128,OS_S128] then
  1400. cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1401. else
  1402. {$else cpu64bitalu}
  1403. if hp.left.location.size in [OS_64,OS_S64] then
  1404. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1405. else
  1406. {$endif cpu64bitalu}
  1407. {$endif not cpuhighleveltarget}
  1408. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
  1409. end;
  1410. end;
  1411. advancearrayoffset(href,elesize);
  1412. end;
  1413. if freetemp then
  1414. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1415. end;
  1416. { load next entry }
  1417. hp:=tarrayconstructornode(hp.right);
  1418. end;
  1419. end;
  1420. {*****************************************************************************
  1421. SecondRTTI
  1422. *****************************************************************************}
  1423. procedure tcgrttinode.pass_generate_code;
  1424. var
  1425. indirect : boolean;
  1426. begin
  1427. indirect := (tf_supports_packages in target_info.flags) and
  1428. (target_info.system in systems_indirect_var_imports) and
  1429. (cs_imported_data in current_settings.localswitches) and
  1430. (rttidef.owner.moduleid<>current_module.moduleid);
  1431. location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint),[]);
  1432. case rttidatatype of
  1433. rdt_normal:
  1434. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype,indirect);
  1435. rdt_ord2str:
  1436. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype,indirect);
  1437. rdt_str2ord:
  1438. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype,indirect);
  1439. end;
  1440. end;
  1441. begin
  1442. cloadnode:=tcgloadnode;
  1443. cassignmentnode:=tcgassignmentnode;
  1444. carrayconstructornode:=tcgarrayconstructornode;
  1445. crttinode:=tcgrttinode;
  1446. end.