ncgld.pas 41 KB

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