ncgld.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  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. node,nld;
  23. type
  24. tcgloadnode = class(tloadnode)
  25. procedure pass_generate_code;override;
  26. procedure generate_picvaraccess;virtual;
  27. end;
  28. tcgassignmentnode = class(tassignmentnode)
  29. procedure pass_generate_code;override;
  30. end;
  31. tcgarrayconstructornode = class(tarrayconstructornode)
  32. procedure pass_generate_code;override;
  33. end;
  34. tcgrttinode = class(trttinode)
  35. procedure pass_generate_code;override;
  36. end;
  37. implementation
  38. uses
  39. cutils,
  40. systems,
  41. verbose,globtype,globals,
  42. symconst,symtype,symdef,symsym,defutil,paramgr,
  43. ncnv,ncon,nmem,nbas,ncgrtti,
  44. aasmbase,aasmtai,aasmdata,aasmcpu,
  45. cgbase,pass_2,
  46. procinfo,
  47. cpubase,parabase,
  48. tgobj,ncgutil,
  49. cgutils,cgobj,
  50. ncgbas,ncgflw;
  51. {*****************************************************************************
  52. SecondLoad
  53. *****************************************************************************}
  54. procedure tcgloadnode.generate_picvaraccess;
  55. begin
  56. {$ifndef sparc}
  57. location.reference.base:=current_procinfo.got;
  58. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname+'@GOT');
  59. {$endif sparc}
  60. end;
  61. procedure tcgloadnode.pass_generate_code;
  62. var
  63. hregister : tregister;
  64. vs : tabstractnormalvarsym;
  65. gvs : tstaticvarsym;
  66. pd : tprocdef;
  67. href : treference;
  68. newsize : tcgsize;
  69. endrelocatelab,
  70. norelocatelab : tasmlabel;
  71. paraloc1 : tcgpara;
  72. begin
  73. { we don't know the size of all arrays }
  74. newsize:=def_cgsize(resultdef);
  75. location_reset(location,LOC_REFERENCE,newsize);
  76. case symtableentry.typ of
  77. absolutevarsym :
  78. begin
  79. { this is only for toasm and toaddr }
  80. case tabsolutevarsym(symtableentry).abstyp of
  81. toaddr :
  82. begin
  83. {$ifdef i386}
  84. if tabsolutevarsym(symtableentry).absseg then
  85. location.reference.segment:=NR_FS;
  86. {$endif i386}
  87. location.reference.offset:=tabsolutevarsym(symtableentry).addroffset;
  88. end;
  89. toasm :
  90. location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
  91. else
  92. internalerror(200310283);
  93. end;
  94. end;
  95. constsym:
  96. begin
  97. if tconstsym(symtableentry).consttyp=constresourcestring then
  98. begin
  99. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  100. location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name));
  101. { Resourcestring layout:
  102. TResourceStringRecord = Packed Record
  103. Name,
  104. CurrentValue,
  105. DefaultValue : AnsiString;
  106. HashValue : LongWord;
  107. end;
  108. }
  109. location.reference.offset:=sizeof(aint);
  110. end
  111. else
  112. internalerror(22798);
  113. end;
  114. staticvarsym :
  115. begin
  116. gvs:=tstaticvarsym(symtableentry);
  117. if ([vo_is_dll_var,vo_is_external] * gvs.varoptions <> []) then
  118. begin
  119. location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tstaticvarsym(symtableentry).mangledname);
  120. if (location.reference.base <> NR_NO) then
  121. exit;
  122. end;
  123. if (vo_is_dll_var in gvs.varoptions) then
  124. { DLL variable }
  125. begin
  126. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  127. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
  128. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
  129. reference_reset_base(location.reference,hregister,0);
  130. end
  131. { Thread variable }
  132. else if (vo_is_thread_var in gvs.varoptions) and
  133. not(tf_section_threadvars in target_info.flags) then
  134. begin
  135. if (tf_section_threadvars in target_info.flags) then
  136. begin
  137. if gvs.localloc.loc=LOC_INVALID then
  138. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
  139. else
  140. location:=gvs.localloc;
  141. {$ifdef i386}
  142. case target_info.system of
  143. system_i386_linux:
  144. location.reference.segment:=NR_GS;
  145. system_i386_win32:
  146. location.reference.segment:=NR_FS;
  147. end;
  148. {$endif i386}
  149. end
  150. else
  151. begin
  152. {
  153. Thread var loading is optimized to first check if
  154. a relocate function is available. When the function
  155. is available it is called to retrieve the address.
  156. Otherwise the address is loaded with the symbol
  157. The code needs to be in the order to first handle the
  158. call and then the address load to be sure that the
  159. register that is used for returning is the same (PFV)
  160. }
  161. current_asmdata.getjumplabel(norelocatelab);
  162. current_asmdata.getjumplabel(endrelocatelab);
  163. { make sure hregister can't allocate the register necessary for the parameter }
  164. paraloc1.init;
  165. paramanager.getintparaloc(pocall_default,1,paraloc1);
  166. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  167. reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0);
  168. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  169. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
  170. { don't save the allocated register else the result will be destroyed later }
  171. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname),0);
  172. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  173. cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  174. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  175. paraloc1.done;
  176. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  177. cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
  178. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  179. cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  180. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  181. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  182. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  183. cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
  184. cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
  185. { no relocation needed, load the address of the variable only, the
  186. layout of a threadvar is (4 bytes pointer):
  187. 0 - Threadvar index
  188. 4 - Threadvar value in single threading }
  189. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname),sizeof(aint));
  190. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  191. cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
  192. location.reference.base:=hregister;
  193. end;
  194. end
  195. { Normal (or external) variable }
  196. else
  197. begin
  198. if gvs.localloc.loc=LOC_INVALID then
  199. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
  200. else
  201. location:=gvs.localloc;
  202. end;
  203. { make const a LOC_CREFERENCE }
  204. if (gvs.varspez=vs_const) and
  205. (location.loc=LOC_REFERENCE) then
  206. location.loc:=LOC_CREFERENCE;
  207. end;
  208. paravarsym,
  209. localvarsym :
  210. begin
  211. vs:=tabstractnormalvarsym(symtableentry);
  212. { Nested variable }
  213. if assigned(left) then
  214. begin
  215. secondpass(left);
  216. if left.location.loc<>LOC_REGISTER then
  217. internalerror(200309286);
  218. if vs.localloc.loc<>LOC_REFERENCE then
  219. internalerror(200409241);
  220. reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset);
  221. end
  222. else
  223. location:=vs.localloc;
  224. { handle call by reference variables when they are not
  225. alreayd copied to local copies. Also ignore the reference
  226. when we need to load the self pointer for objects }
  227. if is_addr_param_load then
  228. begin
  229. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  230. hregister:=location.register
  231. else
  232. begin
  233. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  234. { we need to load only an address }
  235. location.size:=OS_ADDR;
  236. cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
  237. end;
  238. location_reset(location,LOC_REFERENCE,newsize);
  239. location.reference.base:=hregister;
  240. end;
  241. { make const a LOC_CREFERENCE }
  242. if (vs.varspez=vs_const) and
  243. (location.loc=LOC_REFERENCE) then
  244. location.loc:=LOC_CREFERENCE;
  245. end;
  246. procsym:
  247. begin
  248. if not assigned(procdef) then
  249. internalerror(200312011);
  250. if assigned(left) then
  251. begin
  252. if (sizeof(aint) = 4) then
  253. location_reset(location,LOC_CREFERENCE,OS_64)
  254. else if (sizeof(aint) = 8) then
  255. location_reset(location,LOC_CREFERENCE,OS_128)
  256. else
  257. internalerror(20020520);
  258. tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(aint),tt_normal,location.reference);
  259. secondpass(left);
  260. { load class instance/classrefdef address }
  261. if left.location.loc=LOC_CONSTANT then
  262. location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
  263. case left.location.loc of
  264. LOC_CREGISTER,
  265. LOC_REGISTER:
  266. begin
  267. { this is not possible for objects }
  268. if is_object(left.resultdef) then
  269. internalerror(200304234);
  270. hregister:=left.location.register;
  271. end;
  272. LOC_CREFERENCE,
  273. LOC_REFERENCE:
  274. begin
  275. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  276. if not is_object(left.resultdef) then
  277. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  278. else
  279. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
  280. location_freetemp(current_asmdata.CurrAsmList,left.location);
  281. end;
  282. else
  283. internalerror(200610311);
  284. end;
  285. { store the class instance or classredef address }
  286. href:=location.reference;
  287. inc(href.offset,sizeof(aint));
  288. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
  289. { virtual method ? }
  290. if (po_virtualmethod in procdef.procoptions) and
  291. not(nf_inherited in flags) then
  292. begin
  293. { a classrefdef already points to the VMT }
  294. if (left.resultdef.typ<>classrefdef) then
  295. begin
  296. { load vmt pointer }
  297. reference_reset_base(href,hregister,0);
  298. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  299. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  300. end;
  301. { load method address }
  302. reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
  303. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  304. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  305. { ... and store it }
  306. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  307. end
  308. else
  309. begin
  310. { load address of the function }
  311. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0);
  312. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  313. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  314. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  315. end;
  316. end
  317. else
  318. begin
  319. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  320. if (po_external in pd.procoptions) then
  321. location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname);
  322. {!!!!! Be aware, work on virtual methods too }
  323. if (location.reference.base = NR_NO) then
  324. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname);
  325. end;
  326. end;
  327. labelsym :
  328. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  329. else internalerror(200510032);
  330. end;
  331. end;
  332. {*****************************************************************************
  333. SecondAssignment
  334. *****************************************************************************}
  335. procedure tcgassignmentnode.pass_generate_code;
  336. var
  337. otlabel,hlabel,oflabel : tasmlabel;
  338. href : treference;
  339. releaseright : boolean;
  340. len : aint;
  341. r:Tregister;
  342. begin
  343. location_reset(location,LOC_VOID,OS_NO);
  344. otlabel:=current_procinfo.CurrTrueLabel;
  345. oflabel:=current_procinfo.CurrFalseLabel;
  346. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  347. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  348. {
  349. in most cases we can process first the right node which contains
  350. the most complex code. Exceptions for this are:
  351. - result is in flags, loading left will then destroy the flags
  352. - result is a jump, loading left must be already done before the jump is made
  353. - result need reference count, when left points to a value used in
  354. right then decreasing the refcnt on left can possibly release
  355. the memory before right increased the refcnt, result is that an
  356. empty value is assigned
  357. - calln, call destroys most registers and is therefor 'complex'
  358. But not when the result is in the flags, then
  359. loading the left node afterwards can destroy the flags.
  360. }
  361. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  362. ((right.nodetype=calln) or
  363. (right.resultdef.needs_inittable) or
  364. (right.registersint>=left.registersint)) then
  365. begin
  366. secondpass(right);
  367. { increment source reference counter, this is
  368. useless for constants }
  369. if (right.resultdef.needs_inittable) and
  370. not is_constnode(right) then
  371. begin
  372. location_force_mem(current_asmdata.CurrAsmList,right.location);
  373. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  374. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  375. end;
  376. if codegenerror then
  377. exit;
  378. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  379. { can be false }
  380. secondpass(left);
  381. { decrement destination reference counter }
  382. if (left.resultdef.needs_inittable) then
  383. begin
  384. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  385. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  386. end;
  387. if codegenerror then
  388. exit;
  389. end
  390. else
  391. begin
  392. { calculate left sides }
  393. secondpass(left);
  394. { decrement destination reference counter }
  395. if (left.resultdef.needs_inittable) then
  396. begin
  397. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  398. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  399. end;
  400. if codegenerror then
  401. exit;
  402. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  403. { can be false }
  404. secondpass(right);
  405. { increment source reference counter, this is
  406. useless for string constants}
  407. if (right.resultdef.needs_inittable) and
  408. (right.nodetype<>stringconstn) then
  409. begin
  410. location_force_mem(current_asmdata.CurrAsmList,right.location);
  411. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  412. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  413. end;
  414. if codegenerror then
  415. exit;
  416. end;
  417. releaseright:=true;
  418. { optimize temp to temp copies }
  419. {$ifdef old_append_str}
  420. if (left.nodetype = temprefn) and
  421. { we may store certain temps in registers in the future, then this }
  422. { optimization will have to be adapted }
  423. (left.location.loc = LOC_REFERENCE) and
  424. (right.location.loc = LOC_REFERENCE) and
  425. tg.istemp(right.location.reference) and
  426. (tg.sizeoftemp(current_asmdata.CurrAsmList,right.location.reference) = tg.sizeoftemp(current_asmdata.CurrAsmList,left.location.reference)) then
  427. begin
  428. { in theory, we should also make sure the left temp type is }
  429. { already more or less of the same kind (ie. we must not }
  430. { assign an ansistring to a normaltemp). In practice, the }
  431. { assignment node will have already taken care of this for us }
  432. tcgtemprefnode(left).changelocation(right.location.reference);
  433. end
  434. { shortstring assignments are handled separately }
  435. else
  436. {$endif old_append_str}
  437. if is_shortstring(left.resultdef) then
  438. begin
  439. {
  440. we can get here only in the following situations
  441. for the right node:
  442. - empty constant string
  443. - char
  444. }
  445. { The addn is replaced by a blockn or calln that already returns
  446. a shortstring }
  447. if is_shortstring(right.resultdef) and
  448. (right.nodetype in [blockn,calln]) then
  449. begin
  450. { nothing to do }
  451. end
  452. { empty constant string }
  453. else if (right.nodetype=stringconstn) and
  454. (tstringconstnode(right).len=0) then
  455. begin
  456. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,0,left.location.reference);
  457. end
  458. { char loading }
  459. else if is_char(right.resultdef) then
  460. begin
  461. if right.nodetype=ordconstn then
  462. begin
  463. if (target_info.endian = endian_little) then
  464. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,(tordconstnode(right).value shl 8) or 1,
  465. setalignment(left.location.reference,1))
  466. else
  467. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,tordconstnode(right).value or (1 shl 8),
  468. setalignment(left.location.reference,1));
  469. end
  470. else
  471. begin
  472. href:=left.location.reference;
  473. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,1,href);
  474. inc(href.offset,1);
  475. case right.location.loc of
  476. LOC_REGISTER,
  477. LOC_CREGISTER :
  478. begin
  479. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  480. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,r,href);
  481. end;
  482. LOC_REFERENCE,
  483. LOC_CREFERENCE :
  484. cg.a_load_ref_ref(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,href);
  485. else
  486. internalerror(200205111);
  487. end;
  488. end;
  489. end
  490. else
  491. internalerror(200204249);
  492. end
  493. else
  494. begin
  495. { SSA support }
  496. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
  497. maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
  498. case right.location.loc of
  499. LOC_CONSTANT :
  500. begin
  501. {$ifndef cpu64bit}
  502. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  503. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  504. else
  505. {$endif cpu64bit}
  506. cg.a_load_const_loc(current_asmdata.CurrAsmList,right.location.value,left.location);
  507. end;
  508. LOC_REFERENCE,
  509. LOC_CREFERENCE :
  510. begin
  511. case left.location.loc of
  512. LOC_REGISTER,
  513. LOC_CREGISTER :
  514. begin
  515. {$ifndef cpu64bit}
  516. if left.location.size in [OS_64,OS_S64] then
  517. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  518. else
  519. {$endif cpu64bit}
  520. cg.a_load_ref_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.register);
  521. end;
  522. LOC_FPUREGISTER,
  523. LOC_CFPUREGISTER :
  524. begin
  525. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  526. right.location.size,left.location.size,
  527. right.location.reference,
  528. left.location.register);
  529. end;
  530. LOC_REFERENCE,
  531. LOC_CREFERENCE :
  532. begin
  533. if (left.resultdef.typ=floatdef) and
  534. (right.resultdef.typ=floatdef) and
  535. (left.location.size<>right.location.size) then
  536. begin
  537. cg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  538. right.location.size,left.location.size,
  539. right.location.reference,left.location.reference)
  540. end
  541. else
  542. begin
  543. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  544. { Use unaligned copy when the offset is not aligned }
  545. len:=left.resultdef.size;
  546. if (right.location.reference.offset mod sizeof(aint)<>0) or
  547. (left.location.reference.offset mod sizeof(aint)<>0) or
  548. (right.resultdef.alignment<sizeof(aint)) or
  549. ((right.location.reference.alignment<>0) and
  550. (right.location.reference.alignment<sizeof(aint))) or
  551. ((left.location.reference.alignment<>0) and
  552. (left.location.reference.alignment<sizeof(aint))) then
  553. cg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len)
  554. else
  555. cg.g_concatcopy(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len);
  556. end;
  557. end;
  558. LOC_MMREGISTER,
  559. LOC_CMMREGISTER:
  560. begin
  561. {$ifdef x86}
  562. if not use_sse(right.resultdef) then
  563. begin
  564. { perform size conversion if needed (the mm-code cannot }
  565. { convert an extended into a double/single, since sse }
  566. { doesn't support extended) }
  567. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  568. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  569. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  570. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  571. if releaseright then
  572. location_freetemp(current_asmdata.CurrAsmList,right.location);
  573. releaseright:=true;
  574. location_reset(right.location,LOC_REFERENCE,left.location.size);
  575. right.location.reference:=href;
  576. end;
  577. {$endif}
  578. cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  579. right.location.size,
  580. left.location.size,
  581. right.location.reference,
  582. left.location.register,mms_movescalar);
  583. end;
  584. LOC_SUBSETREG,
  585. LOC_CSUBSETREG:
  586. cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
  587. LOC_SUBSETREF,
  588. LOC_CSUBSETREF:
  589. {$ifndef cpu64bit}
  590. if right.location.size in [OS_64,OS_S64] then
  591. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  592. else
  593. {$endif cpu64bit}
  594. cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
  595. else
  596. internalerror(200203284);
  597. end;
  598. end;
  599. {$ifdef SUPPORT_MMX}
  600. LOC_CMMXREGISTER,
  601. LOC_MMXREGISTER:
  602. begin
  603. if left.location.loc=LOC_CMMXREGISTER then
  604. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  605. else
  606. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  607. end;
  608. {$endif SUPPORT_MMX}
  609. LOC_MMREGISTER,
  610. LOC_CMMREGISTER:
  611. begin
  612. if left.resultdef.typ=arraydef then
  613. begin
  614. end
  615. else
  616. begin
  617. if left.location.loc=LOC_CMMREGISTER then
  618. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  619. else
  620. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  621. end;
  622. end;
  623. LOC_REGISTER,
  624. LOC_CREGISTER :
  625. begin
  626. {$ifndef cpu64bit}
  627. if left.location.size in [OS_64,OS_S64] then
  628. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  629. right.location.register64,left.location)
  630. else
  631. {$endif cpu64bit}
  632. cg.a_load_reg_loc(current_asmdata.CurrAsmList,right.location.size,right.location.register,left.location);
  633. end;
  634. LOC_FPUREGISTER,
  635. LOC_CFPUREGISTER :
  636. begin
  637. { we can't do direct moves between fpu and mm registers }
  638. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  639. begin
  640. {$ifdef x86}
  641. if not use_sse(right.resultdef) then
  642. begin
  643. { perform size conversion if needed (the mm-code cannot convert an }
  644. { extended into a double/single, since sse doesn't support extended) }
  645. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  646. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  647. location_reset(right.location,LOC_REFERENCE,left.location.size);
  648. right.location.reference:=href;
  649. end;
  650. {$endif}
  651. location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
  652. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  653. right.location.size,left.location.size,
  654. right.location.register,left.location.register,mms_movescalar);
  655. end
  656. else
  657. cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  658. right.location.size,
  659. right.location.register,left.location);
  660. end;
  661. LOC_SUBSETREG,
  662. LOC_CSUBSETREG:
  663. begin
  664. cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  665. right.location.size,right.location.sreg,left.location);
  666. end;
  667. LOC_SUBSETREF,
  668. LOC_CSUBSETREF:
  669. begin
  670. {$ifndef cpu64bit}
  671. if right.location.size in [OS_64,OS_S64] then
  672. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  673. else
  674. {$endif cpu64bit}
  675. cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  676. right.location.size,right.location.sref,left.location);
  677. end;
  678. LOC_JUMP :
  679. begin
  680. current_asmdata.getjumplabel(hlabel);
  681. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  682. cg.a_load_const_loc(current_asmdata.CurrAsmList,1,left.location);
  683. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  684. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  685. cg.a_load_const_loc(current_asmdata.CurrAsmList,0,left.location);
  686. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  687. end;
  688. {$ifdef cpuflags}
  689. LOC_FLAGS :
  690. begin
  691. {This can be a wordbool or longbool too, no?}
  692. case left.location.loc of
  693. LOC_REGISTER,LOC_CREGISTER:
  694. cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,left.location.register);
  695. LOC_REFERENCE:
  696. cg.g_flags2ref(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,left.location.reference);
  697. LOC_SUBSETREG,LOC_SUBSETREF:
  698. begin
  699. r:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(left.resultdef));
  700. cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,r);
  701. cg.a_load_reg_loc(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),r,left.location);
  702. end;
  703. else
  704. internalerror(200203273);
  705. end;
  706. end;
  707. {$endif cpuflags}
  708. end;
  709. end;
  710. if releaseright then
  711. location_freetemp(current_asmdata.CurrAsmList,right.location);
  712. current_procinfo.CurrTrueLabel:=otlabel;
  713. current_procinfo.CurrFalseLabel:=oflabel;
  714. end;
  715. {*****************************************************************************
  716. SecondArrayConstruct
  717. *****************************************************************************}
  718. const
  719. vtInteger = 0;
  720. vtBoolean = 1;
  721. vtChar = 2;
  722. vtExtended = 3;
  723. vtString = 4;
  724. vtPointer = 5;
  725. vtPChar = 6;
  726. vtObject = 7;
  727. vtClass = 8;
  728. vtWideChar = 9;
  729. vtPWideChar = 10;
  730. vtAnsiString32 = 11;
  731. vtCurrency = 12;
  732. vtVariant = 13;
  733. vtInterface = 14;
  734. vtWideString = 15;
  735. vtInt64 = 16;
  736. vtQWord = 17;
  737. vtAnsiString16 = 18;
  738. vtAnsiString64 = 19;
  739. procedure tcgarrayconstructornode.pass_generate_code;
  740. var
  741. hp : tarrayconstructornode;
  742. href : treference;
  743. lt : tdef;
  744. vaddr : boolean;
  745. vtype : longint;
  746. freetemp,
  747. dovariant : boolean;
  748. elesize : longint;
  749. tmpreg : tregister;
  750. paraloc : tcgparalocation;
  751. otlabel,
  752. oflabel : tasmlabel;
  753. begin
  754. if is_packed_array(resultdef) then
  755. internalerror(200608042);
  756. dovariant:=(nf_forcevaria in flags) or is_variant_array(resultdef);
  757. if dovariant then
  758. elesize:=sizeof(aint)+sizeof(aint)
  759. else
  760. elesize:=tarraydef(resultdef).elesize;
  761. location_reset(location,LOC_CREFERENCE,OS_NO);
  762. fillchar(paraloc,sizeof(paraloc),0);
  763. { Allocate always a temp, also if no elements are required, to
  764. be sure that location is valid (PFV) }
  765. if tarraydef(resultdef).highrange=-1 then
  766. tg.GetTemp(current_asmdata.CurrAsmList,elesize,tt_normal,location.reference)
  767. else
  768. tg.GetTemp(current_asmdata.CurrAsmList,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  769. href:=location.reference;
  770. { Process nodes in array constructor }
  771. hp:=self;
  772. while assigned(hp) do
  773. begin
  774. if assigned(hp.left) then
  775. begin
  776. freetemp:=true;
  777. if (hp.left.expectloc=LOC_JUMP) then
  778. begin
  779. otlabel:=current_procinfo.CurrTrueLabel;
  780. oflabel:=current_procinfo.CurrFalseLabel;
  781. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  782. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  783. end;
  784. secondpass(hp.left);
  785. { Move flags and jump in register }
  786. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  787. location_force_reg(current_asmdata.CurrAsmList,hp.left.location,def_cgsize(hp.left.resultdef),false);
  788. if (hp.left.location.loc=LOC_JUMP) then
  789. begin
  790. if (hp.left.expectloc<>LOC_JUMP) then
  791. internalerror(2007103101);
  792. current_procinfo.CurrTrueLabel:=otlabel;
  793. current_procinfo.CurrFalseLabel:=oflabel;
  794. end;
  795. if dovariant then
  796. begin
  797. { find the correct vtype value }
  798. vtype:=$ff;
  799. vaddr:=false;
  800. lt:=hp.left.resultdef;
  801. case lt.typ of
  802. enumdef,
  803. orddef :
  804. begin
  805. if is_64bit(lt) then
  806. begin
  807. case torddef(lt).ordtype of
  808. scurrency:
  809. vtype:=vtCurrency;
  810. s64bit:
  811. vtype:=vtInt64;
  812. u64bit:
  813. vtype:=vtQWord;
  814. end;
  815. freetemp:=false;
  816. vaddr:=true;
  817. end
  818. else if (lt.typ=enumdef) or
  819. is_integer(lt) then
  820. vtype:=vtInteger
  821. else
  822. if is_boolean(lt) then
  823. vtype:=vtBoolean
  824. else
  825. if (lt.typ=orddef) then
  826. begin
  827. case torddef(lt).ordtype of
  828. uchar:
  829. vtype:=vtChar;
  830. uwidechar:
  831. vtype:=vtWideChar;
  832. end;
  833. end;
  834. end;
  835. floatdef :
  836. begin
  837. if is_currency(lt) then
  838. vtype:=vtCurrency
  839. else
  840. vtype:=vtExtended;
  841. freetemp:=false;
  842. vaddr:=true;
  843. end;
  844. procvardef,
  845. pointerdef :
  846. begin
  847. if is_pchar(lt) then
  848. vtype:=vtPChar
  849. else if is_pwidechar(lt) then
  850. vtype:=vtPWideChar
  851. else
  852. vtype:=vtPointer;
  853. end;
  854. variantdef :
  855. begin
  856. vtype:=vtVariant;
  857. vaddr:=true;
  858. freetemp:=false;
  859. end;
  860. classrefdef :
  861. vtype:=vtClass;
  862. objectdef :
  863. if is_interface(lt) then
  864. vtype:=vtInterface
  865. { vtObject really means a class based on TObject }
  866. else if is_class(lt) then
  867. vtype:=vtObject
  868. else
  869. internalerror(200505171);
  870. stringdef :
  871. begin
  872. if is_shortstring(lt) then
  873. begin
  874. vtype:=vtString;
  875. vaddr:=true;
  876. freetemp:=false;
  877. end
  878. else
  879. if is_ansistring(lt) then
  880. begin
  881. vtype:=vtAnsiString;
  882. freetemp:=false;
  883. end
  884. else
  885. if is_widestring(lt) then
  886. begin
  887. vtype:=vtWideString;
  888. freetemp:=false;
  889. end;
  890. end;
  891. end;
  892. if vtype=$ff then
  893. internalerror(14357);
  894. { write changing field update href to the next element }
  895. inc(href.offset,sizeof(aint));
  896. if vaddr then
  897. begin
  898. location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
  899. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  900. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  901. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  902. end
  903. else
  904. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
  905. { update href to the vtype field and write it }
  906. dec(href.offset,sizeof(aint));
  907. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  908. { goto next array element }
  909. inc(href.offset,sizeof(aint)*2);
  910. end
  911. else
  912. { normal array constructor of the same type }
  913. begin
  914. if resultdef.needs_inittable then
  915. freetemp:=false;
  916. case hp.left.location.loc of
  917. LOC_MMREGISTER,
  918. LOC_CMMREGISTER:
  919. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
  920. hp.left.location.register,href,mms_movescalar);
  921. LOC_FPUREGISTER,
  922. LOC_CFPUREGISTER :
  923. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,hp.left.location.register,href);
  924. LOC_REFERENCE,
  925. LOC_CREFERENCE :
  926. begin
  927. if is_shortstring(hp.left.resultdef) then
  928. cg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  929. Tstringdef(hp.left.resultdef).len)
  930. else
  931. cg.g_concatcopy(current_asmdata.CurrAsmList,hp.left.location.reference,href,elesize);
  932. end;
  933. else
  934. begin
  935. {$ifndef cpu64bit}
  936. if hp.left.location.size in [OS_64,OS_S64] then
  937. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  938. else
  939. {$endif cpu64bit}
  940. cg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location,href);
  941. end;
  942. end;
  943. inc(href.offset,elesize);
  944. end;
  945. if freetemp then
  946. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  947. end;
  948. { load next entry }
  949. hp:=tarrayconstructornode(hp.right);
  950. end;
  951. end;
  952. {*****************************************************************************
  953. SecondRTTI
  954. *****************************************************************************}
  955. procedure tcgrttinode.pass_generate_code;
  956. begin
  957. location_reset(location,LOC_CREFERENCE,OS_NO);
  958. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  959. end;
  960. begin
  961. cloadnode:=tcgloadnode;
  962. cassignmentnode:=tcgassignmentnode;
  963. carrayconstructornode:=tcgarrayconstructornode;
  964. crttinode:=tcgrttinode;
  965. end.