ncgld.pas 61 KB

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