ncgld.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  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.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  155. cg.a_call_reg(exprasmlist,hregister);
  156. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  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. else
  557. internalerror(200203284);
  558. end;
  559. end;
  560. {$ifdef SUPPORT_MMX}
  561. LOC_CMMXREGISTER,
  562. LOC_MMXREGISTER:
  563. begin
  564. if left.location.loc=LOC_CMMXREGISTER then
  565. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  566. else
  567. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  568. end;
  569. {$endif SUPPORT_MMX}
  570. LOC_MMREGISTER,
  571. LOC_CMMREGISTER:
  572. begin
  573. if left.resulttype.def.deftype=arraydef then
  574. begin
  575. end
  576. else
  577. begin
  578. if left.location.loc=LOC_CMMREGISTER then
  579. cg.a_loadmm_reg_reg(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  580. else
  581. cg.a_loadmm_reg_ref(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  582. end;
  583. end;
  584. LOC_REGISTER,
  585. LOC_CREGISTER :
  586. begin
  587. {$ifndef cpu64bit}
  588. if left.location.size in [OS_64,OS_S64] then
  589. cg64.a_load64_reg_loc(exprasmlist,
  590. right.location.register64,left.location)
  591. else
  592. {$endif cpu64bit}
  593. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  594. end;
  595. LOC_FPUREGISTER,
  596. LOC_CFPUREGISTER :
  597. begin
  598. if (left.resulttype.def.deftype=floatdef) then
  599. fputyp:=tfloatdef(left.resulttype.def).typ
  600. else
  601. if (right.resulttype.def.deftype=floatdef) then
  602. fputyp:=tfloatdef(right.resulttype.def).typ
  603. else
  604. if (right.nodetype=typeconvn) and
  605. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  606. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  607. else
  608. fputyp:=s32real;
  609. cg.a_loadfpu_reg_loc(exprasmlist,
  610. tfloat2tcgsize[fputyp],
  611. right.location.register,left.location);
  612. end;
  613. LOC_JUMP :
  614. begin
  615. objectlibrary.getlabel(hlabel);
  616. cg.a_label(exprasmlist,truelabel);
  617. cg.a_load_const_loc(exprasmlist,1,left.location);
  618. cg.a_jmp_always(exprasmlist,hlabel);
  619. cg.a_label(exprasmlist,falselabel);
  620. cg.a_load_const_loc(exprasmlist,0,left.location);
  621. cg.a_label(exprasmlist,hlabel);
  622. end;
  623. {$ifdef cpuflags}
  624. LOC_FLAGS :
  625. begin
  626. {This can be a wordbool or longbool too, no?}
  627. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  628. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  629. else
  630. begin
  631. if not(left.location.loc = LOC_REFERENCE) then
  632. internalerror(200203273);
  633. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  634. end;
  635. end;
  636. {$endif cpuflags}
  637. end;
  638. end;
  639. if releaseright then
  640. location_freetemp(exprasmlist,right.location);
  641. truelabel:=otlabel;
  642. falselabel:=oflabel;
  643. end;
  644. {*****************************************************************************
  645. SecondArrayConstruct
  646. *****************************************************************************}
  647. const
  648. vtInteger = 0;
  649. vtBoolean = 1;
  650. vtChar = 2;
  651. vtExtended = 3;
  652. vtString = 4;
  653. vtPointer = 5;
  654. vtPChar = 6;
  655. vtObject = 7;
  656. vtClass = 8;
  657. vtWideChar = 9;
  658. vtPWideChar = 10;
  659. vtAnsiString32 = 11;
  660. vtCurrency = 12;
  661. vtVariant = 13;
  662. vtInterface = 14;
  663. vtWideString = 15;
  664. vtInt64 = 16;
  665. vtQWord = 17;
  666. vtAnsiString16 = 18;
  667. vtAnsiString64 = 19;
  668. procedure tcgarrayconstructornode.pass_2;
  669. var
  670. hp : tarrayconstructornode;
  671. href : treference;
  672. lt : tdef;
  673. vaddr : boolean;
  674. vtype : longint;
  675. freetemp,
  676. dovariant : boolean;
  677. elesize : longint;
  678. tmpreg : tregister;
  679. paraloc : tcgparalocation;
  680. begin
  681. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  682. if dovariant then
  683. elesize:=sizeof(aint)+sizeof(aint)
  684. else
  685. elesize:=tarraydef(resulttype.def).elesize;
  686. location_reset(location,LOC_CREFERENCE,OS_NO);
  687. fillchar(paraloc,sizeof(paraloc),0);
  688. { Allocate always a temp, also if no elements are required, to
  689. be sure that location is valid (PFV) }
  690. if tarraydef(resulttype.def).highrange=-1 then
  691. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  692. else
  693. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  694. href:=location.reference;
  695. { Process nodes in array constructor }
  696. hp:=self;
  697. while assigned(hp) do
  698. begin
  699. if assigned(hp.left) then
  700. begin
  701. freetemp:=true;
  702. secondpass(hp.left);
  703. if codegenerror then
  704. exit;
  705. { Move flags and jump in register }
  706. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  707. location_force_reg(exprasmlist,hp.left.location,def_cgsize(hp.left.resulttype.def),false);
  708. if dovariant then
  709. begin
  710. { find the correct vtype value }
  711. vtype:=$ff;
  712. vaddr:=false;
  713. lt:=hp.left.resulttype.def;
  714. case lt.deftype of
  715. enumdef,
  716. orddef :
  717. begin
  718. if is_64bit(lt) then
  719. begin
  720. case torddef(lt).typ of
  721. s64bit:
  722. vtype:=vtInt64;
  723. u64bit:
  724. vtype:=vtQWord;
  725. end;
  726. freetemp:=false;
  727. vaddr:=true;
  728. end
  729. else if (lt.deftype=enumdef) or
  730. is_integer(lt) then
  731. vtype:=vtInteger
  732. else
  733. if is_boolean(lt) then
  734. vtype:=vtBoolean
  735. else
  736. if (lt.deftype=orddef) then
  737. begin
  738. case torddef(lt).typ of
  739. uchar:
  740. vtype:=vtChar;
  741. uwidechar:
  742. vtype:=vtWideChar;
  743. end;
  744. end;
  745. end;
  746. floatdef :
  747. begin
  748. if is_currency(lt) then
  749. vtype:=vtCurrency
  750. else
  751. vtype:=vtExtended;
  752. freetemp:=false;
  753. vaddr:=true;
  754. end;
  755. procvardef,
  756. pointerdef :
  757. begin
  758. if is_pchar(lt) then
  759. vtype:=vtPChar
  760. else if is_pwidechar(lt) then
  761. vtype:=vtPWideChar
  762. else
  763. vtype:=vtPointer;
  764. end;
  765. variantdef :
  766. begin
  767. vtype:=vtVariant;
  768. vaddr:=true;
  769. freetemp:=false;
  770. end;
  771. classrefdef :
  772. vtype:=vtClass;
  773. objectdef :
  774. if is_interface(lt) then
  775. vtype:=vtInterface
  776. { vtObject really means a class based on TObject }
  777. else if is_class(lt) then
  778. vtype:=vtObject
  779. else
  780. internalerror(200505171);
  781. stringdef :
  782. begin
  783. if is_shortstring(lt) then
  784. begin
  785. vtype:=vtString;
  786. vaddr:=true;
  787. freetemp:=false;
  788. end
  789. else
  790. if is_ansistring(lt) then
  791. {$ifdef ansistring_bits}
  792. begin
  793. case Tstringdef(lt).string_typ of
  794. st_ansistring16:
  795. vtype:=vtAnsiString16;
  796. st_ansistring32:
  797. vtype:=vtAnsiString32;
  798. st_ansistring64:
  799. vtype:=vtAnsiString64;
  800. end;
  801. freetemp:=false;
  802. end
  803. {$else}
  804. begin
  805. vtype:=vtAnsiString;
  806. freetemp:=false;
  807. end
  808. {$endif}
  809. else
  810. if is_widestring(lt) then
  811. begin
  812. vtype:=vtWideString;
  813. freetemp:=false;
  814. end;
  815. end;
  816. end;
  817. if vtype=$ff then
  818. internalerror(14357);
  819. { write changing field update href to the next element }
  820. inc(href.offset,sizeof(aint));
  821. if vaddr then
  822. begin
  823. location_force_mem(exprasmlist,hp.left.location);
  824. tmpreg:=cg.getaddressregister(exprasmlist);
  825. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  826. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  827. end
  828. else
  829. cg.a_load_loc_ref(exprasmlist,OS_ADDR,hp.left.location,href);
  830. { update href to the vtype field and write it }
  831. dec(href.offset,sizeof(aint));
  832. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  833. { goto next array element }
  834. inc(href.offset,sizeof(aint)*2);
  835. end
  836. else
  837. { normal array constructor of the same type }
  838. begin
  839. if (is_ansistring(left.resulttype.def) or
  840. is_widestring(left.resulttype.def) or
  841. (left.resulttype.def.deftype=variantdef)) then
  842. freetemp:=false;
  843. case hp.left.location.loc of
  844. LOC_FPUREGISTER,
  845. LOC_CFPUREGISTER :
  846. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  847. LOC_REFERENCE,
  848. LOC_CREFERENCE :
  849. begin
  850. if is_shortstring(hp.left.resulttype.def) then
  851. cg.g_copyshortstring(exprasmlist,hp.left.location.reference,href,
  852. Tstringdef(hp.left.resulttype.def).len)
  853. else
  854. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize);
  855. end;
  856. else
  857. begin
  858. {$ifndef cpu64bit}
  859. if hp.left.location.size in [OS_64,OS_S64] then
  860. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  861. else
  862. {$endif cpu64bit}
  863. cg.a_load_loc_ref(exprasmlist,hp.left.location.size,hp.left.location,href);
  864. end;
  865. end;
  866. inc(href.offset,elesize);
  867. end;
  868. if freetemp then
  869. location_freetemp(exprasmlist,hp.left.location);
  870. end;
  871. { load next entry }
  872. hp:=tarrayconstructornode(hp.right);
  873. end;
  874. end;
  875. {*****************************************************************************
  876. SecondRTTI
  877. *****************************************************************************}
  878. procedure tcgrttinode.pass_2;
  879. begin
  880. location_reset(location,LOC_CREFERENCE,OS_NO);
  881. location.reference.symbol:=rttidef.get_rtti_label(rttitype);
  882. end;
  883. begin
  884. cloadnode:=tcgloadnode;
  885. cassignmentnode:=tcgassignmentnode;
  886. carrayconstructornode:=tcgarrayconstructornode;
  887. crttinode:=tcgrttinode;
  888. end.