ncgld.pas 43 KB

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