ncgld.pas 40 KB

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