ncgld.pas 69 KB

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