ncgld.pas 71 KB

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