ncgld.pas 43 KB

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