ncgld.pas 43 KB

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