ncgld.pas 44 KB

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