2
0

ncgld.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for nodes that handle loads and assignments which
  4. are the same for all (most) processors
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgld;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nld;
  23. type
  24. tcgloadnode = class(tloadnode)
  25. procedure pass_2;override;
  26. procedure generate_picvaraccess;virtual;
  27. end;
  28. tcgassignmentnode = class(tassignmentnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgarrayconstructornode = class(tarrayconstructornode)
  32. procedure pass_2;override;
  33. end;
  34. tcgrttinode = class(trttinode)
  35. procedure pass_2;override;
  36. end;
  37. implementation
  38. uses
  39. cutils,
  40. systems,
  41. verbose,globtype,globals,
  42. symconst,symtype,symdef,symsym,defutil,paramgr,
  43. ncnv,ncon,nmem,nbas,
  44. aasmbase,aasmtai,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_2;
  62. var
  63. hregister : tregister;
  64. symtabletype : tsymtabletype;
  65. href : treference;
  66. newsize : tcgsize;
  67. endrelocatelab,
  68. norelocatelab : tasmlabel;
  69. paraloc1 : tcgpara;
  70. begin
  71. { we don't know the size of all arrays }
  72. newsize:=def_cgsize(resulttype.def);
  73. location_reset(location,LOC_REFERENCE,newsize);
  74. case symtableentry.typ of
  75. absolutevarsym :
  76. begin
  77. { this is only for toasm and toaddr }
  78. case tabsolutevarsym(symtableentry).abstyp of
  79. toaddr :
  80. begin
  81. {$ifdef i386}
  82. if tabsolutevarsym(symtableentry).absseg then
  83. location.reference.segment:=NR_FS;
  84. {$endif i386}
  85. location.reference.offset:=tabsolutevarsym(symtableentry).addroffset;
  86. end;
  87. toasm :
  88. location.reference.symbol:=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(resulttype.def));
  203. location.register:=tvarsym(symtableentry).localloc.register;
  204. end;
  205. R_INTREGISTER :
  206. begin
  207. location_reset(location,LOC_CREGISTER,def_cgsize(resulttype.def));
  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. {
  277. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  278. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  279. CONSISTS OF TWO OS_ADDR, so you cannot set it
  280. to OS_64 - how to solve?? Carl
  281. Solved. Florian
  282. }
  283. if (sizeof(aint) = 4) then
  284. location_reset(location,LOC_CREFERENCE,OS_64)
  285. else if (sizeof(aint) = 8) then
  286. location_reset(location,LOC_CREFERENCE,OS_128)
  287. else
  288. internalerror(20020520);
  289. tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(aint),tt_normal,location.reference);
  290. secondpass(left);
  291. { load class instance address }
  292. case left.location.loc of
  293. LOC_CREGISTER,
  294. LOC_REGISTER:
  295. begin
  296. { this is not possible for objects }
  297. if is_object(left.resulttype.def) then
  298. internalerror(200304234);
  299. hregister:=left.location.register;
  300. end;
  301. LOC_CREFERENCE,
  302. LOC_REFERENCE:
  303. begin
  304. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  305. if is_class_or_interface(left.resulttype.def) then
  306. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  307. else
  308. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
  309. location_freetemp(current_asmdata.CurrAsmList,left.location);
  310. end;
  311. else
  312. internalerror(26019);
  313. end;
  314. { store the class instance address }
  315. href:=location.reference;
  316. inc(href.offset,sizeof(aint));
  317. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
  318. { virtual method ? }
  319. if (po_virtualmethod in procdef.procoptions) and
  320. not(nf_inherited in flags) then
  321. begin
  322. { load vmt pointer }
  323. reference_reset_base(href,hregister,0);
  324. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  325. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  326. { load method address }
  327. reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
  328. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  329. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  330. { ... and store it }
  331. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  332. end
  333. else
  334. begin
  335. { load address of the function }
  336. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0);
  337. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  338. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  339. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  340. end;
  341. end
  342. else
  343. begin
  344. if (po_external in tprocsym(symtableentry).procdef[1].procoptions) then
  345. location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tprocsym(symtableentry).procdef[1].mangledname);
  346. {!!!!! Be aware, work on virtual methods too }
  347. if (location.reference.base = NR_NO) then
  348. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname);
  349. end;
  350. end;
  351. typedconstsym :
  352. location.reference.symbol:=current_asmdata.RefAsmSymbol(ttypedconstsym(symtableentry).mangledname);
  353. labelsym :
  354. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  355. else internalerror(200510032);
  356. end;
  357. end;
  358. {*****************************************************************************
  359. SecondAssignment
  360. *****************************************************************************}
  361. procedure tcgassignmentnode.pass_2;
  362. var
  363. otlabel,hlabel,oflabel : tasmlabel;
  364. fputyp : tfloattype;
  365. href : treference;
  366. releaseright : boolean;
  367. len : aint;
  368. r:Tregister;
  369. begin
  370. location_reset(location,LOC_VOID,OS_NO);
  371. otlabel:=current_procinfo.CurrTrueLabel;
  372. oflabel:=current_procinfo.CurrFalseLabel;
  373. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  374. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  375. {
  376. in most cases we can process first the right node which contains
  377. the most complex code. Exceptions for this are:
  378. - result is in flags, loading left will then destroy the flags
  379. - result is a jump, loading left must be already done before the jump is made
  380. - result need reference count, when left points to a value used in
  381. right then decreasing the refcnt on left can possibly release
  382. the memory before right increased the refcnt, result is that an
  383. empty value is assigned
  384. - calln, call destroys most registers and is therefor 'complex'
  385. But not when the result is in the flags, then
  386. loading the left node afterwards can destroy the flags.
  387. }
  388. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  389. ((right.nodetype=calln) or
  390. (right.resulttype.def.needs_inittable) or
  391. (right.registersint>=left.registersint)) then
  392. begin
  393. secondpass(right);
  394. { increment source reference counter, this is
  395. useless for string constants}
  396. if (right.resulttype.def.needs_inittable) and
  397. (right.nodetype<>stringconstn) then
  398. begin
  399. location_force_mem(current_asmdata.CurrAsmList,right.location);
  400. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  401. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resulttype.def,href);
  402. end;
  403. if codegenerror then
  404. exit;
  405. if not(nf_concat_string in flags) then
  406. begin
  407. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  408. { can be false }
  409. secondpass(left);
  410. { decrement destination reference counter }
  411. if (left.resulttype.def.needs_inittable) then
  412. begin
  413. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  414. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resulttype.def,href);
  415. end;
  416. if codegenerror then
  417. exit;
  418. end;
  419. end
  420. else
  421. begin
  422. { calculate left sides }
  423. { don't do it yet if it's a crgister (JM) }
  424. if not(nf_concat_string in flags) then
  425. begin
  426. secondpass(left);
  427. { decrement destination reference counter }
  428. if (left.resulttype.def.needs_inittable) then
  429. begin
  430. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  431. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resulttype.def,href);
  432. end;
  433. if codegenerror then
  434. exit;
  435. end;
  436. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  437. { can be false }
  438. secondpass(right);
  439. { increment source reference counter, this is
  440. useless for string constants}
  441. if (right.resulttype.def.needs_inittable) and
  442. (right.nodetype<>stringconstn) then
  443. begin
  444. location_force_mem(current_asmdata.CurrAsmList,right.location);
  445. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  446. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resulttype.def,href);
  447. end;
  448. if codegenerror then
  449. exit;
  450. end;
  451. releaseright:=true;
  452. { optimize temp to temp copies }
  453. (* if (left.nodetype = temprefn) and
  454. { we may store certain temps in registers in the future, then this }
  455. { optimization will have to be adapted }
  456. (left.location.loc = LOC_REFERENCE) and
  457. (right.location.loc = LOC_REFERENCE) and
  458. tg.istemp(right.location.reference) and
  459. (tg.sizeoftemp(current_asmdata.CurrAsmList,right.location.reference) = tg.sizeoftemp(current_asmdata.CurrAsmList,left.location.reference)) then
  460. begin
  461. { in theory, we should also make sure the left temp type is }
  462. { already more or less of the same kind (ie. we must not }
  463. { assign an ansistring to a normaltemp). In practice, the }
  464. { assignment node will have already taken care of this for us }
  465. tcgtemprefnode(left).changelocation(right.location.reference);
  466. end
  467. { shortstring assignments are handled separately }
  468. else *)
  469. if is_shortstring(left.resulttype.def) then
  470. begin
  471. {
  472. we can get here only in the following situations
  473. for the right node:
  474. - empty constant string
  475. - char
  476. }
  477. { empty constant string }
  478. if (right.nodetype=stringconstn) and
  479. (tstringconstnode(right).len=0) then
  480. begin
  481. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,0,left.location.reference);
  482. end
  483. { char loading }
  484. else if is_char(right.resulttype.def) then
  485. begin
  486. if right.nodetype=ordconstn then
  487. begin
  488. if (target_info.endian = endian_little) then
  489. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,(tordconstnode(right).value shl 8) or 1,
  490. left.location.reference)
  491. else
  492. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,tordconstnode(right).value or (1 shl 8),
  493. left.location.reference);
  494. end
  495. else
  496. begin
  497. href:=left.location.reference;
  498. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,1,href);
  499. inc(href.offset,1);
  500. case right.location.loc of
  501. LOC_REGISTER,
  502. LOC_CREGISTER :
  503. begin
  504. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  505. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,r,href);
  506. end;
  507. LOC_REFERENCE,
  508. LOC_CREFERENCE :
  509. cg.a_load_ref_ref(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,href);
  510. else
  511. internalerror(200205111);
  512. end;
  513. end;
  514. end
  515. else
  516. internalerror(200204249);
  517. end
  518. else
  519. begin
  520. { SSA support }
  521. maybechangeloadnodereg(left);
  522. case right.location.loc of
  523. LOC_CONSTANT :
  524. begin
  525. {$ifndef cpu64bit}
  526. if right.location.size in [OS_64,OS_S64] then
  527. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  528. else
  529. {$endif cpu64bit}
  530. cg.a_load_const_loc(current_asmdata.CurrAsmList,right.location.value,left.location);
  531. end;
  532. LOC_REFERENCE,
  533. LOC_CREFERENCE :
  534. begin
  535. case left.location.loc of
  536. LOC_REGISTER,
  537. LOC_CREGISTER :
  538. begin
  539. {$ifndef cpu64bit}
  540. if left.location.size in [OS_64,OS_S64] then
  541. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  542. else
  543. {$endif cpu64bit}
  544. cg.a_load_ref_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.register);
  545. end;
  546. LOC_FPUREGISTER,
  547. LOC_CFPUREGISTER :
  548. begin
  549. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  550. right.location.size,
  551. right.location.reference,
  552. left.location.register);
  553. end;
  554. LOC_REFERENCE,
  555. LOC_CREFERENCE :
  556. begin
  557. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  558. { Use unaligned copy when the offset is not aligned }
  559. len:=left.resulttype.def.size;
  560. if (right.location.reference.offset mod sizeof(aint)<>0) or
  561. (left.location.reference.offset mod sizeof(aint)<>0) or
  562. (right.resulttype.def.alignment<sizeof(aint)) then
  563. cg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len)
  564. else
  565. cg.g_concatcopy(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len);
  566. end;
  567. LOC_MMREGISTER,
  568. LOC_CMMREGISTER:
  569. cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  570. right.location.size,
  571. left.location.size,
  572. right.location.reference,
  573. left.location.register,mms_movescalar);
  574. LOC_SUBSETREG,
  575. LOC_CSUBSETREG:
  576. cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
  577. LOC_SUBSETREF,
  578. LOC_CSUBSETREF:
  579. {$ifndef cpu64bit}
  580. if right.location.size in [OS_64,OS_S64] then
  581. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  582. else
  583. {$endif cpu64bit}
  584. cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
  585. else
  586. internalerror(200203284);
  587. end;
  588. end;
  589. {$ifdef SUPPORT_MMX}
  590. LOC_CMMXREGISTER,
  591. LOC_MMXREGISTER:
  592. begin
  593. if left.location.loc=LOC_CMMXREGISTER then
  594. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  595. else
  596. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  597. end;
  598. {$endif SUPPORT_MMX}
  599. LOC_MMREGISTER,
  600. LOC_CMMREGISTER:
  601. begin
  602. if left.resulttype.def.deftype=arraydef then
  603. begin
  604. end
  605. else
  606. begin
  607. if left.location.loc=LOC_CMMREGISTER then
  608. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  609. else
  610. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  611. end;
  612. end;
  613. LOC_REGISTER,
  614. LOC_CREGISTER :
  615. begin
  616. {$ifndef cpu64bit}
  617. if left.location.size in [OS_64,OS_S64] then
  618. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  619. right.location.register64,left.location)
  620. else
  621. {$endif cpu64bit}
  622. cg.a_load_reg_loc(current_asmdata.CurrAsmList,right.location.size,right.location.register,left.location);
  623. end;
  624. LOC_FPUREGISTER,
  625. LOC_CFPUREGISTER :
  626. begin
  627. if (left.resulttype.def.deftype=floatdef) then
  628. fputyp:=tfloatdef(left.resulttype.def).typ
  629. else
  630. if (right.resulttype.def.deftype=floatdef) then
  631. fputyp:=tfloatdef(right.resulttype.def).typ
  632. else
  633. if (right.nodetype=typeconvn) and
  634. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  635. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  636. else
  637. fputyp:=s32real;
  638. { we can't do direct moves between fpu and mm registers }
  639. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  640. begin
  641. location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
  642. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  643. tfloat2tcgsize[fputyp],tfloat2tcgsize[fputyp],
  644. right.location.register,left.location.register,mms_movescalar);
  645. end
  646. else
  647. cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  648. tfloat2tcgsize[fputyp],
  649. right.location.register,left.location);
  650. end;
  651. LOC_SUBSETREG,
  652. LOC_CSUBSETREG:
  653. begin
  654. cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  655. right.location.size,right.location.sreg,left.location);
  656. end;
  657. LOC_SUBSETREF,
  658. LOC_CSUBSETREF:
  659. begin
  660. {$ifndef cpu64bit}
  661. if right.location.size in [OS_64,OS_S64] then
  662. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  663. else
  664. {$endif cpu64bit}
  665. cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  666. right.location.size,right.location.sref,left.location);
  667. end;
  668. LOC_JUMP :
  669. begin
  670. current_asmdata.getjumplabel(hlabel);
  671. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  672. cg.a_load_const_loc(current_asmdata.CurrAsmList,1,left.location);
  673. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  674. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  675. cg.a_load_const_loc(current_asmdata.CurrAsmList,0,left.location);
  676. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  677. end;
  678. {$ifdef cpuflags}
  679. LOC_FLAGS :
  680. begin
  681. {This can be a wordbool or longbool too, no?}
  682. case left.location.loc of
  683. LOC_REGISTER,LOC_CREGISTER:
  684. cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register);
  685. LOC_REFERENCE:
  686. cg.g_flags2ref(current_asmdata.CurrAsmList,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  687. LOC_SUBSETREG,LOC_SUBSETREF:
  688. begin
  689. r:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(left.resulttype.def));
  690. cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resulttype.def),right.location.resflags,r);
  691. cg.a_load_reg_loc(current_asmdata.CurrAsmList,def_cgsize(left.resulttype.def),r,left.location);
  692. end;
  693. else
  694. internalerror(200203273);
  695. end;
  696. end;
  697. {$endif cpuflags}
  698. end;
  699. end;
  700. if releaseright then
  701. location_freetemp(current_asmdata.CurrAsmList,right.location);
  702. current_procinfo.CurrTrueLabel:=otlabel;
  703. current_procinfo.CurrFalseLabel:=oflabel;
  704. end;
  705. {*****************************************************************************
  706. SecondArrayConstruct
  707. *****************************************************************************}
  708. const
  709. vtInteger = 0;
  710. vtBoolean = 1;
  711. vtChar = 2;
  712. vtExtended = 3;
  713. vtString = 4;
  714. vtPointer = 5;
  715. vtPChar = 6;
  716. vtObject = 7;
  717. vtClass = 8;
  718. vtWideChar = 9;
  719. vtPWideChar = 10;
  720. vtAnsiString32 = 11;
  721. vtCurrency = 12;
  722. vtVariant = 13;
  723. vtInterface = 14;
  724. vtWideString = 15;
  725. vtInt64 = 16;
  726. vtQWord = 17;
  727. vtAnsiString16 = 18;
  728. vtAnsiString64 = 19;
  729. procedure tcgarrayconstructornode.pass_2;
  730. var
  731. hp : tarrayconstructornode;
  732. href : treference;
  733. lt : tdef;
  734. vaddr : boolean;
  735. vtype : longint;
  736. freetemp,
  737. dovariant : boolean;
  738. elesize : longint;
  739. tmpreg : tregister;
  740. paraloc : tcgparalocation;
  741. begin
  742. if is_packed_array(resulttype.def) then
  743. internalerror(200608042);
  744. dovariant:=(nf_forcevaria in flags) or is_variant_array(resulttype.def);
  745. if dovariant then
  746. elesize:=sizeof(aint)+sizeof(aint)
  747. else
  748. elesize:=tarraydef(resulttype.def).elesize;
  749. location_reset(location,LOC_CREFERENCE,OS_NO);
  750. fillchar(paraloc,sizeof(paraloc),0);
  751. { Allocate always a temp, also if no elements are required, to
  752. be sure that location is valid (PFV) }
  753. if tarraydef(resulttype.def).highrange=-1 then
  754. tg.GetTemp(current_asmdata.CurrAsmList,elesize,tt_normal,location.reference)
  755. else
  756. tg.GetTemp(current_asmdata.CurrAsmList,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  757. href:=location.reference;
  758. { Process nodes in array constructor }
  759. hp:=self;
  760. while assigned(hp) do
  761. begin
  762. if assigned(hp.left) then
  763. begin
  764. freetemp:=true;
  765. secondpass(hp.left);
  766. if codegenerror then
  767. exit;
  768. { Move flags and jump in register }
  769. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  770. location_force_reg(current_asmdata.CurrAsmList,hp.left.location,def_cgsize(hp.left.resulttype.def),false);
  771. if dovariant then
  772. begin
  773. { find the correct vtype value }
  774. vtype:=$ff;
  775. vaddr:=false;
  776. lt:=hp.left.resulttype.def;
  777. case lt.deftype of
  778. enumdef,
  779. orddef :
  780. begin
  781. if is_64bit(lt) then
  782. begin
  783. case torddef(lt).typ of
  784. scurrency:
  785. vtype:=vtCurrency;
  786. s64bit:
  787. vtype:=vtInt64;
  788. u64bit:
  789. vtype:=vtQWord;
  790. end;
  791. freetemp:=false;
  792. vaddr:=true;
  793. end
  794. else if (lt.deftype=enumdef) or
  795. is_integer(lt) then
  796. vtype:=vtInteger
  797. else
  798. if is_boolean(lt) then
  799. vtype:=vtBoolean
  800. else
  801. if (lt.deftype=orddef) then
  802. begin
  803. case torddef(lt).typ of
  804. uchar:
  805. vtype:=vtChar;
  806. uwidechar:
  807. vtype:=vtWideChar;
  808. end;
  809. end;
  810. end;
  811. floatdef :
  812. begin
  813. if is_currency(lt) then
  814. vtype:=vtCurrency
  815. else
  816. vtype:=vtExtended;
  817. freetemp:=false;
  818. vaddr:=true;
  819. end;
  820. procvardef,
  821. pointerdef :
  822. begin
  823. if is_pchar(lt) then
  824. vtype:=vtPChar
  825. else if is_pwidechar(lt) then
  826. vtype:=vtPWideChar
  827. else
  828. vtype:=vtPointer;
  829. end;
  830. variantdef :
  831. begin
  832. vtype:=vtVariant;
  833. vaddr:=true;
  834. freetemp:=false;
  835. end;
  836. classrefdef :
  837. vtype:=vtClass;
  838. objectdef :
  839. if is_interface(lt) then
  840. vtype:=vtInterface
  841. { vtObject really means a class based on TObject }
  842. else if is_class(lt) then
  843. vtype:=vtObject
  844. else
  845. internalerror(200505171);
  846. stringdef :
  847. begin
  848. if is_shortstring(lt) then
  849. begin
  850. vtype:=vtString;
  851. vaddr:=true;
  852. freetemp:=false;
  853. end
  854. else
  855. if is_ansistring(lt) then
  856. begin
  857. vtype:=vtAnsiString;
  858. freetemp:=false;
  859. end
  860. else
  861. if is_widestring(lt) then
  862. begin
  863. vtype:=vtWideString;
  864. freetemp:=false;
  865. end;
  866. end;
  867. end;
  868. if vtype=$ff then
  869. internalerror(14357);
  870. { write changing field update href to the next element }
  871. inc(href.offset,sizeof(aint));
  872. if vaddr then
  873. begin
  874. location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
  875. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  876. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  877. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  878. end
  879. else
  880. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
  881. { update href to the vtype field and write it }
  882. dec(href.offset,sizeof(aint));
  883. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  884. { goto next array element }
  885. inc(href.offset,sizeof(aint)*2);
  886. end
  887. else
  888. { normal array constructor of the same type }
  889. begin
  890. if resulttype.def.needs_inittable then
  891. freetemp:=false;
  892. case hp.left.location.loc of
  893. LOC_MMREGISTER,
  894. LOC_CMMREGISTER:
  895. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
  896. hp.left.location.register,href,mms_movescalar);
  897. LOC_FPUREGISTER,
  898. LOC_CFPUREGISTER :
  899. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.register,href);
  900. LOC_REFERENCE,
  901. LOC_CREFERENCE :
  902. begin
  903. if is_shortstring(hp.left.resulttype.def) then
  904. cg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  905. Tstringdef(hp.left.resulttype.def).len)
  906. else
  907. cg.g_concatcopy(current_asmdata.CurrAsmList,hp.left.location.reference,href,elesize);
  908. end;
  909. else
  910. begin
  911. {$ifndef cpu64bit}
  912. if hp.left.location.size in [OS_64,OS_S64] then
  913. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  914. else
  915. {$endif cpu64bit}
  916. cg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location,href);
  917. end;
  918. end;
  919. inc(href.offset,elesize);
  920. end;
  921. if freetemp then
  922. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  923. end;
  924. { load next entry }
  925. hp:=tarrayconstructornode(hp.right);
  926. end;
  927. end;
  928. {*****************************************************************************
  929. SecondRTTI
  930. *****************************************************************************}
  931. procedure tcgrttinode.pass_2;
  932. begin
  933. location_reset(location,LOC_CREFERENCE,OS_NO);
  934. location.reference.symbol:=rttidef.get_rtti_label(rttitype);
  935. end;
  936. begin
  937. cloadnode:=tcgloadnode;
  938. cassignmentnode:=tcgassignmentnode;
  939. carrayconstructornode:=tcgarrayconstructornode;
  940. crttinode:=tcgrttinode;
  941. end.