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