ncgld.pas 41 KB

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