ncgld.pas 42 KB

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