ncgld.pas 45 KB

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