ncgld.pas 40 KB

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