ncgld.pas 39 KB

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