ncgld.pas 43 KB

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