ncgld.pas 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425
  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. vd,
  227. pvd : tdef;
  228. begin
  229. { we don't know the size of all arrays }
  230. newsize:=def_cgsize(resultdef);
  231. { alignment is overridden per case below }
  232. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment);
  233. case symtableentry.typ of
  234. absolutevarsym :
  235. begin
  236. { this is only for toasm and toaddr }
  237. case tabsolutevarsym(symtableentry).abstyp of
  238. toaddr :
  239. begin
  240. {$if defined(i8086)}
  241. if tabsolutevarsym(symtableentry).absseg then
  242. begin
  243. location.reference.segment:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
  244. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_16,aint(tabsolutevarsym(symtableentry).addrsegment),location.reference.segment);
  245. end;
  246. {$elseif defined(i386)}
  247. if tabsolutevarsym(symtableentry).absseg then
  248. location.reference.segment:=NR_FS;
  249. {$endif}
  250. location.reference.offset:=aint(tabsolutevarsym(symtableentry).addroffset);
  251. end;
  252. toasm :
  253. location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
  254. else
  255. internalerror(200310283);
  256. end;
  257. end;
  258. constsym:
  259. begin
  260. if tconstsym(symtableentry).consttyp=constresourcestring then
  261. begin
  262. location_reset_ref(location,LOC_CREFERENCE,OS_ADDR,sizeof(pint));
  263. location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name),AT_DATA);
  264. { Resourcestring layout:
  265. TResourceStringRecord = Packed Record
  266. Name,
  267. CurrentValue,
  268. DefaultValue : AnsiString;
  269. HashValue : LongWord;
  270. end;
  271. }
  272. location.reference.offset:=sizeof(pint);
  273. end
  274. else
  275. internalerror(22798);
  276. end;
  277. staticvarsym :
  278. begin
  279. gvs:=tstaticvarsym(symtableentry);
  280. if (vo_is_dll_var in gvs.varoptions) then
  281. { DLL variable }
  282. begin
  283. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  284. if not(vo_is_weak_external in gvs.varoptions) then
  285. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname)
  286. else
  287. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
  288. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
  289. reference_reset_base(location.reference,hregister,0,location.reference.alignment);
  290. end
  291. { Thread variable }
  292. else if (vo_is_thread_var in gvs.varoptions) then
  293. begin
  294. if (tf_section_threadvars in target_info.flags) then
  295. begin
  296. if target_info.system in [system_i386_win32,system_x86_64_win64] then
  297. begin
  298. paraloc1.init;
  299. pd:=search_system_proc('fpc_tls_add');
  300. paramanager.getintparaloc(pd,1,paraloc1);
  301. if not(vo_is_weak_external in gvs.varoptions) then
  302. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
  303. else
  304. reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
  305. cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href,paraloc1);
  306. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  307. paraloc1.done;
  308. cg.g_call(current_asmdata.CurrAsmList,'FPC_TLS_ADD');
  309. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  310. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  311. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  312. location.reference.base:=hregister;
  313. end
  314. else
  315. begin
  316. if gvs.localloc.loc=LOC_INVALID then
  317. if not(vo_is_weak_external in gvs.varoptions) then
  318. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
  319. else
  320. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
  321. else
  322. location:=gvs.localloc;
  323. {$ifdef i386}
  324. case target_info.system of
  325. system_i386_linux,system_i386_android:
  326. location.reference.segment:=NR_GS;
  327. end;
  328. {$endif i386}
  329. end;
  330. end
  331. else
  332. begin
  333. {
  334. Thread var loading is optimized to first check if
  335. a relocate function is available. When the function
  336. is available it is called to retrieve the address.
  337. Otherwise the address is loaded with the symbol
  338. The code needs to be in the order to first handle the
  339. call and then the address load to be sure that the
  340. register that is used for returning is the same (PFV)
  341. }
  342. current_asmdata.getjumplabel(norelocatelab);
  343. current_asmdata.getjumplabel(endrelocatelab);
  344. { make sure hregister can't allocate the register necessary for the parameter }
  345. pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
  346. if pvd.typ<>procvardef then
  347. internalerror(2012120901);
  348. paraloc1.init;
  349. paramanager.getintparaloc(tprocvardef(pvd),1,paraloc1);
  350. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  351. reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,sizeof(pint));
  352. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  353. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
  354. { don't save the allocated register else the result will be destroyed later }
  355. if not(vo_is_weak_external in gvs.varoptions) then
  356. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
  357. else
  358. reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
  359. cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  360. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  361. paraloc1.done;
  362. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  363. cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
  364. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  365. cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  366. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  367. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  368. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  369. cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
  370. cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
  371. { no relocation needed, load the address of the variable only, the
  372. layout of a threadvar is (4 bytes pointer):
  373. 0 - Threadvar index
  374. 4 - Threadvar value in single threading }
  375. if not(vo_is_weak_external in gvs.varoptions) then
  376. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint))
  377. else
  378. reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint));
  379. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  380. cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
  381. location.reference.base:=hregister;
  382. end;
  383. end
  384. { Normal (or external) variable }
  385. else
  386. begin
  387. if gvs.localloc.loc=LOC_INVALID then
  388. if not(vo_is_weak_external in gvs.varoptions) then
  389. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
  390. else
  391. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
  392. else
  393. location:=gvs.localloc;
  394. end;
  395. { make const a LOC_CREFERENCE }
  396. if (gvs.varspez=vs_const) and
  397. (location.loc=LOC_REFERENCE) then
  398. location.loc:=LOC_CREFERENCE;
  399. end;
  400. paravarsym,
  401. localvarsym :
  402. begin
  403. vs:=tabstractnormalvarsym(symtableentry);
  404. { Nested variable }
  405. if assigned(left) then
  406. generate_nested_access(vs)
  407. else
  408. location:=vs.localloc;
  409. { handle call by reference variables when they are not
  410. already copied to local copies. Also ignore the reference
  411. when we need to load the self pointer for objects }
  412. if is_addr_param_load then
  413. begin
  414. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  415. hregister:=location.register
  416. else
  417. begin
  418. vd:=getpointerdef(resultdef);
  419. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vd);
  420. { we need to load only an address }
  421. location.size:=OS_ADDR;
  422. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,vd,vd,location,hregister);
  423. end;
  424. { assume packed records may always be unaligned }
  425. if not(resultdef.typ in [recorddef,objectdef]) or
  426. (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
  427. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment)
  428. else
  429. location_reset_ref(location,LOC_REFERENCE,newsize,1);
  430. location.reference.base:=hregister;
  431. end;
  432. { make const a LOC_CREFERENCE }
  433. if (vs.varspez=vs_const) and
  434. (location.loc=LOC_REFERENCE) then
  435. location.loc:=LOC_CREFERENCE;
  436. end;
  437. procsym:
  438. begin
  439. if not assigned(procdef) then
  440. internalerror(200312011);
  441. if assigned(left) then
  442. begin
  443. location_reset(location,LOC_CREGISTER,int_cgsize(voidpointertype.size*2));
  444. secondpass(left);
  445. { load class instance/classrefdef address }
  446. if left.location.loc=LOC_CONSTANT then
  447. { todo: exact type for hlcg (can't use left.resultdef, because can be TP-style object, which is not pointer-sized) }
  448. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,voidpointertype,false);
  449. case left.location.loc of
  450. LOC_CREGISTER,
  451. LOC_REGISTER:
  452. begin
  453. { this is not possible for objects }
  454. if is_object(left.resultdef) then
  455. internalerror(200304234);
  456. location.registerhi:=left.location.register;
  457. end;
  458. LOC_CREFERENCE,
  459. LOC_REFERENCE:
  460. begin
  461. location.registerhi:=cg.getaddressregister(current_asmdata.CurrAsmList);
  462. if not is_object(left.resultdef) then
  463. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.registerhi)
  464. else
  465. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.registerhi);
  466. location_freetemp(current_asmdata.CurrAsmList,left.location);
  467. end;
  468. else
  469. internalerror(200610311);
  470. end;
  471. { virtual method ? }
  472. if (po_virtualmethod in procdef.procoptions) and
  473. not(loadnf_inherited in loadnodeflags) and
  474. not is_objectpascal_helper(procdef.struct) then
  475. begin
  476. if (not assigned(current_procinfo) or
  477. wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
  478. tobjectdef(procdef.struct).register_vmt_call(procdef.extnumber);
  479. {$ifdef vtentry}
  480. if not is_interface(procdef.struct) then
  481. begin
  482. inc(current_asmdata.NextVTEntryNr);
  483. current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+procdef._class.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0));
  484. end;
  485. {$endif vtentry}
  486. { a classrefdef already points to the VMT }
  487. if (left.resultdef.typ<>classrefdef) then
  488. begin
  489. { load vmt pointer }
  490. reference_reset_base(href,location.registerhi,tobjectdef(left.resultdef).vmt_offset,sizeof(pint));
  491. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  492. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  493. end
  494. else
  495. hregister:=location.registerhi;
  496. { load method address }
  497. {$ifdef i8086}
  498. if po_far in procdef.procoptions then
  499. begin
  500. reference_reset_base(href,hregister,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
  501. location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  502. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,href,location.register);
  503. end
  504. else
  505. {$endif i8086}
  506. begin
  507. reference_reset_base(href,hregister,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
  508. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  509. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
  510. end;
  511. end
  512. else
  513. begin
  514. { load address of the function }
  515. {$ifdef i8086}
  516. if po_far in procdef.procoptions then
  517. begin
  518. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0,sizeof(pint));
  519. location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  520. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
  521. href.refaddr:=addr_seg;
  522. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_16,OS_16,href,GetNextReg(location.register));
  523. end
  524. else
  525. {$endif i8086}
  526. begin
  527. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0,sizeof(pint));
  528. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  529. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
  530. end;
  531. end;
  532. { to get methodpointers stored correctly, code and self register must be swapped on
  533. big endian targets }
  534. if target_info.endian=endian_big then
  535. begin
  536. hregister:=location.register;
  537. location.register:=location.registerhi;
  538. location.registerhi:=hregister;
  539. end;
  540. end
  541. else
  542. begin
  543. { def_cgsize does not work for procdef }
  544. location.size:=OS_ADDR;
  545. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  546. {$ifdef i8086}
  547. if po_far in pd.procoptions then
  548. location.size:=OS_32;
  549. {$endif i8086}
  550. if not(po_weakexternal in pd.procoptions) then
  551. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname)
  552. else
  553. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname);
  554. end;
  555. end;
  556. labelsym :
  557. if assigned(tlabelsym(symtableentry).asmblocklabel) then
  558. location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
  559. else
  560. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  561. else internalerror(200510032);
  562. end;
  563. end;
  564. {*****************************************************************************
  565. SecondAssignment
  566. *****************************************************************************}
  567. procedure tcgassignmentnode.pass_generate_code;
  568. var
  569. otlabel,hlabel,oflabel : tasmlabel;
  570. href : treference;
  571. releaseright : boolean;
  572. alignmentrequirement,
  573. len : aint;
  574. r : tregister;
  575. r64 : tregister64;
  576. oldflowcontrol : tflowcontrol;
  577. begin
  578. { previously, managed types were handled in firstpass
  579. newer FPCs however can identify situations when
  580. assignments of managed types require no special code and the
  581. value could be just copied so this could should be able also to handle
  582. managed types without any special "managing code"}
  583. location_reset(location,LOC_VOID,OS_NO);
  584. otlabel:=current_procinfo.CurrTrueLabel;
  585. oflabel:=current_procinfo.CurrFalseLabel;
  586. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  587. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  588. {
  589. in most cases we can process first the right node which contains
  590. the most complex code. Exceptions for this are:
  591. - result is in flags, loading left will then destroy the flags
  592. - result is a jump, loading left must be already done before the jump is made
  593. - result need reference count, when left points to a value used in
  594. right then decreasing the refcnt on left can possibly release
  595. the memory before right increased the refcnt, result is that an
  596. empty value is assigned
  597. But not when the result is in the flags, then
  598. loading the left node afterwards can destroy the flags.
  599. }
  600. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  601. (node_complexity(right)>node_complexity(left)) then
  602. begin
  603. secondpass(right);
  604. if codegenerror then
  605. exit;
  606. secondpass(left);
  607. if codegenerror then
  608. exit;
  609. end
  610. else
  611. begin
  612. { calculate left sides }
  613. secondpass(left);
  614. if codegenerror then
  615. exit;
  616. { tell the SSA/SSL code that the left side was handled first so
  617. ni SSL is done
  618. }
  619. oldflowcontrol:=flowcontrol;
  620. include(flowcontrol,fc_lefthandled);
  621. secondpass(right);
  622. flowcontrol:=oldflowcontrol;
  623. if codegenerror then
  624. exit;
  625. end;
  626. releaseright:=true;
  627. { shortstring assignments are handled separately }
  628. if is_shortstring(left.resultdef) then
  629. begin
  630. {
  631. we can get here only in the following situations
  632. for the right node:
  633. - empty constant string
  634. - char
  635. }
  636. { The addn is replaced by a blockn or calln that already returns
  637. a shortstring }
  638. if is_shortstring(right.resultdef) and
  639. (right.nodetype in [blockn,calln]) then
  640. begin
  641. { nothing to do }
  642. end
  643. { empty constant string }
  644. else if (right.nodetype=stringconstn) and
  645. (tstringconstnode(right).len=0) then
  646. begin
  647. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u8inttype,0,left.location.reference);
  648. end
  649. { char loading }
  650. else if is_char(right.resultdef) then
  651. begin
  652. if right.nodetype=ordconstn then
  653. begin
  654. if (target_info.endian = endian_little) then
  655. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,(tordconstnode(right).value.svalue shl 8) or 1,
  656. setalignment(left.location.reference,1))
  657. else
  658. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,tordconstnode(right).value.svalue or (1 shl 8),
  659. setalignment(left.location.reference,1));
  660. end
  661. else
  662. begin
  663. href:=left.location.reference;
  664. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u8inttype,1,href);
  665. inc(href.offset,1);
  666. case right.location.loc of
  667. LOC_REGISTER,
  668. LOC_CREGISTER :
  669. begin
  670. {$ifndef cpuhighleveltarget}
  671. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  672. {$else not cpuhighleveltarget}
  673. r:=hlcg.getintregister(current_asmdata.CurrAsmList,u8inttype);
  674. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,u8inttype,u8inttype,right.location.register,r);
  675. {$endif cpuhighleveltarget}
  676. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,r,href);
  677. end;
  678. LOC_REFERENCE,
  679. LOC_CREFERENCE :
  680. hlcg.a_load_ref_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,right.location.reference,href);
  681. else
  682. internalerror(200205111);
  683. end;
  684. end;
  685. end
  686. else
  687. internalerror(2002042410);
  688. end
  689. { try to reuse memory locations instead of copying }
  690. { copy to a memory location ... }
  691. else if (right.location.loc = LOC_REFERENCE) and
  692. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  693. begin
  694. { if it worked, we're done }
  695. end
  696. else
  697. begin
  698. { SSA support }
  699. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
  700. maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
  701. case right.location.loc of
  702. LOC_CONSTANT :
  703. begin
  704. {$ifndef cpu64bitalu}
  705. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  706. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  707. else
  708. {$endif not cpu64bitalu}
  709. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
  710. end;
  711. LOC_REFERENCE,
  712. LOC_CREFERENCE :
  713. begin
  714. case left.location.loc of
  715. LOC_REGISTER,
  716. LOC_CREGISTER :
  717. begin
  718. {$ifdef cpu64bitalu}
  719. if left.location.size in [OS_128,OS_S128] then
  720. cg128.a_load128_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register128)
  721. else
  722. {$else cpu64bitalu}
  723. if left.location.size in [OS_64,OS_S64] then
  724. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  725. else
  726. {$endif cpu64bitalu}
  727. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
  728. end;
  729. LOC_FPUREGISTER,
  730. LOC_CFPUREGISTER :
  731. begin
  732. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  733. right.resultdef,left.resultdef,
  734. right.location.reference,
  735. left.location.register);
  736. end;
  737. LOC_REFERENCE,
  738. LOC_CREFERENCE :
  739. begin
  740. if (left.resultdef.typ=floatdef) and
  741. (right.resultdef.typ=floatdef) and
  742. (left.location.size<>right.location.size) then
  743. begin
  744. hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  745. right.resultdef,left.resultdef,
  746. right.location.reference,left.location.reference)
  747. end
  748. else
  749. begin
  750. { TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  751. { Use unaligned copy when the offset is not aligned }
  752. len:=left.resultdef.size;
  753. { can be 0 in case of formaldef on JVM target }
  754. if len=0 then
  755. len:=sizeof(pint);
  756. { data smaller than an aint has less alignment requirements }
  757. { max(1,...) avoids div by zero in case of an empty record }
  758. alignmentrequirement:=min(max(1,len),sizeof(aint));
  759. if (right.location.reference.offset mod alignmentrequirement<>0) or
  760. (left.location.reference.offset mod alignmentrequirement<>0) or
  761. (right.resultdef.alignment<alignmentrequirement) or
  762. ((right.location.reference.alignment<>0) and
  763. (right.location.reference.alignment<alignmentrequirement)) or
  764. ((left.location.reference.alignment<>0) and
  765. (left.location.reference.alignment<alignmentrequirement)) then
  766. hlcg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference)
  767. else
  768. hlcg.g_concatcopy(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference);
  769. end;
  770. end;
  771. LOC_MMREGISTER,
  772. LOC_CMMREGISTER:
  773. begin
  774. {$ifdef x86}
  775. if (right.resultdef.typ=floatdef) and
  776. not use_vectorfpu(right.resultdef) then
  777. begin
  778. { perform size conversion if needed (the mm-code cannot }
  779. { convert an extended into a double/single, since sse }
  780. { doesn't support extended) }
  781. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  782. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  783. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  784. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  785. if releaseright then
  786. location_freetemp(current_asmdata.CurrAsmList,right.location);
  787. releaseright:=true;
  788. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
  789. right.location.reference:=href;
  790. right.resultdef:=left.resultdef;
  791. end;
  792. {$endif}
  793. hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  794. right.resultdef,
  795. left.resultdef,
  796. right.location.reference,
  797. left.location.register,mms_movescalar);
  798. end;
  799. LOC_SUBSETREG,
  800. LOC_CSUBSETREG:
  801. hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
  802. LOC_SUBSETREF,
  803. LOC_CSUBSETREF:
  804. {$ifndef cpu64bitalu}
  805. if right.location.size in [OS_64,OS_S64] then
  806. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  807. else
  808. {$endif not cpu64bitalu}
  809. hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
  810. else
  811. internalerror(200203284);
  812. end;
  813. end;
  814. {$ifdef SUPPORT_MMX}
  815. LOC_CMMXREGISTER,
  816. LOC_MMXREGISTER:
  817. begin
  818. if left.location.loc=LOC_CMMXREGISTER then
  819. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  820. else
  821. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  822. end;
  823. {$endif SUPPORT_MMX}
  824. LOC_MMREGISTER,
  825. LOC_CMMREGISTER:
  826. begin
  827. if left.resultdef.typ=arraydef then
  828. begin
  829. end
  830. else
  831. begin
  832. case left.location.loc of
  833. LOC_CMMREGISTER,
  834. LOC_MMREGISTER:
  835. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.register,mms_movescalar);
  836. LOC_REFERENCE,
  837. LOC_CREFERENCE:
  838. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location.reference,mms_movescalar);
  839. else
  840. internalerror(2009112601);
  841. end;
  842. end;
  843. end;
  844. LOC_REGISTER,
  845. LOC_CREGISTER :
  846. begin
  847. {$ifdef cpu64bitalu}
  848. if left.location.size in [OS_128,OS_S128] then
  849. cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
  850. right.location.register128,left.location)
  851. else
  852. {$else cpu64bitalu}
  853. { also OS_F64 in case of mmreg -> intreg }
  854. if left.location.size in [OS_64,OS_S64,OS_F64] then
  855. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  856. right.location.register64,left.location)
  857. else
  858. {$endif cpu64bitalu}
  859. {$ifdef i8086}
  860. { i8086 method pointer support (incl. 6-byte method pointers for the medium and compact memory models) }
  861. if (left.resultdef.typ = procvardef) and
  862. ((po_methodpointer in tprocvardef(left.resultdef).procoptions) or is_nested_pd(tprocvardef(left.resultdef))) and
  863. not(po_addressonly in tprocvardef(left.resultdef).procoptions) then
  864. begin
  865. case left.location.loc of
  866. LOC_REFERENCE,LOC_CREFERENCE:
  867. begin
  868. href:=left.location.reference;
  869. { proc address }
  870. if po_far in tprocdef(right.resultdef).procoptions then
  871. begin
  872. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_32,OS_32,right.location.register,href);
  873. inc(href.offset, 4)
  874. end
  875. else
  876. begin
  877. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_16,OS_16,right.location.register,href);
  878. inc(href.offset, 2);
  879. end;
  880. { object self }
  881. if current_settings.x86memorymodel in x86_far_data_models then
  882. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_32,OS_32,right.location.registerhi,href)
  883. else
  884. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_16,OS_16,right.location.registerhi,href);
  885. end;
  886. else
  887. internalerror(2013072001);
  888. end;
  889. end
  890. else
  891. {$endif i8086}
  892. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
  893. end;
  894. LOC_FPUREGISTER,
  895. LOC_CFPUREGISTER :
  896. begin
  897. { we can't do direct moves between fpu and mm registers }
  898. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  899. begin
  900. {$ifdef x86}
  901. if not use_vectorfpu(right.resultdef) then
  902. begin
  903. { perform size conversion if needed (the mm-code cannot convert an }
  904. { extended into a double/single, since sse doesn't support extended) }
  905. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  906. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  907. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
  908. right.location.reference:=href;
  909. right.resultdef:=left.resultdef;
  910. end;
  911. {$endif}
  912. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,false);
  913. hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  914. right.resultdef,left.resultdef,
  915. right.location.register,left.location.register,mms_movescalar);
  916. end
  917. else
  918. hlcg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  919. right.resultdef,left.resultdef,
  920. right.location.register,left.location);
  921. end;
  922. LOC_SUBSETREG,
  923. LOC_CSUBSETREG:
  924. begin
  925. hlcg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  926. right.resultdef,left.resultdef,right.location.sreg,left.location);
  927. end;
  928. LOC_SUBSETREF,
  929. LOC_CSUBSETREF:
  930. begin
  931. {$ifndef cpu64bitalu}
  932. if right.location.size in [OS_64,OS_S64] then
  933. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  934. else
  935. {$endif not cpu64bitalu}
  936. hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  937. right.resultdef,left.resultdef,right.location.sref,left.location);
  938. end;
  939. LOC_JUMP :
  940. begin
  941. current_asmdata.getjumplabel(hlabel);
  942. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  943. if is_pasbool(left.resultdef) then
  944. begin
  945. {$ifndef cpu64bitalu}
  946. if left.location.size in [OS_64,OS_S64] then
  947. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
  948. else
  949. {$endif not cpu64bitalu}
  950. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
  951. end
  952. else
  953. begin
  954. {$ifndef cpu64bitalu}
  955. if left.location.size in [OS_64,OS_S64] then
  956. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
  957. else
  958. {$endif not cpu64bitalu}
  959. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
  960. end;
  961. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  962. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  963. {$ifndef cpu64bitalu}
  964. if left.location.size in [OS_64,OS_S64] then
  965. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
  966. else
  967. {$endif not cpu64bitalu}
  968. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
  969. hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
  970. end;
  971. {$ifdef cpuflags}
  972. LOC_FLAGS :
  973. begin
  974. if is_pasbool(left.resultdef) then
  975. begin
  976. case left.location.loc of
  977. LOC_REGISTER,LOC_CREGISTER:
  978. {$ifndef cpu64bitalu}
  979. if left.location.size in [OS_S64,OS_64] then
  980. begin
  981. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
  982. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  983. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
  984. end
  985. else
  986. {$endif not cpu64bitalu}
  987. begin
  988. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  989. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  990. end;
  991. LOC_REFERENCE:
  992. { i8086 and i386 have hacks in their code generators so that they can
  993. deal with 64 bit locations in this parcticular case }
  994. {$if not defined(cpu64bitalu) and not defined(x86)}
  995. if left.location.size in [OS_S64,OS_64] then
  996. begin
  997. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  998. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  999. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1000. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1001. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1002. cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
  1003. end
  1004. else
  1005. {$endif not cpu64bitalu}
  1006. begin
  1007. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  1008. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1009. end;
  1010. LOC_SUBSETREG,LOC_SUBSETREF:
  1011. begin
  1012. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1013. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1014. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1015. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1016. end;
  1017. else
  1018. internalerror(200203273);
  1019. end;
  1020. end
  1021. else
  1022. begin
  1023. {$ifndef cpu64bitalu}
  1024. if left.location.size in [OS_S64,OS_64] then
  1025. begin
  1026. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1027. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  1028. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  1029. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1030. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  1031. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
  1032. r64,r64);
  1033. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
  1034. end
  1035. else
  1036. {$endif not cpu64bitalu}
  1037. begin
  1038. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  1039. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  1040. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  1041. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  1042. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  1043. end
  1044. end;
  1045. end;
  1046. {$endif cpuflags}
  1047. end;
  1048. end;
  1049. if releaseright then
  1050. location_freetemp(current_asmdata.CurrAsmList,right.location);
  1051. current_procinfo.CurrTrueLabel:=otlabel;
  1052. current_procinfo.CurrFalseLabel:=oflabel;
  1053. end;
  1054. {*****************************************************************************
  1055. SecondArrayConstruct
  1056. *****************************************************************************}
  1057. const
  1058. vtInteger = 0;
  1059. vtBoolean = 1;
  1060. vtChar = 2;
  1061. vtExtended = 3;
  1062. vtString = 4;
  1063. vtPointer = 5;
  1064. vtPChar = 6;
  1065. vtObject = 7;
  1066. vtClass = 8;
  1067. vtWideChar = 9;
  1068. vtPWideChar = 10;
  1069. vtAnsiString32 = 11;
  1070. vtCurrency = 12;
  1071. vtVariant = 13;
  1072. vtInterface = 14;
  1073. vtWideString = 15;
  1074. vtInt64 = 16;
  1075. vtQWord = 17;
  1076. vtUnicodeString = 18;
  1077. vtAnsiString16 = 19;
  1078. vtAnsiString64 = 20;
  1079. procedure tcgarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  1080. begin
  1081. { do nothing by default }
  1082. end;
  1083. procedure tcgarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  1084. begin
  1085. inc(ref.offset,elesize);
  1086. end;
  1087. procedure tcgarrayconstructornode.pass_generate_code;
  1088. var
  1089. hp : tarrayconstructornode;
  1090. href : treference;
  1091. lt : tdef;
  1092. paraloc : tcgparalocation;
  1093. otlabel,
  1094. oflabel : tasmlabel;
  1095. vtype : longint;
  1096. eledef: tdef;
  1097. elesize : longint;
  1098. tmpreg : tregister;
  1099. vaddr : boolean;
  1100. freetemp,
  1101. dovariant: boolean;
  1102. begin
  1103. otlabel:=nil;
  1104. oflabel:=nil;
  1105. if is_packed_array(resultdef) then
  1106. internalerror(200608042);
  1107. dovariant:=
  1108. ((nf_forcevaria in flags) or is_variant_array(resultdef)) and
  1109. not(target_info.system in systems_managed_vm);
  1110. if dovariant then
  1111. begin
  1112. eledef:=search_system_type('TVARREC').typedef;
  1113. elesize:=eledef.size;
  1114. end
  1115. else
  1116. begin
  1117. eledef:=tarraydef(resultdef).elementdef;
  1118. elesize:=tarraydef(resultdef).elesize;
  1119. end;
  1120. { alignment is filled in by tg.gethltemp below }
  1121. location_reset_ref(location,LOC_CREFERENCE,OS_NO,0);
  1122. fillchar(paraloc,sizeof(paraloc),0);
  1123. { Allocate always a temp, also if no elements are required, to
  1124. be sure that location is valid (PFV) }
  1125. { on the JVM platform, an array can have 0 elements; since the length
  1126. of the array is part of the array itself, make sure we allocate one
  1127. of the proper length to avoid getting unexpected results later }
  1128. if tarraydef(resultdef).highrange=-1 then
  1129. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,{$ifdef jvm}0{$else}elesize{$endif},tt_normal,location.reference)
  1130. else
  1131. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  1132. href:=location.reference;
  1133. makearrayref(href,eledef);
  1134. { Process nodes in array constructor }
  1135. hp:=self;
  1136. while assigned(hp) do
  1137. begin
  1138. if assigned(hp.left) then
  1139. begin
  1140. freetemp:=true;
  1141. if (hp.left.expectloc=LOC_JUMP) then
  1142. begin
  1143. otlabel:=current_procinfo.CurrTrueLabel;
  1144. oflabel:=current_procinfo.CurrFalseLabel;
  1145. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  1146. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  1147. end;
  1148. secondpass(hp.left);
  1149. { Move flags and jump in register }
  1150. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  1151. hlcg.location_force_reg(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef,hp.left.resultdef,false);
  1152. if (hp.left.location.loc=LOC_JUMP) then
  1153. begin
  1154. if (hp.left.expectloc<>LOC_JUMP) then
  1155. internalerror(2007103101);
  1156. current_procinfo.CurrTrueLabel:=otlabel;
  1157. current_procinfo.CurrFalseLabel:=oflabel;
  1158. end;
  1159. if dovariant then
  1160. begin
  1161. { find the correct vtype value }
  1162. vtype:=$ff;
  1163. vaddr:=false;
  1164. lt:=hp.left.resultdef;
  1165. case lt.typ of
  1166. enumdef,
  1167. orddef :
  1168. begin
  1169. if is_64bit(lt) then
  1170. begin
  1171. case torddef(lt).ordtype of
  1172. scurrency:
  1173. vtype:=vtCurrency;
  1174. s64bit:
  1175. vtype:=vtInt64;
  1176. u64bit:
  1177. vtype:=vtQWord;
  1178. end;
  1179. freetemp:=false;
  1180. vaddr:=true;
  1181. end
  1182. else if (lt.typ=enumdef) or
  1183. is_integer(lt) then
  1184. vtype:=vtInteger
  1185. else
  1186. if is_boolean(lt) then
  1187. vtype:=vtBoolean
  1188. else
  1189. if (lt.typ=orddef) then
  1190. begin
  1191. case torddef(lt).ordtype of
  1192. uchar:
  1193. vtype:=vtChar;
  1194. uwidechar:
  1195. vtype:=vtWideChar;
  1196. end;
  1197. end;
  1198. end;
  1199. floatdef :
  1200. begin
  1201. if is_currency(lt) then
  1202. vtype:=vtCurrency
  1203. else
  1204. vtype:=vtExtended;
  1205. freetemp:=false;
  1206. vaddr:=true;
  1207. end;
  1208. procvardef,
  1209. pointerdef :
  1210. begin
  1211. if is_pchar(lt) then
  1212. vtype:=vtPChar
  1213. else if is_pwidechar(lt) then
  1214. vtype:=vtPWideChar
  1215. else
  1216. vtype:=vtPointer;
  1217. end;
  1218. variantdef :
  1219. begin
  1220. vtype:=vtVariant;
  1221. vaddr:=true;
  1222. freetemp:=false;
  1223. end;
  1224. classrefdef :
  1225. vtype:=vtClass;
  1226. objectdef :
  1227. if is_interface(lt) then
  1228. vtype:=vtInterface
  1229. { vtObject really means a class based on TObject }
  1230. else if is_class(lt) then
  1231. vtype:=vtObject
  1232. else
  1233. internalerror(200505171);
  1234. stringdef :
  1235. begin
  1236. if is_shortstring(lt) then
  1237. begin
  1238. vtype:=vtString;
  1239. vaddr:=true;
  1240. freetemp:=false;
  1241. end
  1242. else
  1243. if is_ansistring(lt) then
  1244. begin
  1245. vtype:=vtAnsiString;
  1246. freetemp:=false;
  1247. end
  1248. else
  1249. if is_widestring(lt) then
  1250. begin
  1251. vtype:=vtWideString;
  1252. freetemp:=false;
  1253. end
  1254. else
  1255. if is_unicodestring(lt) then
  1256. begin
  1257. vtype:=vtUnicodeString;
  1258. freetemp:=false;
  1259. end;
  1260. end;
  1261. end;
  1262. if vtype=$ff then
  1263. internalerror(14357);
  1264. { write changing field update href to the next element }
  1265. inc(href.offset,sizeof(pint));
  1266. if vaddr then
  1267. begin
  1268. hlcg.location_force_mem(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef);
  1269. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  1270. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  1271. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  1272. end
  1273. else
  1274. { todo: proper type information for hlcg }
  1275. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.resultdef,{$ifdef cpu16bitaddr}u32inttype{$else}voidpointertype{$endif},hp.left.location,href);
  1276. { update href to the vtype field and write it }
  1277. dec(href.offset,sizeof(pint));
  1278. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  1279. { goto next array element }
  1280. advancearrayoffset(href,elesize);
  1281. end
  1282. else
  1283. { normal array constructor of the same type }
  1284. begin
  1285. if is_managed_type(resultdef) then
  1286. freetemp:=false;
  1287. case hp.left.location.loc of
  1288. LOC_MMREGISTER,
  1289. LOC_CMMREGISTER:
  1290. hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,
  1291. hp.left.location.register,href,mms_movescalar);
  1292. LOC_FPUREGISTER,
  1293. LOC_CFPUREGISTER :
  1294. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,hp.left.location.register,href);
  1295. LOC_REFERENCE,
  1296. LOC_CREFERENCE :
  1297. begin
  1298. if is_shortstring(hp.left.resultdef) then
  1299. hlcg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1300. Tstringdef(hp.left.resultdef))
  1301. else
  1302. hlcg.g_concatcopy(current_asmdata.CurrAsmList,eledef,hp.left.location.reference,href);
  1303. end;
  1304. else
  1305. begin
  1306. {$ifdef cpu64bitalu}
  1307. if hp.left.location.size in [OS_128,OS_S128] then
  1308. cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1309. else
  1310. {$else cpu64bitalu}
  1311. if hp.left.location.size in [OS_64,OS_S64] then
  1312. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1313. else
  1314. {$endif cpu64bitalu}
  1315. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
  1316. end;
  1317. end;
  1318. advancearrayoffset(href,elesize);
  1319. end;
  1320. if freetemp then
  1321. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1322. end;
  1323. { load next entry }
  1324. hp:=tarrayconstructornode(hp.right);
  1325. end;
  1326. end;
  1327. {*****************************************************************************
  1328. SecondRTTI
  1329. *****************************************************************************}
  1330. procedure tcgrttinode.pass_generate_code;
  1331. begin
  1332. location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint));
  1333. case rttidatatype of
  1334. rdt_normal:
  1335. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  1336. rdt_ord2str:
  1337. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype);
  1338. rdt_str2ord:
  1339. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype);
  1340. end;
  1341. end;
  1342. begin
  1343. cloadnode:=tcgloadnode;
  1344. cassignmentnode:=tcgassignmentnode;
  1345. carrayconstructornode:=tcgarrayconstructornode;
  1346. crttinode:=tcgrttinode;
  1347. end.