ncgld.pas 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  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) then
  305. begin
  306. { load vmt pointer }
  307. reference_reset_base(href,hregister,0);
  308. hregister:=cg.getaddressregister(exprasmlist);
  309. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  310. { load method address }
  311. reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
  312. hregister:=cg.getaddressregister(exprasmlist);
  313. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  314. { ... and store it }
  315. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  316. end
  317. else
  318. begin
  319. { load address of the function }
  320. reference_reset_symbol(href,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION),0);
  321. hregister:=cg.getaddressregister(exprasmlist);
  322. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  323. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  324. end;
  325. end
  326. else
  327. begin
  328. {!!!!! Be aware, work on virtual methods too }
  329. location.reference.symbol:=objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION);
  330. end;
  331. end;
  332. typedconstsym :
  333. location.reference.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
  334. labelsym :
  335. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  336. else internalerror(200510032);
  337. end;
  338. end;
  339. {*****************************************************************************
  340. SecondAssignment
  341. *****************************************************************************}
  342. procedure tcgassignmentnode.pass_2;
  343. var
  344. otlabel,hlabel,oflabel : tasmlabel;
  345. fputyp : tfloattype;
  346. href : treference;
  347. releaseright : boolean;
  348. len : aint;
  349. r:Tregister;
  350. begin
  351. location_reset(location,LOC_VOID,OS_NO);
  352. otlabel:=truelabel;
  353. oflabel:=falselabel;
  354. objectlibrary.getjumplabel(truelabel);
  355. objectlibrary.getjumplabel(falselabel);
  356. {
  357. in most cases we can process first the right node which contains
  358. the most complex code. Exceptions for this are:
  359. - result is in flags, loading left will then destroy the flags
  360. - result is a jump, loading left must be already done before the jump is made
  361. - result need reference count, when left points to a value used in
  362. right then decreasing the refcnt on left can possibly release
  363. the memory before right increased the refcnt, result is that an
  364. empty value is assigned
  365. - calln, call destroys most registers and is therefor 'complex'
  366. But not when the result is in the flags, then
  367. loading the left node afterwards can destroy the flags.
  368. }
  369. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  370. ((right.nodetype=calln) or
  371. (right.resulttype.def.needs_inittable) or
  372. (right.registersint>=left.registersint)) then
  373. begin
  374. secondpass(right);
  375. { increment source reference counter, this is
  376. useless for string constants}
  377. if (right.resulttype.def.needs_inittable) and
  378. (right.nodetype<>stringconstn) then
  379. begin
  380. location_force_mem(exprasmlist,right.location);
  381. location_get_data_ref(exprasmlist,right.location,href,false);
  382. cg.g_incrrefcount(exprasmlist,right.resulttype.def,href);
  383. end;
  384. if codegenerror then
  385. exit;
  386. if not(nf_concat_string in flags) then
  387. begin
  388. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  389. { can be false }
  390. secondpass(left);
  391. { decrement destination reference counter }
  392. if (left.resulttype.def.needs_inittable) then
  393. begin
  394. location_get_data_ref(exprasmlist,left.location,href,false);
  395. cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
  396. end;
  397. if codegenerror then
  398. exit;
  399. end;
  400. end
  401. else
  402. begin
  403. { calculate left sides }
  404. { don't do it yet if it's a crgister (JM) }
  405. if not(nf_concat_string in flags) then
  406. begin
  407. secondpass(left);
  408. { decrement destination reference counter }
  409. if (left.resulttype.def.needs_inittable) then
  410. begin
  411. location_get_data_ref(exprasmlist,left.location,href,false);
  412. cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
  413. end;
  414. if codegenerror then
  415. exit;
  416. end;
  417. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  418. { can be false }
  419. secondpass(right);
  420. { increment source reference counter, this is
  421. useless for string constants}
  422. if (right.resulttype.def.needs_inittable) and
  423. (right.nodetype<>stringconstn) then
  424. begin
  425. location_force_mem(exprasmlist,right.location);
  426. location_get_data_ref(exprasmlist,right.location,href,false);
  427. cg.g_incrrefcount(exprasmlist,right.resulttype.def,href);
  428. end;
  429. if codegenerror then
  430. exit;
  431. end;
  432. releaseright:=true;
  433. { optimize temp to temp copies }
  434. (* if (left.nodetype = temprefn) and
  435. { we may store certain temps in registers in the future, then this }
  436. { optimization will have to be adapted }
  437. (left.location.loc = LOC_REFERENCE) and
  438. (right.location.loc = LOC_REFERENCE) and
  439. tg.istemp(right.location.reference) and
  440. (tg.sizeoftemp(exprasmlist,right.location.reference) = tg.sizeoftemp(exprasmlist,left.location.reference)) then
  441. begin
  442. { in theory, we should also make sure the left temp type is }
  443. { already more or less of the same kind (ie. we must not }
  444. { assign an ansistring to a normaltemp). In practice, the }
  445. { assignment node will have already taken care of this for us }
  446. tcgtemprefnode(left).changelocation(right.location.reference);
  447. end
  448. { shortstring assignments are handled separately }
  449. else *)
  450. if is_shortstring(left.resulttype.def) then
  451. begin
  452. {
  453. we can get here only in the following situations
  454. for the right node:
  455. - empty constant string
  456. - char
  457. }
  458. { empty constant string }
  459. if (right.nodetype=stringconstn) and
  460. (tstringconstnode(right).len=0) then
  461. begin
  462. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  463. end
  464. { char loading }
  465. else if is_char(right.resulttype.def) then
  466. begin
  467. if right.nodetype=ordconstn then
  468. begin
  469. if (target_info.endian = endian_little) then
  470. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  471. left.location.reference)
  472. else
  473. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  474. left.location.reference);
  475. end
  476. else
  477. begin
  478. href:=left.location.reference;
  479. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  480. inc(href.offset,1);
  481. case right.location.loc of
  482. LOC_REGISTER,
  483. LOC_CREGISTER :
  484. begin
  485. r:=cg.makeregsize(exprasmlist,right.location.register,OS_8);
  486. cg.a_load_reg_ref(exprasmlist,OS_8,OS_8,r,href);
  487. end;
  488. LOC_REFERENCE,
  489. LOC_CREFERENCE :
  490. cg.a_load_ref_ref(exprasmlist,OS_8,OS_8,right.location.reference,href);
  491. else
  492. internalerror(200205111);
  493. end;
  494. end;
  495. end
  496. else
  497. internalerror(200204249);
  498. end
  499. else
  500. begin
  501. case right.location.loc of
  502. LOC_CONSTANT :
  503. begin
  504. {$ifndef cpu64bit}
  505. if right.location.size in [OS_64,OS_S64] then
  506. cg64.a_load64_const_loc(exprasmlist,right.location.value64,left.location)
  507. else
  508. {$endif cpu64bit}
  509. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  510. end;
  511. LOC_REFERENCE,
  512. LOC_CREFERENCE :
  513. begin
  514. case left.location.loc of
  515. LOC_REGISTER,
  516. LOC_CREGISTER :
  517. begin
  518. {$ifndef cpu64bit}
  519. if left.location.size in [OS_64,OS_S64] then
  520. cg64.a_load64_ref_reg(exprasmlist,right.location.reference,left.location.register64)
  521. else
  522. {$endif cpu64bit}
  523. cg.a_load_ref_reg(exprasmlist,right.location.size,left.location.size,right.location.reference,left.location.register);
  524. end;
  525. LOC_FPUREGISTER,
  526. LOC_CFPUREGISTER :
  527. begin
  528. cg.a_loadfpu_ref_reg(exprasmlist,
  529. right.location.size,
  530. right.location.reference,
  531. left.location.register);
  532. end;
  533. LOC_REFERENCE,
  534. LOC_CREFERENCE :
  535. begin
  536. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  537. { Use unaligned copy when the offset is not aligned }
  538. len:=left.resulttype.def.size;
  539. if (right.location.reference.offset mod sizeof(aint)<>0) or
  540. (left.location.reference.offset mod sizeof(aint)<>0) or
  541. (right.resulttype.def.alignment<sizeof(aint)) then
  542. cg.g_concatcopy_unaligned(exprasmlist,right.location.reference,left.location.reference,len)
  543. else
  544. cg.g_concatcopy(exprasmlist,right.location.reference,left.location.reference,len);
  545. end;
  546. LOC_MMREGISTER,
  547. LOC_CMMREGISTER:
  548. cg.a_loadmm_ref_reg(exprasmlist,
  549. right.location.size,
  550. left.location.size,
  551. right.location.reference,
  552. left.location.register,mms_movescalar);
  553. else
  554. internalerror(200203284);
  555. end;
  556. end;
  557. {$ifdef SUPPORT_MMX}
  558. LOC_CMMXREGISTER,
  559. LOC_MMXREGISTER:
  560. begin
  561. if left.location.loc=LOC_CMMXREGISTER then
  562. cg.a_loadmm_reg_reg(exprasmlist,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  563. else
  564. cg.a_loadmm_reg_ref(exprasmlist,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  565. end;
  566. {$endif SUPPORT_MMX}
  567. LOC_MMREGISTER,
  568. LOC_CMMREGISTER:
  569. begin
  570. if left.resulttype.def.deftype=arraydef then
  571. begin
  572. end
  573. else
  574. begin
  575. if left.location.loc=LOC_CMMREGISTER then
  576. cg.a_loadmm_reg_reg(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  577. else
  578. cg.a_loadmm_reg_ref(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  579. end;
  580. end;
  581. LOC_REGISTER,
  582. LOC_CREGISTER :
  583. begin
  584. {$ifndef cpu64bit}
  585. if left.location.size in [OS_64,OS_S64] then
  586. cg64.a_load64_reg_loc(exprasmlist,
  587. right.location.register64,left.location)
  588. else
  589. {$endif cpu64bit}
  590. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  591. end;
  592. LOC_FPUREGISTER,
  593. LOC_CFPUREGISTER :
  594. begin
  595. if (left.resulttype.def.deftype=floatdef) then
  596. fputyp:=tfloatdef(left.resulttype.def).typ
  597. else
  598. if (right.resulttype.def.deftype=floatdef) then
  599. fputyp:=tfloatdef(right.resulttype.def).typ
  600. else
  601. if (right.nodetype=typeconvn) and
  602. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  603. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  604. else
  605. fputyp:=s32real;
  606. { we can't do direct moves between fpu and mm registers }
  607. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  608. begin
  609. location_force_mmregscalar(exprasmlist,right.location,false);
  610. cg.a_loadmm_reg_reg(exprasmlist,
  611. tfloat2tcgsize[fputyp],tfloat2tcgsize[fputyp],
  612. right.location.register,left.location.register,mms_movescalar);
  613. end
  614. else
  615. cg.a_loadfpu_reg_loc(exprasmlist,
  616. tfloat2tcgsize[fputyp],
  617. right.location.register,left.location);
  618. end;
  619. LOC_JUMP :
  620. begin
  621. objectlibrary.getjumplabel(hlabel);
  622. cg.a_label(exprasmlist,truelabel);
  623. cg.a_load_const_loc(exprasmlist,1,left.location);
  624. cg.a_jmp_always(exprasmlist,hlabel);
  625. cg.a_label(exprasmlist,falselabel);
  626. cg.a_load_const_loc(exprasmlist,0,left.location);
  627. cg.a_label(exprasmlist,hlabel);
  628. end;
  629. {$ifdef cpuflags}
  630. LOC_FLAGS :
  631. begin
  632. {This can be a wordbool or longbool too, no?}
  633. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  634. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  635. else
  636. begin
  637. if not(left.location.loc = LOC_REFERENCE) then
  638. internalerror(200203273);
  639. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  640. end;
  641. end;
  642. {$endif cpuflags}
  643. end;
  644. end;
  645. if releaseright then
  646. location_freetemp(exprasmlist,right.location);
  647. truelabel:=otlabel;
  648. falselabel:=oflabel;
  649. end;
  650. {*****************************************************************************
  651. SecondArrayConstruct
  652. *****************************************************************************}
  653. const
  654. vtInteger = 0;
  655. vtBoolean = 1;
  656. vtChar = 2;
  657. vtExtended = 3;
  658. vtString = 4;
  659. vtPointer = 5;
  660. vtPChar = 6;
  661. vtObject = 7;
  662. vtClass = 8;
  663. vtWideChar = 9;
  664. vtPWideChar = 10;
  665. vtAnsiString32 = 11;
  666. vtCurrency = 12;
  667. vtVariant = 13;
  668. vtInterface = 14;
  669. vtWideString = 15;
  670. vtInt64 = 16;
  671. vtQWord = 17;
  672. vtAnsiString16 = 18;
  673. vtAnsiString64 = 19;
  674. procedure tcgarrayconstructornode.pass_2;
  675. var
  676. hp : tarrayconstructornode;
  677. href : treference;
  678. lt : tdef;
  679. vaddr : boolean;
  680. vtype : longint;
  681. freetemp,
  682. dovariant : boolean;
  683. elesize : longint;
  684. tmpreg : tregister;
  685. paraloc : tcgparalocation;
  686. begin
  687. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  688. if dovariant then
  689. elesize:=sizeof(aint)+sizeof(aint)
  690. else
  691. elesize:=tarraydef(resulttype.def).elesize;
  692. location_reset(location,LOC_CREFERENCE,OS_NO);
  693. fillchar(paraloc,sizeof(paraloc),0);
  694. { Allocate always a temp, also if no elements are required, to
  695. be sure that location is valid (PFV) }
  696. if tarraydef(resulttype.def).highrange=-1 then
  697. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  698. else
  699. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  700. href:=location.reference;
  701. { Process nodes in array constructor }
  702. hp:=self;
  703. while assigned(hp) do
  704. begin
  705. if assigned(hp.left) then
  706. begin
  707. freetemp:=true;
  708. secondpass(hp.left);
  709. if codegenerror then
  710. exit;
  711. { Move flags and jump in register }
  712. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  713. location_force_reg(exprasmlist,hp.left.location,def_cgsize(hp.left.resulttype.def),false);
  714. if dovariant then
  715. begin
  716. { find the correct vtype value }
  717. vtype:=$ff;
  718. vaddr:=false;
  719. lt:=hp.left.resulttype.def;
  720. case lt.deftype of
  721. enumdef,
  722. orddef :
  723. begin
  724. if is_64bit(lt) then
  725. begin
  726. case torddef(lt).typ of
  727. scurrency:
  728. vtype:=vtCurrency;
  729. s64bit:
  730. vtype:=vtInt64;
  731. u64bit:
  732. vtype:=vtQWord;
  733. end;
  734. freetemp:=false;
  735. vaddr:=true;
  736. end
  737. else if (lt.deftype=enumdef) or
  738. is_integer(lt) then
  739. vtype:=vtInteger
  740. else
  741. if is_boolean(lt) then
  742. vtype:=vtBoolean
  743. else
  744. if (lt.deftype=orddef) then
  745. begin
  746. case torddef(lt).typ of
  747. uchar:
  748. vtype:=vtChar;
  749. uwidechar:
  750. vtype:=vtWideChar;
  751. end;
  752. end;
  753. end;
  754. floatdef :
  755. begin
  756. if is_currency(lt) then
  757. vtype:=vtCurrency
  758. else
  759. vtype:=vtExtended;
  760. freetemp:=false;
  761. vaddr:=true;
  762. end;
  763. procvardef,
  764. pointerdef :
  765. begin
  766. if is_pchar(lt) then
  767. vtype:=vtPChar
  768. else if is_pwidechar(lt) then
  769. vtype:=vtPWideChar
  770. else
  771. vtype:=vtPointer;
  772. end;
  773. variantdef :
  774. begin
  775. vtype:=vtVariant;
  776. vaddr:=true;
  777. freetemp:=false;
  778. end;
  779. classrefdef :
  780. vtype:=vtClass;
  781. objectdef :
  782. if is_interface(lt) then
  783. vtype:=vtInterface
  784. { vtObject really means a class based on TObject }
  785. else if is_class(lt) then
  786. vtype:=vtObject
  787. else
  788. internalerror(200505171);
  789. stringdef :
  790. begin
  791. if is_shortstring(lt) then
  792. begin
  793. vtype:=vtString;
  794. vaddr:=true;
  795. freetemp:=false;
  796. end
  797. else
  798. if is_ansistring(lt) then
  799. begin
  800. vtype:=vtAnsiString;
  801. freetemp:=false;
  802. end
  803. else
  804. if is_widestring(lt) then
  805. begin
  806. vtype:=vtWideString;
  807. freetemp:=false;
  808. end;
  809. end;
  810. end;
  811. if vtype=$ff then
  812. internalerror(14357);
  813. { write changing field update href to the next element }
  814. inc(href.offset,sizeof(aint));
  815. if vaddr then
  816. begin
  817. location_force_mem(exprasmlist,hp.left.location);
  818. tmpreg:=cg.getaddressregister(exprasmlist);
  819. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  820. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  821. end
  822. else
  823. cg.a_load_loc_ref(exprasmlist,OS_ADDR,hp.left.location,href);
  824. { update href to the vtype field and write it }
  825. dec(href.offset,sizeof(aint));
  826. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  827. { goto next array element }
  828. inc(href.offset,sizeof(aint)*2);
  829. end
  830. else
  831. { normal array constructor of the same type }
  832. begin
  833. if resulttype.def.needs_inittable then
  834. freetemp:=false;
  835. case hp.left.location.loc of
  836. LOC_FPUREGISTER,
  837. LOC_CFPUREGISTER :
  838. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  839. LOC_REFERENCE,
  840. LOC_CREFERENCE :
  841. begin
  842. if is_shortstring(hp.left.resulttype.def) then
  843. cg.g_copyshortstring(exprasmlist,hp.left.location.reference,href,
  844. Tstringdef(hp.left.resulttype.def).len)
  845. else
  846. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize);
  847. end;
  848. else
  849. begin
  850. {$ifndef cpu64bit}
  851. if hp.left.location.size in [OS_64,OS_S64] then
  852. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  853. else
  854. {$endif cpu64bit}
  855. cg.a_load_loc_ref(exprasmlist,hp.left.location.size,hp.left.location,href);
  856. end;
  857. end;
  858. inc(href.offset,elesize);
  859. end;
  860. if freetemp then
  861. location_freetemp(exprasmlist,hp.left.location);
  862. end;
  863. { load next entry }
  864. hp:=tarrayconstructornode(hp.right);
  865. end;
  866. end;
  867. {*****************************************************************************
  868. SecondRTTI
  869. *****************************************************************************}
  870. procedure tcgrttinode.pass_2;
  871. begin
  872. location_reset(location,LOC_CREFERENCE,OS_NO);
  873. location.reference.symbol:=rttidef.get_rtti_label(rttitype);
  874. end;
  875. begin
  876. cloadnode:=tcgloadnode;
  877. cassignmentnode:=tcgassignmentnode;
  878. carrayconstructornode:=tcgarrayconstructornode;
  879. crttinode:=tcgrttinode;
  880. end.