ncgld.pas 43 KB

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