ncgld.pas 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for nodes that handle loads and assignments which
  5. are the same for all (most) processors
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit ncgld;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,nld;
  24. type
  25. tcgloadnode = class(tloadnode)
  26. procedure pass_2;override;
  27. procedure generate_picvaraccess;virtual;
  28. end;
  29. tcgassignmentnode = class(tassignmentnode)
  30. procedure pass_2;override;
  31. end;
  32. tcgarrayconstructornode = class(tarrayconstructornode)
  33. procedure pass_2;override;
  34. end;
  35. tcgrttinode = class(trttinode)
  36. procedure pass_2;override;
  37. end;
  38. implementation
  39. uses
  40. cutils,
  41. systems,
  42. verbose,globtype,globals,
  43. symconst,symtype,symdef,symsym,defutil,paramgr,
  44. ncnv,ncon,nmem,nbas,
  45. aasmbase,aasmtai,aasmcpu,
  46. cgbase,pass_2,
  47. procinfo,
  48. cpubase,parabase,
  49. tgobj,ncgutil,
  50. cgutils,cgobj,
  51. ncgbas;
  52. {*****************************************************************************
  53. SecondLoad
  54. *****************************************************************************}
  55. procedure tcgloadnode.generate_picvaraccess;
  56. begin
  57. location.reference.base:=current_procinfo.got;
  58. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname+'@GOT',AB_EXTERNAL,AT_DATA);
  59. end;
  60. procedure tcgloadnode.pass_2;
  61. var
  62. hregister : tregister;
  63. symtabletype : tsymtabletype;
  64. href : treference;
  65. newsize : tcgsize;
  66. endrelocatelab,
  67. norelocatelab : tasmlabel;
  68. paraloc1 : tcgpara;
  69. begin
  70. { we don't know the size of all arrays }
  71. newsize:=def_cgsize(resulttype.def);
  72. location_reset(location,LOC_REFERENCE,newsize);
  73. case symtableentry.typ of
  74. absolutesym :
  75. begin
  76. { this is only for toasm and toaddr }
  77. case tabsolutesym(symtableentry).abstyp of
  78. toaddr :
  79. begin
  80. {$ifdef i386}
  81. if tabsolutesym(symtableentry).absseg then
  82. location.reference.segment:=NR_FS;
  83. {$endif i386}
  84. location.reference.offset:=tabsolutesym(symtableentry).fieldoffset;
  85. end;
  86. toasm :
  87. location.reference.symbol:=objectlibrary.newasmsymbol(tabsolutesym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
  88. else
  89. internalerror(200310283);
  90. end;
  91. end;
  92. constsym:
  93. begin
  94. if tconstsym(symtableentry).consttyp=constresourcestring then
  95. begin
  96. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  97. location.reference.symbol:=objectlibrary.newasmsymbol(make_mangledname('RESOURCESTRINGLIST',tconstsym(symtableentry).owner,''),AB_EXTERNAL,AT_DATA);
  98. location.reference.offset:=tconstsym(symtableentry).resstrindex*(4+sizeof(aint)*3)+4+sizeof(aint);
  99. end
  100. else
  101. internalerror(22798);
  102. end;
  103. varsym :
  104. begin
  105. symtabletype:=symtable.symtabletype;
  106. hregister:=NR_NO;
  107. { DLL variable }
  108. if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  109. begin
  110. if target_info.system=system_powerpc_darwin then
  111. begin
  112. generate_picvaraccess;
  113. if not(pi_needs_got in current_procinfo.flags) then
  114. internalerror(200403022);
  115. end
  116. else
  117. begin
  118. hregister:=cg.getaddressregister(exprasmlist);
  119. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
  120. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,location.reference,hregister);
  121. reference_reset_base(location.reference,hregister,0);
  122. end;
  123. end
  124. { Thread variable }
  125. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  126. begin
  127. {
  128. Thread var loading is optimized to first check if
  129. a relocate function is available. When the function
  130. is available it is called to retrieve the address.
  131. Otherwise the address is loaded with the symbol
  132. The code needs to be in the order to first handle the
  133. call and then the address load to be sure that the
  134. register that is used for returning is the same (PFV)
  135. }
  136. objectlibrary.getlabel(norelocatelab);
  137. objectlibrary.getlabel(endrelocatelab);
  138. { make sure hregister can't allocate the register necessary for the parameter }
  139. paraloc1.init;
  140. paramanager.getintparaloc(pocall_default,1,paraloc1);
  141. hregister:=cg.getaddressregister(exprasmlist);
  142. reference_reset_symbol(href,objectlibrary.newasmsymbol('FPC_THREADVAR_RELOCATE',AB_EXTERNAL,AT_DATA),0);
  143. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  144. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
  145. { don't save the allocated register else the result will be destroyed later }
  146. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0);
  147. paramanager.allocparaloc(exprasmlist,paraloc1);
  148. cg.a_param_ref(exprasmlist,OS_ADDR,href,paraloc1);
  149. paramanager.freeparaloc(exprasmlist,paraloc1);
  150. paraloc1.done;
  151. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  152. cg.a_call_reg(exprasmlist,hregister);
  153. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  154. cg.getcpuregister(exprasmlist,NR_FUNCTION_RESULT_REG);
  155. cg.ungetcpuregister(exprasmlist,NR_FUNCTION_RESULT_REG);
  156. hregister:=cg.getaddressregister(exprasmlist);
  157. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  158. cg.a_jmp_always(exprasmlist,endrelocatelab);
  159. cg.a_label(exprasmlist,norelocatelab);
  160. { no relocation needed, load the address of the variable only, the
  161. layout of a threadvar is (4 bytes pointer):
  162. 0 - Threadvar index
  163. 4 - Threadvar value in single threading }
  164. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),sizeof(aint));
  165. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  166. cg.a_label(exprasmlist,endrelocatelab);
  167. location.reference.base:=hregister;
  168. end
  169. { Nested variable }
  170. else if assigned(left) then
  171. begin
  172. if not(symtabletype in [localsymtable,parasymtable]) then
  173. internalerror(200309285);
  174. secondpass(left);
  175. if left.location.loc<>LOC_REGISTER then
  176. internalerror(200309286);
  177. if tvarsym(symtableentry).localloc.loc<>LOC_REFERENCE then
  178. internalerror(200409241);
  179. hregister:=left.location.register;
  180. reference_reset_base(location.reference,hregister,tvarsym(symtableentry).localloc.reference.offset);
  181. end
  182. { Normal (or external) variable }
  183. else
  184. begin
  185. {$ifdef OLDREGVARS}
  186. { in case it is a register variable: }
  187. if tvarsym(symtableentry).localloc.loc in [LOC_REGISTER,LOC_FPUREGISTER] then
  188. begin
  189. case getregtype(tvarsym(symtableentry).localloc.register) of
  190. R_FPUREGISTER :
  191. begin
  192. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  193. location.register:=tvarsym(symtableentry).localloc.register;
  194. end;
  195. R_INTREGISTER :
  196. begin
  197. location_reset(location,LOC_CREGISTER,def_cgsize(resulttype.def));
  198. location.register:=tvarsym(symtableentry).localloc.register;
  199. hregister := location.register;
  200. end;
  201. else
  202. internalerror(200301172);
  203. end;
  204. end
  205. else
  206. {$endif OLDREGVARS}
  207. begin
  208. case symtabletype of
  209. stt_exceptsymtable,
  210. localsymtable,
  211. parasymtable :
  212. location:=tvarsym(symtableentry).localloc;
  213. globalsymtable,
  214. staticsymtable :
  215. begin
  216. if cs_create_pic in aktmoduleswitches then
  217. begin
  218. generate_picvaraccess;
  219. if not(pi_needs_got in current_procinfo.flags) then
  220. internalerror(200403023);
  221. end
  222. else
  223. begin
  224. if tvarsym(symtableentry).localloc.loc=LOC_INVALID then
  225. reference_reset_symbol(location.reference,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0)
  226. else
  227. location:=tvarsym(symtableentry).localloc;
  228. end;
  229. end;
  230. else
  231. internalerror(200305102);
  232. end;
  233. end;
  234. end;
  235. { handle call by reference variables when they are not
  236. alreayd copied to local copies. Also ignore the reference
  237. when we need to load the self pointer for objects }
  238. if is_addr_param_load then
  239. begin
  240. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  241. hregister:=location.register
  242. else
  243. begin
  244. hregister:=cg.getaddressregister(exprasmlist);
  245. { we need to load only an address }
  246. location.size:=OS_ADDR;
  247. cg.a_load_loc_reg(exprasmlist,location.size,location,hregister);
  248. end;
  249. location_reset(location,LOC_REFERENCE,newsize);
  250. location.reference.base:=hregister;
  251. end;
  252. { make const a LOC_CREFERENCE }
  253. if (tvarsym(symtableentry).varspez=vs_const) and
  254. (location.loc=LOC_REFERENCE) then
  255. location.loc:=LOC_CREFERENCE;
  256. end;
  257. procsym:
  258. begin
  259. if not assigned(procdef) then
  260. internalerror(200312011);
  261. if assigned(left) then
  262. begin
  263. {
  264. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  265. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  266. CONSISTS OF TWO OS_ADDR, so you cannot set it
  267. to OS_64 - how to solve?? Carl
  268. Solved. Florian
  269. }
  270. if (sizeof(aint) = 4) then
  271. location_reset(location,LOC_CREFERENCE,OS_64)
  272. else if (sizeof(aint) = 8) then
  273. location_reset(location,LOC_CREFERENCE,OS_128)
  274. else
  275. internalerror(20020520);
  276. tg.GetTemp(exprasmlist,2*sizeof(aint),tt_normal,location.reference);
  277. secondpass(left);
  278. { load class instance address }
  279. case left.location.loc of
  280. LOC_CREGISTER,
  281. LOC_REGISTER:
  282. begin
  283. { this is not possible for objects }
  284. if is_object(left.resulttype.def) then
  285. internalerror(200304234);
  286. hregister:=left.location.register;
  287. end;
  288. LOC_CREFERENCE,
  289. LOC_REFERENCE:
  290. begin
  291. hregister:=cg.getaddressregister(exprasmlist);
  292. if is_class_or_interface(left.resulttype.def) then
  293. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  294. else
  295. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  296. location_freetemp(exprasmlist,left.location);
  297. end;
  298. else
  299. internalerror(26019);
  300. end;
  301. { store the class instance address }
  302. href:=location.reference;
  303. inc(href.offset,sizeof(aint));
  304. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,href);
  305. { virtual method ? }
  306. if (po_virtualmethod in procdef.procoptions) then
  307. begin
  308. { load vmt pointer }
  309. reference_reset_base(href,hregister,0);
  310. hregister:=cg.getaddressregister(exprasmlist);
  311. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  312. { load method address }
  313. reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
  314. hregister:=cg.getaddressregister(exprasmlist);
  315. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  316. { ... and store it }
  317. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  318. end
  319. else
  320. begin
  321. { load address of the function }
  322. reference_reset_symbol(href,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION),0);
  323. hregister:=cg.getaddressregister(exprasmlist);
  324. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  325. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  326. end;
  327. end
  328. else
  329. begin
  330. {!!!!! Be aware, work on virtual methods too }
  331. location.reference.symbol:=objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION);
  332. end;
  333. end;
  334. typedconstsym :
  335. begin
  336. location.reference.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
  337. end;
  338. else internalerror(4);
  339. end;
  340. end;
  341. {*****************************************************************************
  342. SecondAssignment
  343. *****************************************************************************}
  344. procedure tcgassignmentnode.pass_2;
  345. var
  346. otlabel,hlabel,oflabel : tasmlabel;
  347. fputyp : tfloattype;
  348. href : treference;
  349. old_allow_multi_pass2,
  350. releaseright : boolean;
  351. len : aint;
  352. cgsize : tcgsize;
  353. r:Tregister;
  354. begin
  355. location_reset(location,LOC_VOID,OS_NO);
  356. otlabel:=truelabel;
  357. oflabel:=falselabel;
  358. objectlibrary.getlabel(truelabel);
  359. objectlibrary.getlabel(falselabel);
  360. {
  361. in most cases we can process first the right node which contains
  362. the most complex code. Exceptions for this are:
  363. - result is in flags, loading left will then destroy the flags
  364. - result need reference count, when left points to a value used in
  365. right then decreasing the refcnt on left can possibly release
  366. the memory before right increased the refcnt, result is that an
  367. empty value is assigned
  368. - calln, call destroys most registers and is therefor 'complex'
  369. But not when the result is in the flags, then
  370. loading the left node afterwards can destroy the flags.
  371. when the right node returns as LOC_JUMP then we will generate
  372. the following code:
  373. rightnode
  374. true:
  375. leftnode
  376. assign 1
  377. false:
  378. leftnode
  379. assign 0
  380. }
  381. if (right.expectloc<>LOC_FLAGS) and
  382. ((right.expectloc=LOC_JUMP) or
  383. (right.nodetype=calln) or
  384. (right.resulttype.def.needs_inittable) or
  385. (right.registersint>=left.registersint)) then
  386. begin
  387. secondpass(right);
  388. { increment source reference counter, this is
  389. useless for string constants}
  390. if (right.resulttype.def.needs_inittable) and
  391. (right.nodetype<>stringconstn) then
  392. begin
  393. location_get_data_ref(exprasmlist,right.location,href,false);
  394. cg.g_incrrefcount(exprasmlist,right.resulttype.def,href);
  395. end;
  396. if codegenerror then
  397. exit;
  398. { We skip the generation of the left node when it's a jump, see
  399. explanation above }
  400. if (right.location.loc<>LOC_JUMP) and
  401. not(nf_concat_string in flags) then
  402. begin
  403. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  404. { can be false }
  405. secondpass(left);
  406. { decrement destination reference counter }
  407. if (left.resulttype.def.needs_inittable) then
  408. begin
  409. location_get_data_ref(exprasmlist,left.location,href,false);
  410. cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
  411. end;
  412. if codegenerror then
  413. exit;
  414. end;
  415. end
  416. else
  417. begin
  418. { calculate left sides }
  419. { don't do it yet if it's a crgister (JM) }
  420. if not(nf_concat_string in flags) then
  421. begin
  422. secondpass(left);
  423. { decrement destination reference counter }
  424. if (left.resulttype.def.needs_inittable) then
  425. begin
  426. location_get_data_ref(exprasmlist,left.location,href,false);
  427. cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
  428. end;
  429. if codegenerror then
  430. exit;
  431. end;
  432. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  433. { can be false }
  434. secondpass(right);
  435. { increment source reference counter, this is
  436. useless for string constants}
  437. if (right.resulttype.def.needs_inittable) and
  438. (right.nodetype<>stringconstn) then
  439. begin
  440. location_get_data_ref(exprasmlist,right.location,href,false);
  441. cg.g_incrrefcount(exprasmlist,right.resulttype.def,href);
  442. end;
  443. if codegenerror then
  444. exit;
  445. end;
  446. releaseright:=true;
  447. { optimize temp to temp copies }
  448. (* if (left.nodetype = temprefn) and
  449. { we may store certain temps in registers in the future, then this }
  450. { optimization will have to be adapted }
  451. (left.location.loc = LOC_REFERENCE) and
  452. (right.location.loc = LOC_REFERENCE) and
  453. tg.istemp(right.location.reference) and
  454. (tg.sizeoftemp(exprasmlist,right.location.reference) = tg.sizeoftemp(exprasmlist,left.location.reference)) then
  455. begin
  456. { in theory, we should also make sure the left temp type is }
  457. { already more or less of the same kind (ie. we must not }
  458. { assign an ansistring to a normaltemp). In practice, the }
  459. { assignment node will have already taken care of this for us }
  460. tcgtemprefnode(left).changelocation(right.location.reference);
  461. end
  462. { shortstring assignments are handled separately }
  463. else *) if is_shortstring(left.resulttype.def) then
  464. begin
  465. {
  466. we can get here only in the following situations
  467. for the right node:
  468. - empty constant string
  469. - char
  470. }
  471. { empty constant string }
  472. if (right.nodetype=stringconstn) and
  473. (tstringconstnode(right).len=0) then
  474. begin
  475. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  476. end
  477. { char loading }
  478. else if is_char(right.resulttype.def) then
  479. begin
  480. if right.nodetype=ordconstn then
  481. begin
  482. if (target_info.endian = endian_little) then
  483. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  484. left.location.reference)
  485. else
  486. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  487. left.location.reference);
  488. end
  489. else
  490. begin
  491. href:=left.location.reference;
  492. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  493. inc(href.offset,1);
  494. case right.location.loc of
  495. LOC_REGISTER,
  496. LOC_CREGISTER :
  497. begin
  498. r:=cg.makeregsize(exprasmlist,right.location.register,OS_8);
  499. cg.a_load_reg_ref(exprasmlist,OS_8,OS_8,r,href);
  500. end;
  501. LOC_REFERENCE,
  502. LOC_CREFERENCE :
  503. cg.a_load_ref_ref(exprasmlist,OS_8,OS_8,right.location.reference,href);
  504. else
  505. internalerror(200205111);
  506. end;
  507. end;
  508. end
  509. else
  510. internalerror(200204249);
  511. end
  512. else
  513. begin
  514. case right.location.loc of
  515. LOC_CONSTANT :
  516. begin
  517. {$ifndef cpu64bit}
  518. if right.location.size in [OS_64,OS_S64] then
  519. cg64.a_load64_const_loc(exprasmlist,right.location.value64,left.location)
  520. else
  521. {$endif cpu64bit}
  522. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  523. end;
  524. LOC_REFERENCE,
  525. LOC_CREFERENCE :
  526. begin
  527. case left.location.loc of
  528. LOC_REGISTER,
  529. LOC_CREGISTER :
  530. begin
  531. cgsize:=def_cgsize(left.resulttype.def);
  532. {$ifndef cpu64bit}
  533. if cgsize in [OS_64,OS_S64] then
  534. cg64.a_load64_ref_reg(exprasmlist,right.location.reference,left.location.register64)
  535. else
  536. {$endif cpu64bit}
  537. cg.a_load_ref_reg(exprasmlist,cgsize,cgsize,right.location.reference,left.location.register);
  538. end;
  539. LOC_FPUREGISTER,
  540. LOC_CFPUREGISTER :
  541. begin
  542. cg.a_loadfpu_ref_reg(exprasmlist,
  543. def_cgsize(right.resulttype.def),
  544. right.location.reference,
  545. left.location.register);
  546. end;
  547. LOC_REFERENCE,
  548. LOC_CREFERENCE :
  549. begin
  550. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  551. { Use unaligned copy when the offset is not aligned }
  552. len:=left.resulttype.def.size;
  553. if (right.location.reference.offset mod sizeof(aint)<>0) and
  554. (len>sizeof(aint)) then
  555. cg.g_concatcopy_unaligned(exprasmlist,right.location.reference,left.location.reference,len)
  556. else
  557. cg.g_concatcopy(exprasmlist,right.location.reference,left.location.reference,len);
  558. end;
  559. else
  560. internalerror(200203284);
  561. end;
  562. end;
  563. {$ifdef SUPPORT_MMX}
  564. LOC_CMMXREGISTER,
  565. LOC_MMXREGISTER:
  566. begin
  567. if left.location.loc=LOC_CMMXREGISTER then
  568. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  569. else
  570. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  571. end;
  572. {$endif SUPPORT_MMX}
  573. LOC_MMREGISTER,
  574. LOC_CMMREGISTER:
  575. begin
  576. if left.resulttype.def.deftype=arraydef then
  577. begin
  578. end
  579. else
  580. begin
  581. cgsize:=def_cgsize(left.resulttype.def);
  582. if left.location.loc=LOC_CMMREGISTER then
  583. cg.a_loadmm_reg_reg(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  584. else
  585. cg.a_loadmm_reg_ref(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  586. end;
  587. end;
  588. LOC_REGISTER,
  589. LOC_CREGISTER :
  590. begin
  591. cgsize:=def_cgsize(left.resulttype.def);
  592. {$ifndef cpu64bit}
  593. if cgsize in [OS_64,OS_S64] then
  594. cg64.a_load64_reg_loc(exprasmlist,
  595. right.location.register64,left.location)
  596. else
  597. {$endif cpu64bit}
  598. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  599. end;
  600. LOC_FPUREGISTER,
  601. LOC_CFPUREGISTER :
  602. begin
  603. if (left.resulttype.def.deftype=floatdef) then
  604. fputyp:=tfloatdef(left.resulttype.def).typ
  605. else
  606. if (right.resulttype.def.deftype=floatdef) then
  607. fputyp:=tfloatdef(right.resulttype.def).typ
  608. else
  609. if (right.nodetype=typeconvn) and
  610. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  611. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  612. else
  613. fputyp:=s32real;
  614. cg.a_loadfpu_reg_loc(exprasmlist,
  615. tfloat2tcgsize[fputyp],
  616. right.location.register,left.location);
  617. end;
  618. LOC_JUMP :
  619. begin
  620. cgsize:=def_cgsize(left.resulttype.def);
  621. objectlibrary.getlabel(hlabel);
  622. { generate the leftnode for the true case, and
  623. release the location }
  624. cg.a_label(exprasmlist,truelabel);
  625. secondpass(left);
  626. if codegenerror then
  627. exit;
  628. cg.a_load_const_loc(exprasmlist,1,left.location);
  629. cg.a_jmp_always(exprasmlist,hlabel);
  630. { generate the leftnode for the false case }
  631. cg.a_label(exprasmlist,falselabel);
  632. old_allow_multi_pass2:=allow_multi_pass2;
  633. allow_multi_pass2:=true;
  634. secondpass(left);
  635. allow_multi_pass2:=old_allow_multi_pass2;
  636. if codegenerror then
  637. exit;
  638. cg.a_load_const_loc(exprasmlist,0,left.location);
  639. cg.a_label(exprasmlist,hlabel);
  640. end;
  641. {$ifdef cpuflags}
  642. LOC_FLAGS :
  643. begin
  644. {This can be a wordbool or longbool too, no?}
  645. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  646. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  647. else
  648. begin
  649. if not(left.location.loc = LOC_REFERENCE) then
  650. internalerror(200203273);
  651. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  652. end;
  653. end;
  654. {$endif cpuflags}
  655. end;
  656. end;
  657. if releaseright then
  658. location_freetemp(exprasmlist,right.location);
  659. truelabel:=otlabel;
  660. falselabel:=oflabel;
  661. end;
  662. {*****************************************************************************
  663. SecondArrayConstruct
  664. *****************************************************************************}
  665. const
  666. vtInteger = 0;
  667. vtBoolean = 1;
  668. vtChar = 2;
  669. vtExtended = 3;
  670. vtString = 4;
  671. vtPointer = 5;
  672. vtPChar = 6;
  673. vtObject = 7;
  674. vtClass = 8;
  675. vtWideChar = 9;
  676. vtPWideChar = 10;
  677. vtAnsiString32 = 11;
  678. vtCurrency = 12;
  679. vtVariant = 13;
  680. vtInterface = 14;
  681. vtWideString = 15;
  682. vtInt64 = 16;
  683. vtQWord = 17;
  684. vtAnsiString16 = 18;
  685. vtAnsiString64 = 19;
  686. procedure tcgarrayconstructornode.pass_2;
  687. var
  688. hp : tarrayconstructornode;
  689. href : treference;
  690. lt : tdef;
  691. vaddr : boolean;
  692. vtype : longint;
  693. freetemp,
  694. dovariant : boolean;
  695. elesize : longint;
  696. tmpreg : tregister;
  697. paraloc : tcgparalocation;
  698. begin
  699. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  700. if dovariant then
  701. elesize:=sizeof(aint)+sizeof(aint)
  702. else
  703. elesize:=tarraydef(resulttype.def).elesize;
  704. location_reset(location,LOC_CREFERENCE,OS_NO);
  705. fillchar(paraloc,sizeof(paraloc),0);
  706. { Allocate always a temp, also if no elements are required, to
  707. be sure that location is valid (PFV) }
  708. if tarraydef(resulttype.def).highrange=-1 then
  709. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  710. else
  711. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  712. href:=location.reference;
  713. { Process nodes in array constructor }
  714. hp:=self;
  715. while assigned(hp) do
  716. begin
  717. if assigned(hp.left) then
  718. begin
  719. freetemp:=true;
  720. secondpass(hp.left);
  721. if codegenerror then
  722. exit;
  723. { Move flags and jump in register }
  724. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  725. location_force_reg(exprasmlist,hp.left.location,def_cgsize(hp.left.resulttype.def),false);
  726. if dovariant then
  727. begin
  728. { find the correct vtype value }
  729. vtype:=$ff;
  730. vaddr:=false;
  731. lt:=hp.left.resulttype.def;
  732. case lt.deftype of
  733. enumdef,
  734. orddef :
  735. begin
  736. if is_64bit(lt) then
  737. begin
  738. case torddef(lt).typ of
  739. s64bit:
  740. vtype:=vtInt64;
  741. u64bit:
  742. vtype:=vtQWord;
  743. end;
  744. freetemp:=false;
  745. vaddr:=true;
  746. end
  747. else if (lt.deftype=enumdef) or
  748. is_integer(lt) then
  749. vtype:=vtInteger
  750. else
  751. if is_boolean(lt) then
  752. vtype:=vtBoolean
  753. else
  754. if (lt.deftype=orddef) then
  755. begin
  756. case torddef(lt).typ of
  757. uchar:
  758. vtype:=vtChar;
  759. uwidechar:
  760. vtype:=vtWideChar;
  761. end;
  762. end;
  763. end;
  764. floatdef :
  765. begin
  766. vtype:=vtExtended;
  767. freetemp:=false;
  768. vaddr:=true;
  769. end;
  770. procvardef,
  771. pointerdef :
  772. begin
  773. if is_pchar(lt) then
  774. vtype:=vtPChar
  775. else if is_pwidechar(lt) then
  776. vtype:=vtPWideChar
  777. else
  778. vtype:=vtPointer;
  779. end;
  780. variantdef :
  781. begin
  782. vtype:=vtVariant;
  783. vaddr:=true;
  784. freetemp:=false;
  785. end;
  786. classrefdef :
  787. vtype:=vtClass;
  788. objectdef :
  789. vtype:=vtObject;
  790. stringdef :
  791. begin
  792. if is_shortstring(lt) then
  793. begin
  794. vtype:=vtString;
  795. vaddr:=true;
  796. freetemp:=false;
  797. end
  798. else
  799. if is_ansistring(lt) then
  800. {$ifdef ansistring_bits}
  801. begin
  802. case Tstringdef(lt).string_typ of
  803. st_ansistring16:
  804. vtype:=vtAnsiString16;
  805. st_ansistring32:
  806. vtype:=vtAnsiString32;
  807. st_ansistring64:
  808. vtype:=vtAnsiString64;
  809. end;
  810. freetemp:=false;
  811. end
  812. {$else}
  813. begin
  814. vtype:=vtAnsiString;
  815. freetemp:=false;
  816. end
  817. {$endif}
  818. else
  819. if is_widestring(lt) then
  820. begin
  821. vtype:=vtWideString;
  822. freetemp:=false;
  823. end;
  824. end;
  825. end;
  826. if vtype=$ff then
  827. internalerror(14357);
  828. { write changing field update href to the next element }
  829. inc(href.offset,sizeof(aint));
  830. if vaddr then
  831. begin
  832. location_force_mem(exprasmlist,hp.left.location);
  833. tmpreg:=cg.getaddressregister(exprasmlist);
  834. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  835. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  836. end
  837. else
  838. cg.a_load_loc_ref(exprasmlist,OS_ADDR,hp.left.location,href);
  839. { update href to the vtype field and write it }
  840. dec(href.offset,sizeof(aint));
  841. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  842. { goto next array element }
  843. inc(href.offset,sizeof(aint)*2);
  844. end
  845. else
  846. { normal array constructor of the same type }
  847. begin
  848. if not(
  849. is_ansistring(left.resulttype.def) or
  850. is_widestring(left.resulttype.def) or
  851. (left.resulttype.def.deftype=variantdef)
  852. ) then
  853. freetemp:=true;
  854. case hp.left.location.loc of
  855. LOC_FPUREGISTER,
  856. LOC_CFPUREGISTER :
  857. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  858. LOC_REFERENCE,
  859. LOC_CREFERENCE :
  860. begin
  861. if is_shortstring(hp.left.resulttype.def) then
  862. cg.g_copyshortstring(exprasmlist,hp.left.location.reference,href,
  863. Tstringdef(hp.left.resulttype.def).len)
  864. else
  865. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize);
  866. end;
  867. else
  868. begin
  869. {$ifndef cpu64bit}
  870. if hp.left.location.size in [OS_64,OS_S64] then
  871. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  872. else
  873. {$endif cpu64bit}
  874. cg.a_load_loc_ref(exprasmlist,hp.left.location.size,hp.left.location,href);
  875. end;
  876. end;
  877. inc(href.offset,elesize);
  878. end;
  879. if freetemp then
  880. location_freetemp(exprasmlist,hp.left.location);
  881. end;
  882. { load next entry }
  883. hp:=tarrayconstructornode(hp.right);
  884. end;
  885. end;
  886. {*****************************************************************************
  887. SecondRTTI
  888. *****************************************************************************}
  889. procedure tcgrttinode.pass_2;
  890. begin
  891. location_reset(location,LOC_CREFERENCE,OS_NO);
  892. location.reference.symbol:=rttidef.get_rtti_label(rttitype);
  893. end;
  894. begin
  895. cloadnode:=tcgloadnode;
  896. cassignmentnode:=tcgassignmentnode;
  897. carrayconstructornode:=tcgarrayconstructornode;
  898. crttinode:=tcgrttinode;
  899. end.
  900. {
  901. $Log$
  902. Revision 1.129 2004-10-31 21:45:03 peter
  903. * generic tlocation
  904. * move tlocation to cgutils
  905. Revision 1.128 2004/10/24 11:44:28 peter
  906. * small regvar fixes
  907. * loadref parameter removed from concatcopy,incrrefcount,etc
  908. Revision 1.127 2004/10/10 20:21:18 peter
  909. * passing a var parameter to var parameter is now also allowed
  910. for register locations (=regvars)
  911. Revision 1.126 2004/09/26 17:45:30 peter
  912. * simple regvar support, not yet finished
  913. Revision 1.125 2004/09/25 14:23:54 peter
  914. * ungetregister is now only used for cpuregisters, renamed to
  915. ungetcpuregister
  916. * renamed (get|unget)explicitregister(s) to ..cpuregister
  917. * removed location-release/reference_release
  918. Revision 1.124 2004/09/21 17:25:12 peter
  919. * paraloc branch merged
  920. Revision 1.123 2004/09/13 20:33:41 peter
  921. * pwidechar support in array of const
  922. Revision 1.122.4.3 2004/09/12 18:31:50 peter
  923. * use normal concatcopy when data < sizeof(aint)
  924. Revision 1.122.4.2 2004/09/12 13:36:40 peter
  925. * fixed alignment issues
  926. Revision 1.122.4.1 2004/08/31 20:43:06 peter
  927. * paraloc patch
  928. Revision 1.122 2004/08/15 13:30:18 florian
  929. * fixed alignment of variant records
  930. * more alignment problems fixed
  931. Revision 1.121 2004/07/15 20:47:53 jonas
  932. - disabled temp-to-temp copy optimization, because it can cause errors
  933. now that the local variables are temps as well (it can cause local
  934. variables to be "freed" in the middle of a procedure)
  935. Revision 1.120 2004/07/03 10:26:35 peter
  936. * always pass right before left when type needs refcnt
  937. Revision 1.119 2004/06/29 20:57:03 peter
  938. * redundant freetemp removed
  939. Revision 1.118 2004/06/20 08:55:29 florian
  940. * logs truncated
  941. Revision 1.117 2004/06/16 20:07:08 florian
  942. * dwarf branch merged
  943. Revision 1.116 2004/05/22 23:34:28 peter
  944. tai_regalloc.allocation changed to ratype to notify rgobj of register size changes
  945. Revision 1.115 2004/04/29 19:56:37 daniel
  946. * Prepare compiler infrastructure for multiple ansistring types
  947. Revision 1.114.2.8 2004/06/13 10:51:16 florian
  948. * fixed several register allocator problems (sparc/arm)
  949. Revision 1.114.2.7 2004/06/12 17:01:01 florian
  950. * fixed compilation of arm compiler
  951. }