ncgld.pas 76 KB

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