ncgld.pas 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440
  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:=aint(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. { a classrefdef already points to the VMT, and
  486. so do interfaces }
  487. if (left.resultdef.typ<>classrefdef) and
  488. not is_any_interface_kind(left.resultdef) then
  489. begin
  490. { vmt pointer is a pointer to the vmt record }
  491. hlcg.reference_reset_base(href,vd,location.registerhi,0,vd.alignment);
  492. vmtdef:=cpointerdef.getreusable(tobjectdef(left.resultdef).vmt_def);
  493. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,tobjectdef(left.resultdef),tfieldvarsym(tobjectdef(left.resultdef).vmt_field),href);
  494. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtdef);
  495. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,tfieldvarsym(tobjectdef(left.resultdef).vmt_field).vardef,vmtdef,href,hregister);
  496. end
  497. else
  498. begin
  499. hregister:=location.registerhi;
  500. if left.resultdef.typ=classrefdef then
  501. vmtdef:=cpointerdef.getreusable(tobjectdef(tclassrefdef(left.resultdef).pointeddef).vmt_def)
  502. else
  503. vmtdef:=cpointerdef.getreusable(tobjectdef(left.resultdef).vmt_def);
  504. hlcg.g_ptrtypecast_reg(current_asmdata.CurrAsmList,left.resultdef,vmtdef,hregister);
  505. end;
  506. { load method address }
  507. vmtentry:=tabstractrecordsymtable(trecorddef(vmtdef.pointeddef).symtable).findfieldbyoffset(
  508. tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber));
  509. hlcg.reference_reset_base(href,vmtdef,hregister,0,vmtdef.alignment);
  510. location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtentry.vardef);
  511. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,tabstractrecorddef(vmtdef.pointeddef),vmtentry,href);
  512. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,vmtentry.vardef,vmtentry.vardef,href,location.register);
  513. end
  514. else
  515. begin
  516. { load address of the function }
  517. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0,procdef.address_type.alignment);
  518. location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef));
  519. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,procdef,cprocvardef.getreusableprocaddr(procdef),href,location.register);
  520. end;
  521. { to get methodpointers stored correctly, code and self register must be swapped on
  522. big endian targets }
  523. if target_info.endian=endian_big then
  524. begin
  525. hregister:=location.register;
  526. location.register:=location.registerhi;
  527. location.registerhi:=hregister;
  528. end;
  529. end
  530. else
  531. begin
  532. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  533. { def_cgsize does not work for tprocdef, so we use pd.address_type }
  534. location.size:=def_cgsize(pd.address_type);
  535. if not(po_weakexternal in pd.procoptions) then
  536. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname)
  537. else
  538. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname);
  539. end;
  540. end;
  541. labelsym :
  542. if assigned(tlabelsym(symtableentry).asmblocklabel) then
  543. location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
  544. else
  545. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  546. else internalerror(200510032);
  547. end;
  548. end;
  549. {*****************************************************************************
  550. SecondAssignment
  551. *****************************************************************************}
  552. procedure tcgassignmentnode.pass_generate_code;
  553. var
  554. hlabel : tasmlabel;
  555. href : treference;
  556. releaseright : boolean;
  557. alignmentrequirement,
  558. len : aint;
  559. r : tregister;
  560. {$if not defined(cpu64bitalu)}
  561. r64 : tregister64;
  562. {$endif}
  563. oldflowcontrol : tflowcontrol;
  564. begin
  565. { previously, managed types were handled in firstpass
  566. newer FPCs however can identify situations when
  567. assignments of managed types require no special code and the
  568. value could be just copied so this could should be able also to handle
  569. managed types without any special "managing code"}
  570. location_reset(location,LOC_VOID,OS_NO);
  571. {
  572. in most cases we can process first the right node which contains
  573. the most complex code. Exceptions for this are:
  574. - result is in flags, loading left will then destroy the flags
  575. - result is a jump, loading left must be already done before the jump is made
  576. - result need reference count, when left points to a value used in
  577. right then decreasing the refcnt on left can possibly release
  578. the memory before right increased the refcnt, result is that an
  579. empty value is assigned
  580. But not when the result is in the flags, then
  581. loading the left node afterwards can destroy the flags.
  582. }
  583. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  584. (node_complexity(right)>node_complexity(left)) then
  585. begin
  586. secondpass(right);
  587. if codegenerror then
  588. exit;
  589. secondpass(left);
  590. if codegenerror then
  591. exit;
  592. end
  593. else
  594. begin
  595. { calculate left sides }
  596. secondpass(left);
  597. if codegenerror then
  598. exit;
  599. { tell the SSA/SSL code that the left side was handled first so
  600. ni SSL is done
  601. }
  602. oldflowcontrol:=flowcontrol;
  603. include(flowcontrol,fc_lefthandled);
  604. secondpass(right);
  605. flowcontrol:=oldflowcontrol;
  606. if codegenerror then
  607. exit;
  608. end;
  609. releaseright:=true;
  610. { shortstring assignments are handled separately }
  611. if is_shortstring(left.resultdef) then
  612. begin
  613. {
  614. we can get here only in the following situations
  615. for the right node:
  616. - empty constant string
  617. - char
  618. }
  619. { The addn is replaced by a blockn or calln that already returns
  620. a shortstring }
  621. if is_shortstring(right.resultdef) and
  622. (right.nodetype in [blockn,calln]) then
  623. begin
  624. { verify that we indeed have nothing to do }
  625. if not(nf_assign_done_in_right in flags) then
  626. internalerror(2015042201);
  627. end
  628. { empty constant string }
  629. else if (right.nodetype=stringconstn) and
  630. (tstringconstnode(right).len=0) then
  631. begin
  632. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),tpointerdef(charpointertype),left.location.reference);
  633. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,cansichartype,0,left.location.reference);
  634. end
  635. { char loading }
  636. else if is_char(right.resultdef) then
  637. begin
  638. if right.nodetype=ordconstn then
  639. begin
  640. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),cpointerdef.getreusable(u16inttype),left.location.reference);
  641. if (target_info.endian = endian_little) then
  642. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,(tordconstnode(right).value.svalue shl 8) or 1,
  643. setalignment(left.location.reference,1))
  644. else
  645. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,tordconstnode(right).value.svalue or (1 shl 8),
  646. setalignment(left.location.reference,1));
  647. end
  648. else
  649. begin
  650. href:=left.location.reference;
  651. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(left.resultdef),tpointerdef(charpointertype),href);
  652. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,cansichartype,1,href);
  653. inc(href.offset,1);
  654. case right.location.loc of
  655. LOC_REGISTER,
  656. LOC_CREGISTER :
  657. begin
  658. {$ifndef cpuhighleveltarget}
  659. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  660. {$else not cpuhighleveltarget}
  661. r:=hlcg.getintregister(current_asmdata.CurrAsmList,u8inttype);
  662. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,cansichartype,u8inttype,right.location.register,r);
  663. {$endif cpuhighleveltarget}
  664. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,r,href);
  665. end;
  666. LOC_REFERENCE,
  667. LOC_CREFERENCE :
  668. hlcg.a_load_ref_ref(current_asmdata.CurrAsmList,cansichartype,cansichartype,right.location.reference,href);
  669. else
  670. internalerror(200205111);
  671. end;
  672. end;
  673. end
  674. else
  675. internalerror(2002042410);
  676. end
  677. { try to reuse memory locations instead of copying }
  678. { copy to a memory location ... }
  679. else if (right.location.loc = LOC_REFERENCE) and
  680. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  681. begin
  682. { if it worked, we're done }
  683. end
  684. else
  685. begin
  686. { SSA support }
  687. hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
  688. hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,right,true);
  689. case right.location.loc of
  690. LOC_CONSTANT :
  691. begin
  692. {$ifndef cpu64bitalu}
  693. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  694. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  695. else
  696. {$endif not cpu64bitalu}
  697. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
  698. end;
  699. LOC_REFERENCE,
  700. LOC_CREFERENCE :
  701. begin
  702. case left.location.loc of
  703. LOC_REGISTER,
  704. LOC_CREGISTER :
  705. begin
  706. {$ifndef cpuhighleveltarget}
  707. {$ifdef cpu64bitalu}
  708. if left.location.size in [OS_128,OS_S128] then
  709. cg128.a_load128_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register128)
  710. else
  711. {$else cpu64bitalu}
  712. if left.location.size in [OS_64,OS_S64] then
  713. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  714. else
  715. {$endif cpu64bitalu}
  716. {$endif not cpuhighleveltarget}
  717. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
  718. end;
  719. LOC_FPUREGISTER,
  720. LOC_CFPUREGISTER :
  721. begin
  722. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  723. right.resultdef,left.resultdef,
  724. right.location.reference,
  725. left.location.register);
  726. end;
  727. LOC_REFERENCE,
  728. LOC_CREFERENCE :
  729. begin
  730. if (left.resultdef.typ=floatdef) and
  731. (right.resultdef.typ=floatdef) and
  732. (left.location.size<>right.location.size) then
  733. begin
  734. { assume that all float types can be handed by the
  735. fpu if one can be handled by the fpu }
  736. if not use_vectorfpu(left.resultdef) or
  737. not use_vectorfpu(right.resultdef) then
  738. hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  739. right.resultdef,left.resultdef,
  740. right.location.reference,left.location.reference)
  741. else
  742. hlcg.a_loadmm_ref_ref(current_asmdata.CurrAsmList,
  743. right.resultdef,left.resultdef,
  744. right.location.reference,left.location.reference,mms_movescalar)
  745. end
  746. else
  747. begin
  748. { TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  749. { Use unaligned copy when the offset is not aligned }
  750. len:=left.resultdef.size;
  751. { can be 0 in case of formaldef on JVM target }
  752. if len=0 then
  753. len:=sizeof(pint);
  754. { data smaller than an aint has less alignment requirements }
  755. { max(1,...) avoids div by zero in case of an empty record }
  756. alignmentrequirement:=min(max(1,len),sizeof(aint));
  757. if (right.location.reference.offset mod alignmentrequirement<>0) or
  758. (left.location.reference.offset mod alignmentrequirement<>0) or
  759. (right.resultdef.alignment<alignmentrequirement) or
  760. ((right.location.reference.alignment<>0) and
  761. (right.location.reference.alignment<alignmentrequirement)) or
  762. ((left.location.reference.alignment<>0) and
  763. (left.location.reference.alignment<alignmentrequirement)) then
  764. hlcg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference)
  765. else
  766. hlcg.g_concatcopy(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference);
  767. end;
  768. end;
  769. LOC_MMREGISTER,
  770. LOC_CMMREGISTER:
  771. begin
  772. {$ifdef x86}
  773. if (right.resultdef.typ=floatdef) and
  774. not use_vectorfpu(right.resultdef) then
  775. begin
  776. { perform size conversion if needed (the mm-code cannot }
  777. { convert an extended into a double/single, since sse }
  778. { doesn't support extended) }
  779. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  780. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  781. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  782. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  783. if releaseright then
  784. location_freetemp(current_asmdata.CurrAsmList,right.location);
  785. releaseright:=true;
  786. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
  787. right.location.reference:=href;
  788. right.resultdef:=left.resultdef;
  789. end;
  790. {$endif}
  791. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  792. right.resultdef,
  793. left.resultdef,
  794. right.location.reference,
  795. left.location.register,mms_movescalar);
  796. end;
  797. LOC_SUBSETREG,
  798. LOC_CSUBSETREG:
  799. hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
  800. LOC_SUBSETREF,
  801. LOC_CSUBSETREF:
  802. {$ifndef cpu64bitalu}
  803. if right.location.size in [OS_64,OS_S64] then
  804. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  805. else
  806. {$endif not cpu64bitalu}
  807. hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
  808. else
  809. internalerror(200203284);
  810. end;
  811. end;
  812. {$ifdef SUPPORT_MMX}
  813. LOC_CMMXREGISTER,
  814. LOC_MMXREGISTER:
  815. begin
  816. if left.location.loc=LOC_CMMXREGISTER then
  817. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  818. else
  819. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  820. end;
  821. {$endif SUPPORT_MMX}
  822. LOC_MMREGISTER,
  823. LOC_CMMREGISTER:
  824. begin
  825. if left.resultdef.typ=arraydef then
  826. begin
  827. end
  828. else
  829. begin
  830. case left.location.loc of
  831. LOC_CMMREGISTER,
  832. LOC_MMREGISTER:
  833. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.register,mms_movescalar);
  834. LOC_REFERENCE,
  835. LOC_CREFERENCE:
  836. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.reference,mms_movescalar);
  837. else
  838. internalerror(2009112601);
  839. end;
  840. end;
  841. end;
  842. LOC_REGISTER,
  843. LOC_CREGISTER :
  844. begin
  845. {$ifndef cpuhighleveltarget}
  846. {$ifdef cpu64bitalu}
  847. if left.location.size in [OS_128,OS_S128] then
  848. cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
  849. right.location.register128,left.location)
  850. else
  851. {$else cpu64bitalu}
  852. { also OS_F64 in case of mmreg -> intreg }
  853. if left.location.size in [OS_64,OS_S64,OS_F64] then
  854. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  855. right.location.register64,left.location)
  856. else
  857. {$endif cpu64bitalu}
  858. {$endif not cpuhighleveltarget}
  859. {$ifdef i8086}
  860. { prefer a_load_loc_ref, because it supports i8086-specific types
  861. that use registerhi (like 6-byte method pointers)
  862. (todo: maybe we should add a_load_loc_loc?) }
  863. if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  864. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.reference)
  865. else
  866. {$endif i8086}
  867. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
  868. end;
  869. LOC_FPUREGISTER,
  870. LOC_CFPUREGISTER :
  871. begin
  872. { we can't do direct moves between fpu and mm registers }
  873. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  874. begin
  875. {$ifdef x86}
  876. if not use_vectorfpu(right.resultdef) then
  877. begin
  878. { perform size conversion if needed (the mm-code cannot convert an }
  879. { extended into a double/single, since sse doesn't support extended) }
  880. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  881. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  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.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,false);
  888. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  889. right.resultdef,left.resultdef,
  890. right.location.register,left.location.register,mms_movescalar);
  891. end
  892. else
  893. hlcg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  894. right.resultdef,left.resultdef,
  895. right.location.register,left.location);
  896. end;
  897. LOC_SUBSETREG,
  898. LOC_CSUBSETREG:
  899. begin
  900. hlcg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  901. right.resultdef,left.resultdef,right.location.sreg,left.location);
  902. end;
  903. LOC_SUBSETREF,
  904. LOC_CSUBSETREF:
  905. begin
  906. {$ifndef cpu64bitalu}
  907. if right.location.size in [OS_64,OS_S64] then
  908. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  909. else
  910. {$endif not cpu64bitalu}
  911. hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  912. right.resultdef,left.resultdef,right.location.sref,left.location);
  913. end;
  914. LOC_JUMP :
  915. begin
  916. current_asmdata.getjumplabel(hlabel);
  917. hlcg.a_label(current_asmdata.CurrAsmList,right.location.truelabel);
  918. if is_pasbool(left.resultdef) then
  919. begin
  920. {$ifndef cpu64bitalu}
  921. if left.location.size in [OS_64,OS_S64] then
  922. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
  923. else
  924. {$endif not cpu64bitalu}
  925. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
  926. end
  927. else
  928. begin
  929. {$ifndef cpu64bitalu}
  930. if left.location.size in [OS_64,OS_S64] then
  931. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
  932. else
  933. {$endif not cpu64bitalu}
  934. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
  935. end;
  936. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  937. hlcg.a_label(current_asmdata.CurrAsmList,right.location.falselabel);
  938. {$ifndef cpu64bitalu}
  939. if left.location.size in [OS_64,OS_S64] then
  940. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
  941. else
  942. {$endif not cpu64bitalu}
  943. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
  944. hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
  945. end;
  946. {$ifdef cpuflags}
  947. LOC_FLAGS :
  948. begin
  949. if is_pasbool(left.resultdef) then
  950. begin
  951. case left.location.loc of
  952. LOC_REGISTER,LOC_CREGISTER:
  953. {$ifndef cpu64bitalu}
  954. if left.location.size in [OS_S64,OS_64] then
  955. begin
  956. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
  957. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  958. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
  959. end
  960. else
  961. {$endif not cpu64bitalu}
  962. begin
  963. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  964. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  965. end;
  966. LOC_REFERENCE:
  967. { i8086 and i386 have hacks in their code generators so that they can
  968. deal with 64 bit locations in this parcticular case }
  969. {$if not defined(cpu64bitalu) and not defined(x86)}
  970. if left.location.size in [OS_S64,OS_64] then
  971. begin
  972. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  973. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  974. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  975. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  976. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  977. cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
  978. end
  979. else
  980. {$endif not cpu64bitalu}
  981. begin
  982. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  983. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  984. end;
  985. LOC_SUBSETREG,LOC_SUBSETREF:
  986. begin
  987. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  988. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  989. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  990. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  991. end;
  992. else
  993. internalerror(200203273);
  994. end;
  995. end
  996. else
  997. begin
  998. {$ifndef cpu64bitalu}
  999. if left.location.size in [OS_S64,OS_64] then
  1000. begin
  1001. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1002. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1003. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1004. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1005. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1006. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
  1007. r64,r64);
  1008. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
  1009. end
  1010. else
  1011. {$endif not cpu64bitalu}
  1012. begin
  1013. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1014. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1015. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1016. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  1017. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1018. end
  1019. end;
  1020. end;
  1021. {$endif cpuflags}
  1022. end;
  1023. end;
  1024. if releaseright then
  1025. location_freetemp(current_asmdata.CurrAsmList,right.location);
  1026. end;
  1027. {*****************************************************************************
  1028. SecondArrayConstruct
  1029. *****************************************************************************}
  1030. const
  1031. vtInteger = 0;
  1032. vtBoolean = 1;
  1033. vtChar = 2;
  1034. vtExtended = 3;
  1035. vtString = 4;
  1036. vtPointer = 5;
  1037. vtPChar = 6;
  1038. vtObject = 7;
  1039. vtClass = 8;
  1040. vtWideChar = 9;
  1041. vtPWideChar = 10;
  1042. vtAnsiString32 = 11;
  1043. vtCurrency = 12;
  1044. vtVariant = 13;
  1045. vtInterface = 14;
  1046. vtWideString = 15;
  1047. vtInt64 = 16;
  1048. vtQWord = 17;
  1049. vtUnicodeString = 18;
  1050. vtAnsiString16 = 19;
  1051. vtAnsiString64 = 20;
  1052. procedure tcgarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  1053. begin
  1054. { do nothing by default }
  1055. end;
  1056. procedure tcgarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  1057. begin
  1058. inc(ref.offset,elesize);
  1059. end;
  1060. procedure tcgarrayconstructornode.pass_generate_code;
  1061. var
  1062. hp : tarrayconstructornode;
  1063. href,
  1064. fref : treference;
  1065. lt : tdef;
  1066. paraloc : tcgparalocation;
  1067. varvtypefield,
  1068. varfield : tfieldvarsym;
  1069. vtype : longint;
  1070. eledef: tdef;
  1071. elesize : longint;
  1072. tmpreg : tregister;
  1073. vaddr : boolean;
  1074. freetemp,
  1075. dovariant: boolean;
  1076. begin
  1077. if is_packed_array(resultdef) then
  1078. internalerror(200608042);
  1079. dovariant:=
  1080. ((nf_forcevaria in flags) or is_variant_array(resultdef)) and
  1081. not(target_info.system in systems_managed_vm);
  1082. eledef:=tarraydef(resultdef).elementdef;
  1083. elesize:=eledef.size;
  1084. if dovariant then
  1085. varvtypefield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VTYPE'))
  1086. else
  1087. varvtypefield:=nil;
  1088. { alignment is filled in by tg.gethltemp below }
  1089. location_reset_ref(location,LOC_CREFERENCE,OS_NO,0);
  1090. fillchar(paraloc,sizeof(paraloc),0);
  1091. { Allocate always a temp, also if no elements are required, to
  1092. be sure that location is valid (PFV) }
  1093. { on the JVM platform, an array can have 0 elements; since the length
  1094. of the array is part of the array itself, make sure we allocate one
  1095. of the proper length to avoid getting unexpected results later --
  1096. allocating a temp of size 0 also forces it to be size 4 on regular
  1097. targets }
  1098. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  1099. href:=location.reference;
  1100. makearrayref(href,eledef);
  1101. { Process nodes in array constructor }
  1102. hp:=self;
  1103. while assigned(hp) do
  1104. begin
  1105. if assigned(hp.left) then
  1106. begin
  1107. freetemp:=true;
  1108. secondpass(hp.left);
  1109. if (hp.left.location.loc=LOC_JUMP)<>
  1110. (hp.left.expectloc=LOC_JUMP) then
  1111. internalerror(2007103101);
  1112. { Move flags and jump in register }
  1113. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  1114. hlcg.location_force_reg(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef,hp.left.resultdef,false);
  1115. if dovariant then
  1116. begin
  1117. { find the correct vtype value }
  1118. vtype:=$ff;
  1119. varfield:=nil;
  1120. vaddr:=false;
  1121. lt:=hp.left.resultdef;
  1122. case lt.typ of
  1123. enumdef,
  1124. orddef :
  1125. begin
  1126. if is_64bit(lt) then
  1127. begin
  1128. case torddef(lt).ordtype of
  1129. scurrency:
  1130. begin
  1131. vtype:=vtCurrency;
  1132. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1133. end;
  1134. s64bit:
  1135. begin
  1136. vtype:=vtInt64;
  1137. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINT64'));
  1138. end;
  1139. u64bit:
  1140. begin
  1141. vtype:=vtQWord;
  1142. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VQWORD'));
  1143. end;
  1144. end;
  1145. freetemp:=false;
  1146. vaddr:=true;
  1147. end
  1148. else if (lt.typ=enumdef) or
  1149. is_integer(lt) then
  1150. begin
  1151. vtype:=vtInteger;
  1152. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1153. end
  1154. else
  1155. if is_boolean(lt) then
  1156. begin
  1157. vtype:=vtBoolean;
  1158. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1159. end
  1160. else
  1161. if (lt.typ=orddef) then
  1162. begin
  1163. case torddef(lt).ordtype of
  1164. uchar:
  1165. begin
  1166. vtype:=vtChar;
  1167. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1168. end;
  1169. uwidechar:
  1170. begin
  1171. vtype:=vtWideChar;
  1172. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTEGER'));
  1173. end;
  1174. end;
  1175. end;
  1176. end;
  1177. floatdef :
  1178. begin
  1179. if is_currency(lt) then
  1180. begin
  1181. vtype:=vtCurrency;
  1182. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCURRENCY'));
  1183. end
  1184. else
  1185. begin
  1186. vtype:=vtExtended;
  1187. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VEXTENDED'));
  1188. end;
  1189. freetemp:=false;
  1190. vaddr:=true;
  1191. end;
  1192. procvardef,
  1193. pointerdef :
  1194. begin
  1195. if is_pchar(lt) then
  1196. begin
  1197. vtype:=vtPChar;
  1198. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPCHAR'));
  1199. end
  1200. else if is_pwidechar(lt) then
  1201. begin
  1202. vtype:=vtPWideChar;
  1203. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPWIDECHAR'));
  1204. end
  1205. else
  1206. begin
  1207. vtype:=vtPointer;
  1208. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VPOINTER'));
  1209. end;
  1210. end;
  1211. variantdef :
  1212. begin
  1213. vtype:=vtVariant;
  1214. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VVARIANT'));
  1215. vaddr:=true;
  1216. freetemp:=false;
  1217. end;
  1218. classrefdef :
  1219. begin
  1220. vtype:=vtClass;
  1221. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VCLASS'));
  1222. end;
  1223. objectdef :
  1224. if is_interface(lt) then
  1225. begin
  1226. vtype:=vtInterface;
  1227. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VINTERFACE'));
  1228. end
  1229. { vtObject really means a class based on TObject }
  1230. else if is_class(lt) then
  1231. begin
  1232. vtype:=vtObject;
  1233. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VOBJECT'));
  1234. end
  1235. else
  1236. internalerror(200505171);
  1237. stringdef :
  1238. begin
  1239. if is_shortstring(lt) then
  1240. begin
  1241. vtype:=vtString;
  1242. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VSTRING'));
  1243. vaddr:=true;
  1244. freetemp:=false;
  1245. end
  1246. else
  1247. if is_ansistring(lt) then
  1248. begin
  1249. vtype:=vtAnsiString;
  1250. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VANSISTRING'));
  1251. freetemp:=false;
  1252. end
  1253. else
  1254. if is_widestring(lt) then
  1255. begin
  1256. vtype:=vtWideString;
  1257. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VWIDESTRING'));
  1258. freetemp:=false;
  1259. end
  1260. else
  1261. if is_unicodestring(lt) then
  1262. begin
  1263. vtype:=vtUnicodeString;
  1264. varfield:=tfieldvarsym(search_struct_member_no_helper(trecorddef(eledef),'VUNICODESTRING'));
  1265. freetemp:=false;
  1266. end;
  1267. end;
  1268. end;
  1269. if vtype=$ff then
  1270. internalerror(14357);
  1271. if not assigned(varfield) then
  1272. internalerror(2015102901);
  1273. { write changing field update href to the next element }
  1274. fref:=href;
  1275. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varfield,fref);
  1276. if vaddr then
  1277. begin
  1278. hlcg.location_force_mem(current_asmdata.CurrAsmList,hp.left.location,lt);
  1279. tmpreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt));
  1280. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.resultdef,cpointerdef.getreusable(lt),hp.left.location.reference,tmpreg);
  1281. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(lt),varfield.vardef,tmpreg,fref);
  1282. end
  1283. else
  1284. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.resultdef,varfield.vardef,hp.left.location,fref);
  1285. { update href to the vtype field and write it }
  1286. fref:=href;
  1287. hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varvtypefield,fref);
  1288. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,varvtypefield.vardef,vtype,fref);
  1289. { goto next array element }
  1290. advancearrayoffset(href,elesize);
  1291. end
  1292. else
  1293. { normal array constructor of the same type }
  1294. begin
  1295. if is_managed_type(resultdef) then
  1296. freetemp:=false;
  1297. case hp.left.location.loc of
  1298. LOC_MMREGISTER,
  1299. LOC_CMMREGISTER:
  1300. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,
  1301. hp.left.location.register,href,mms_movescalar);
  1302. LOC_FPUREGISTER,
  1303. LOC_CFPUREGISTER :
  1304. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,hp.left.location.register,href);
  1305. LOC_REFERENCE,
  1306. LOC_CREFERENCE :
  1307. begin
  1308. if is_shortstring(hp.left.resultdef) then
  1309. hlcg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1310. Tstringdef(hp.left.resultdef))
  1311. else
  1312. hlcg.g_concatcopy(current_asmdata.CurrAsmList,eledef,hp.left.location.reference,href);
  1313. end;
  1314. else
  1315. begin
  1316. {$ifndef cpuhighleveltarget}
  1317. {$ifdef cpu64bitalu}
  1318. if hp.left.location.size in [OS_128,OS_S128] then
  1319. cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1320. else
  1321. {$else cpu64bitalu}
  1322. if hp.left.location.size in [OS_64,OS_S64] then
  1323. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1324. else
  1325. {$endif cpu64bitalu}
  1326. {$endif not cpuhighleveltarget}
  1327. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
  1328. end;
  1329. end;
  1330. advancearrayoffset(href,elesize);
  1331. end;
  1332. if freetemp then
  1333. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1334. end;
  1335. { load next entry }
  1336. hp:=tarrayconstructornode(hp.right);
  1337. end;
  1338. end;
  1339. {*****************************************************************************
  1340. SecondRTTI
  1341. *****************************************************************************}
  1342. procedure tcgrttinode.pass_generate_code;
  1343. begin
  1344. location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint));
  1345. case rttidatatype of
  1346. rdt_normal:
  1347. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  1348. rdt_ord2str:
  1349. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype);
  1350. rdt_str2ord:
  1351. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype);
  1352. end;
  1353. end;
  1354. begin
  1355. cloadnode:=tcgloadnode;
  1356. cassignmentnode:=tcgassignmentnode;
  1357. carrayconstructornode:=tcgarrayconstructornode;
  1358. crttinode:=tcgrttinode;
  1359. end.