ncgld.pas 66 KB

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