ncgld.pas 62 KB

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