ncgld.pas 44 KB

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