ncgld.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  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. end;
  28. tcgassignmentnode = class(tassignmentnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgfuncretnode = class(tfuncretnode)
  32. procedure pass_2;override;
  33. end;
  34. tcgarrayconstructornode = class(tarrayconstructornode)
  35. procedure pass_2;override;
  36. end;
  37. implementation
  38. uses
  39. systems,
  40. verbose,globtype,globals,
  41. symconst,symtype,symdef,symsym,symtable,defbase,paramgr,
  42. ncnv,ncon,nmem,
  43. aasmbase,aasmtai,aasmcpu,regvars,
  44. cginfo,cgbase,pass_2,
  45. cpubase,cpuinfo,cpupara,
  46. tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
  47. {*****************************************************************************
  48. SecondLoad
  49. *****************************************************************************}
  50. procedure tcgloadnode.pass_2;
  51. var
  52. intreg,
  53. hregister : tregister;
  54. is_cdecl,
  55. freereg : boolean;
  56. symtabletype : tsymtabletype;
  57. i : longint;
  58. href : treference;
  59. newsize : tcgsize;
  60. pushed : tpushedsaved;
  61. begin
  62. { we don't know the size of all arrays }
  63. newsize:=def_cgsize(resulttype.def);
  64. location_reset(location,LOC_REFERENCE,newsize);
  65. case symtableentry.typ of
  66. absolutesym :
  67. begin
  68. { this is only for toasm and toaddr }
  69. if (tabsolutesym(symtableentry).abstyp=toaddr) then
  70. begin
  71. {$ifdef i386}
  72. if tabsolutesym(symtableentry).absseg then
  73. location.reference.segment:=R_FS;
  74. {$endif i386}
  75. location.reference.offset:=tabsolutesym(symtableentry).address;
  76. end
  77. else
  78. location.reference.symbol:=objectlibrary.newasmsymbol(tabsolutesym(symtableentry).mangledname);
  79. end;
  80. constsym:
  81. begin
  82. if tconstsym(symtableentry).consttyp=constresourcestring then
  83. begin
  84. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  85. location.reference.symbol:=objectlibrary.newasmsymbol(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
  86. location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
  87. end
  88. else
  89. internalerror(22798);
  90. end;
  91. varsym :
  92. begin
  93. hregister:=R_NO;
  94. { C variable }
  95. if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
  96. begin
  97. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  98. end
  99. { DLL variable }
  100. else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  101. begin
  102. hregister:=rg.getaddressregister(exprasmlist);
  103. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  104. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hregister);
  105. reference_reset_base(location.reference,hregister,0);
  106. end
  107. { external variable }
  108. else if (vo_is_external in tvarsym(symtableentry).varoptions) then
  109. begin
  110. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  111. end
  112. { thread variable }
  113. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  114. begin
  115. { we've to allocate the register before we save the used registers }
  116. location.reference.base:=rg.getaddressregister(exprasmlist);
  117. rg.saveusedregisters(exprasmlist,pushed,[accumulator]);
  118. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname),0);
  119. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
  120. { the called procedure isn't allowed to change }
  121. { any register except EAX }
  122. cg.a_call_name(exprasmlist,'FPC_RELOCATE_THREADVAR');
  123. cg.a_load_reg_reg(exprasmlist,OS_INT,accumulator,location.reference.base);
  124. rg.restoreusedregisters(exprasmlist,pushed);
  125. end
  126. { normal variable }
  127. else
  128. begin
  129. symtabletype:=symtable.symtabletype;
  130. { in case it is a register variable: }
  131. if tvarsym(symtableentry).reg<>R_NO then
  132. begin
  133. if tvarsym(symtableentry).reg in fpuregs then
  134. begin
  135. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  136. location.register:=tvarsym(symtableentry).reg;
  137. end
  138. else
  139. begin
  140. intreg:=rg.makeregsize(tvarsym(symtableentry).reg,OS_INT);
  141. if (intreg in general_registers) and
  142. (not rg.regvar_loaded[intreg]) then
  143. load_regvar(exprasmlist,tvarsym(symtableentry));
  144. location_reset(location,LOC_CREGISTER,cg.reg_cgsize(tvarsym(symtableentry).reg));
  145. location.register:=tvarsym(symtableentry).reg;
  146. exclude(rg.unusedregsint,intreg);
  147. end;
  148. end
  149. else
  150. begin
  151. { first handle local and temporary variables }
  152. if (symtabletype in [parasymtable,inlinelocalsymtable,
  153. inlineparasymtable,localsymtable]) then
  154. begin
  155. location.reference.base:=procinfo.framepointer;
  156. if (symtabletype in [inlinelocalsymtable,
  157. localsymtable])
  158. {$ifdef powerpc}
  159. { the ifdef is only for speed reasons }
  160. and not(target_info.system in [system_powerpc_linux,system_powerpc_macos])
  161. {$endif powerpc}
  162. then
  163. location.reference.offset:=
  164. tvarsym(symtableentry).address-symtable.address_fixup
  165. else
  166. location.reference.offset:=
  167. tvarsym(symtableentry).address+symtable.address_fixup;
  168. {$ifndef powerpc}
  169. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  170. begin
  171. if use_esp_stackframe then
  172. dec(location.reference.offset,
  173. tvarsym(symtableentry).getvaluesize)
  174. else
  175. location.reference.offset:=-location.reference.offset;
  176. end;
  177. {$endif powerpc}
  178. if (lexlevel>symtable.symtablelevel) then
  179. begin
  180. hregister:=rg.getaddressregister(exprasmlist);
  181. { make a reference }
  182. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  183. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  184. { walk parents }
  185. i:=lexlevel-1;
  186. while (i>symtable.symtablelevel) do
  187. begin
  188. { make a reference }
  189. reference_reset_base(href,hregister,target_info.first_parm_offset);
  190. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  191. dec(i);
  192. end;
  193. location.reference.base:=hregister;
  194. end;
  195. end
  196. else
  197. case symtabletype of
  198. globalsymtable,
  199. staticsymtable :
  200. begin
  201. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  202. end;
  203. stt_exceptsymtable:
  204. begin
  205. location.reference.base:=procinfo.framepointer;
  206. location.reference.offset:=tvarsym(symtableentry).address;
  207. end;
  208. objectsymtable:
  209. begin
  210. if (sp_static in tvarsym(symtableentry).symoptions) then
  211. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname)
  212. else
  213. begin
  214. rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
  215. location.reference.base:=SELF_POINTER_REG;
  216. location.reference.offset:=tvarsym(symtableentry).address;
  217. end;
  218. end;
  219. withsymtable:
  220. begin
  221. if nf_islocal in tnode(twithsymtable(symtable).withnode).flags then
  222. location.reference:=twithnode(twithsymtable(symtable).withnode).withreference
  223. else
  224. begin
  225. location.reference.base:=rg.getaddressregister(exprasmlist);
  226. cg.a_load_ref_reg(exprasmlist,OS_ADDR,
  227. twithnode(twithsymtable(symtable).withnode).withreference,
  228. location.reference.base);
  229. end;
  230. inc(location.reference.offset,tvarsym(symtableentry).address);
  231. end;
  232. end;
  233. end;
  234. { cdecl procedure }
  235. is_cdecl:=(symtabletype=parasymtable) and
  236. (tprocdef(symtable.defowner).proccalloption in [pocall_cdecl,pocall_cppdecl]);
  237. { in case call by reference, then calculate. Open array
  238. is always an reference! }
  239. if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  240. is_open_array(tvarsym(symtableentry).vartype.def) or
  241. is_array_of_const(tvarsym(symtableentry).vartype.def) or
  242. ((tvarsym(symtableentry).varspez=vs_const) and
  243. paramanager.push_addr_param(tvarsym(symtableentry).vartype.def,is_cdecl)) then
  244. begin
  245. if hregister=R_NO then
  246. hregister:=rg.getaddressregister(exprasmlist);
  247. { we need to load only an address }
  248. location.size:=OS_ADDR;
  249. cg.a_load_loc_reg(exprasmlist,location,hregister);
  250. location_reset(location,LOC_REFERENCE,newsize);
  251. location.reference.base:=hregister;
  252. end;
  253. end;
  254. end;
  255. procsym:
  256. begin
  257. if assigned(left) then
  258. begin
  259. {
  260. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  261. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  262. CONSISTS OF TWO OS_ADDR, so you cannot set it
  263. to OS_64 - how to solve?? Carl
  264. }
  265. if (sizeof(aword) = 4) then
  266. location_reset(location,LOC_CREFERENCE,OS_64)
  267. else
  268. internalerror(20020520);
  269. tg.GetTemp(exprasmlist,2*POINTER_SIZE,tt_normal,location.reference);
  270. freereg:=false;
  271. { called as type.method, then we only need to return
  272. the address of the function, not the self pointer }
  273. if left.nodetype=typen then
  274. begin
  275. { there is no instance, we return 0 }
  276. cg.a_load_const_ref(exprasmlist,OS_ADDR,0,location.reference);
  277. end
  278. else
  279. begin
  280. secondpass(left);
  281. { load class instance address }
  282. case left.location.loc of
  283. LOC_CREGISTER,
  284. LOC_REGISTER:
  285. begin
  286. hregister:=left.location.register;
  287. if is_object(left.resulttype.def) then
  288. CGMessage(cg_e_illegal_expression);
  289. end;
  290. LOC_CREFERENCE,
  291. LOC_REFERENCE:
  292. begin
  293. hregister:=rg.getaddressregister(exprasmlist);
  294. if is_class_or_interface(left.resulttype.def) then
  295. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister)
  296. else
  297. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  298. location_release(exprasmlist,left.location);
  299. location_freetemp(exprasmlist,left.location);
  300. end;
  301. else
  302. internalerror(26019);
  303. end;
  304. { store the class instance address }
  305. href:=location.reference;
  306. inc(href.offset,POINTER_SIZE);
  307. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
  308. { hregister will be reused when loading a virtual method }
  309. freereg:=true;
  310. end;
  311. { virtual method ? }
  312. if (po_virtualmethod in tprocdef(resulttype.def).procoptions) then
  313. begin
  314. if not freereg then
  315. begin
  316. if left.nodetype <> typen then
  317. internalerror(200205161);
  318. reference_reset_symbol(href,objectlibrary.newasmsymbol(tobjectdef(left.resulttype.def).vmt_mangledname),
  319. tprocdef(resulttype.def)._class.vmtmethodoffset(tprocdef(resulttype.def).extnumber));
  320. end
  321. else
  322. begin
  323. { load vmt pointer }
  324. reference_reset_base(href,hregister,0);
  325. reference_release(exprasmlist,href);
  326. hregister:=rg.getaddressregister(exprasmlist);
  327. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  328. reference_reset_base(href,hregister,tprocdef(resulttype.def)._class.vmtmethodoffset(
  329. tprocdef(resulttype.def).extnumber));
  330. reference_release(exprasmlist,href);
  331. end;
  332. { load method address }
  333. hregister:=rg.getaddressregister(exprasmlist);
  334. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  335. { ... and store it }
  336. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  337. rg.ungetaddressregister(exprasmlist,hregister);
  338. end
  339. else
  340. begin
  341. { we don't use the hregister }
  342. if freereg then
  343. rg.ungetregister(exprasmlist,hregister);
  344. { load address of the function }
  345. reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
  346. hregister:=cg.get_scratch_reg_address(exprasmlist);
  347. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  348. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  349. cg.free_scratch_reg(exprasmlist,hregister);
  350. end;
  351. end
  352. else
  353. begin
  354. {!!!!! Be aware, work on virtual methods too }
  355. location.reference.symbol:=objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname);
  356. end;
  357. end;
  358. typedconstsym :
  359. begin
  360. location.reference.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(symtableentry).mangledname);
  361. end;
  362. else internalerror(4);
  363. end;
  364. end;
  365. {*****************************************************************************
  366. SecondAssignment
  367. *****************************************************************************}
  368. procedure tcgassignmentnode.pass_2;
  369. var
  370. otlabel,hlabel,oflabel : tasmlabel;
  371. fputyp : tfloattype;
  372. href : treference;
  373. ai : taicpu;
  374. releaseright : boolean;
  375. pushedregs : tmaybesave;
  376. cgsize : tcgsize;
  377. begin
  378. otlabel:=truelabel;
  379. oflabel:=falselabel;
  380. objectlibrary.getlabel(truelabel);
  381. objectlibrary.getlabel(falselabel);
  382. {
  383. in most cases we can process first the right node which contains
  384. the most complex code. But not when the result is in the flags, then
  385. loading the left node afterwards can destroy the flags.
  386. when the right node returns as LOC_JUMP then we will generate
  387. the following code:
  388. rightnode
  389. true:
  390. leftnode
  391. assign 1
  392. false:
  393. leftnode
  394. assign 0
  395. }
  396. { Try to determine which side to calculate first, }
  397. if (right.location.loc<>LOC_FLAGS) and
  398. ((right.location.loc=LOC_JUMP) or
  399. (right.registers32>=left.registers32)) then
  400. begin
  401. secondpass(right);
  402. { increment source reference counter, this is
  403. useless for string constants}
  404. if (right.resulttype.def.needs_inittable) and
  405. (right.nodetype<>stringconstn) then
  406. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  407. if codegenerror then
  408. exit;
  409. { We skip the generation of the left node when it's a jump, see
  410. explanation above }
  411. if (right.location.loc<>LOC_JUMP) and
  412. not(nf_concat_string in flags) then
  413. begin
  414. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  415. { can be false }
  416. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  417. secondpass(left);
  418. { decrement destination reference counter }
  419. if (left.resulttype.def.needs_inittable) then
  420. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  421. maybe_restore(exprasmlist,right.location,pushedregs);
  422. if codegenerror then
  423. exit;
  424. end;
  425. end
  426. else
  427. begin
  428. { calculate left sides }
  429. { don't do it yet if it's a crgister (JM) }
  430. if not(nf_concat_string in flags) then
  431. begin
  432. secondpass(left);
  433. { decrement destination reference counter }
  434. if (left.resulttype.def.needs_inittable) then
  435. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  436. if codegenerror then
  437. exit;
  438. end;
  439. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  440. { can be false }
  441. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  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. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  448. maybe_restore(exprasmlist,left.location,pushedregs);
  449. if codegenerror then
  450. exit;
  451. end;
  452. if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  453. {$ifdef SUPPORT_MMX}LOC_CMMXREGISTER,{$endif}
  454. LOC_CREGISTER]) then
  455. begin
  456. CGMessage(cg_e_illegal_expression);
  457. exit;
  458. end;
  459. releaseright:=true;
  460. { shortstring assignments are handled separately }
  461. if is_shortstring(left.resulttype.def) then
  462. begin
  463. {
  464. we can get here only in the following situations
  465. for the right node:
  466. - empty constant string
  467. - char
  468. }
  469. { empty constant string }
  470. if (right.nodetype=stringconstn) and
  471. (tstringconstnode(right).len=0) then
  472. begin
  473. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  474. end
  475. { char loading }
  476. else if is_char(right.resulttype.def) then
  477. begin
  478. if right.nodetype=ordconstn then
  479. begin
  480. if (target_info.endian = endian_little) then
  481. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  482. left.location.reference)
  483. else
  484. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  485. left.location.reference);
  486. end
  487. else
  488. begin
  489. href:=left.location.reference;
  490. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  491. inc(href.offset,1);
  492. case right.location.loc of
  493. LOC_REGISTER,
  494. LOC_CREGISTER :
  495. cg.a_load_reg_ref(exprasmlist,OS_8,rg.makeregsize(right.location.register,OS_8),href);
  496. LOC_REFERENCE,
  497. LOC_CREFERENCE :
  498. cg.a_load_ref_ref(exprasmlist,OS_8,right.location.reference,href);
  499. else
  500. internalerror(200205111);
  501. end;
  502. end;
  503. end
  504. else
  505. internalerror(200204249);
  506. end
  507. else
  508. begin
  509. case right.location.loc of
  510. LOC_CONSTANT :
  511. begin
  512. if right.location.size in [OS_64,OS_S64] then
  513. cg64.a_load64_const_loc(exprasmlist,
  514. right.location.valueqword,left.location)
  515. else
  516. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  517. end;
  518. LOC_REFERENCE,
  519. LOC_CREFERENCE :
  520. begin
  521. case left.location.loc of
  522. LOC_CREGISTER :
  523. begin
  524. cgsize:=def_cgsize(left.resulttype.def);
  525. if cgsize in [OS_64,OS_S64] then
  526. cg64.a_load64_ref_reg(exprasmlist,
  527. right.location.reference,left.location.register64)
  528. else
  529. cg.a_load_ref_reg(exprasmlist,cgsize,
  530. right.location.reference,left.location.register);
  531. location_release(exprasmlist,right.location);
  532. end;
  533. LOC_CFPUREGISTER :
  534. begin
  535. cg.a_loadfpu_ref_reg(exprasmlist,
  536. def_cgsize(right.resulttype.def),
  537. right.location.reference,
  538. left.location.register);
  539. end;
  540. LOC_REFERENCE,
  541. LOC_CREFERENCE :
  542. begin
  543. cg.g_concatcopy(exprasmlist,right.location.reference,
  544. left.location.reference,left.resulttype.def.size,true,false);
  545. { right.location is already released by concatcopy }
  546. releaseright:=false;
  547. end;
  548. else
  549. internalerror(200203284);
  550. end;
  551. end;
  552. {$ifdef SUPPORT_MMX}
  553. LOC_CMMXREGISTER,
  554. LOC_MMXREGISTER:
  555. begin
  556. if left.location.loc=LOC_CMMXREGISTER then
  557. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  558. else
  559. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  560. end;
  561. {$endif SUPPORT_MMX}
  562. LOC_REGISTER,
  563. LOC_CREGISTER :
  564. begin
  565. cgsize:=def_cgsize(left.resulttype.def);
  566. if cgsize in [OS_64,OS_S64] then
  567. cg64.a_load64_reg_loc(exprasmlist,
  568. right.location.register64,left.location)
  569. else
  570. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  571. end;
  572. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  573. begin
  574. if (left.resulttype.def.deftype=floatdef) then
  575. fputyp:=tfloatdef(left.resulttype.def).typ
  576. else
  577. if (right.resulttype.def.deftype=floatdef) then
  578. fputyp:=tfloatdef(right.resulttype.def).typ
  579. else
  580. if (right.nodetype=typeconvn) and
  581. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  582. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  583. else
  584. fputyp:=s32real;
  585. cg.a_loadfpu_reg_loc(exprasmlist,
  586. tfloat2tcgsize[fputyp],
  587. right.location.register,left.location);
  588. end;
  589. LOC_JUMP :
  590. begin
  591. cgsize:=def_cgsize(left.resulttype.def);
  592. objectlibrary.getlabel(hlabel);
  593. { generate the leftnode for the true case, and
  594. release the location }
  595. cg.a_label(exprasmlist,truelabel);
  596. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  597. secondpass(left);
  598. maybe_restore(exprasmlist,right.location,pushedregs);
  599. if codegenerror then
  600. exit;
  601. cg.a_load_const_loc(exprasmlist,1,left.location);
  602. location_release(exprasmlist,left.location);
  603. cg.a_jmp_always(exprasmlist,hlabel);
  604. { generate the leftnode for the false case }
  605. cg.a_label(exprasmlist,falselabel);
  606. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  607. secondpass(left);
  608. maybe_restore(exprasmlist,right.location,pushedregs);
  609. if codegenerror then
  610. exit;
  611. cg.a_load_const_loc(exprasmlist,0,left.location);
  612. cg.a_label(exprasmlist,hlabel);
  613. end;
  614. LOC_FLAGS :
  615. begin
  616. // this can be a wordbool or longbool too, no?
  617. if left.location.loc=LOC_CREGISTER then
  618. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  619. else
  620. begin
  621. if not(left.location.loc = LOC_REFERENCE) then
  622. internalerror(200203273);
  623. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  624. end;
  625. end;
  626. end;
  627. end;
  628. if releaseright then
  629. location_release(exprasmlist,right.location);
  630. location_release(exprasmlist,left.location);
  631. truelabel:=otlabel;
  632. falselabel:=oflabel;
  633. end;
  634. {*****************************************************************************
  635. SecondFuncRet
  636. *****************************************************************************}
  637. procedure tcgfuncretnode.pass_2;
  638. var
  639. hreg : tregister;
  640. href : treference;
  641. pp : tprocinfo;
  642. hr_valid : boolean;
  643. i : integer;
  644. begin
  645. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  646. hr_valid:=false;
  647. if (not inlining_procedure) and
  648. (lexlevel<>funcretsym.owner.symtablelevel) then
  649. begin
  650. hreg:=rg.getaddressregister(exprasmlist);
  651. hr_valid:=true;
  652. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  653. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  654. { walk up the stack frame }
  655. pp:=procinfo.parent;
  656. i:=lexlevel-1;
  657. while i>funcretsym.owner.symtablelevel do
  658. begin
  659. reference_reset_base(href,hreg,pp.framepointer_offset);
  660. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  661. pp:=pp.parent;
  662. dec(i);
  663. end;
  664. location.reference.base:=hreg;
  665. location.reference.offset:=pp.return_offset;
  666. end
  667. else
  668. begin
  669. location.reference.base:=procinfo.framepointer;
  670. location.reference.offset:=procinfo.return_offset;
  671. end;
  672. if paramanager.ret_in_param(resulttype.def) then
  673. begin
  674. { the parameter is actual a pointer to the value }
  675. if not hr_valid then
  676. hreg:=rg.getaddressregister(exprasmlist);
  677. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hreg);
  678. location.reference.base:=hreg;
  679. location.reference.offset:=0;
  680. end;
  681. end;
  682. {*****************************************************************************
  683. SecondArrayConstruct
  684. *****************************************************************************}
  685. const
  686. vtInteger = 0;
  687. vtBoolean = 1;
  688. vtChar = 2;
  689. vtExtended = 3;
  690. vtString = 4;
  691. vtPointer = 5;
  692. vtPChar = 6;
  693. vtObject = 7;
  694. vtClass = 8;
  695. vtWideChar = 9;
  696. vtPWideChar = 10;
  697. vtAnsiString = 11;
  698. vtCurrency = 12;
  699. vtVariant = 13;
  700. vtInterface = 14;
  701. vtWideString = 15;
  702. vtInt64 = 16;
  703. vtQWord = 17;
  704. procedure tcgarrayconstructornode.pass_2;
  705. var
  706. hp : tarrayconstructornode;
  707. href : treference;
  708. lt : tdef;
  709. vaddr : boolean;
  710. vtype : longint;
  711. freetemp,
  712. dovariant : boolean;
  713. elesize : longint;
  714. tmpreg : tregister;
  715. begin
  716. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  717. if dovariant then
  718. elesize:=8
  719. else
  720. elesize:=tarraydef(resulttype.def).elesize;
  721. if not(nf_cargs in flags) then
  722. begin
  723. location_reset(location,LOC_REFERENCE,OS_NO);
  724. { Allocate always a temp, also if no elements are required, to
  725. be sure that location is valid (PFV) }
  726. if tarraydef(resulttype.def).highrange=-1 then
  727. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  728. else
  729. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  730. href:=location.reference;
  731. end;
  732. hp:=self;
  733. while assigned(hp) do
  734. begin
  735. if assigned(hp.left) then
  736. begin
  737. freetemp:=true;
  738. secondpass(hp.left);
  739. if codegenerror then
  740. exit;
  741. if dovariant then
  742. begin
  743. { find the correct vtype value }
  744. vtype:=$ff;
  745. vaddr:=false;
  746. lt:=hp.left.resulttype.def;
  747. case lt.deftype of
  748. enumdef,
  749. orddef :
  750. begin
  751. if is_64bitint(lt) then
  752. begin
  753. case torddef(lt).typ of
  754. s64bit:
  755. vtype:=vtInt64;
  756. u64bit:
  757. vtype:=vtQWord;
  758. end;
  759. freetemp:=false;
  760. vaddr:=true;
  761. end
  762. else if (lt.deftype=enumdef) or
  763. is_integer(lt) then
  764. vtype:=vtInteger
  765. else
  766. if is_boolean(lt) then
  767. vtype:=vtBoolean
  768. else
  769. if (lt.deftype=orddef) and (torddef(lt).typ=uchar) then
  770. vtype:=vtChar;
  771. end;
  772. floatdef :
  773. begin
  774. vtype:=vtExtended;
  775. vaddr:=true;
  776. freetemp:=false;
  777. end;
  778. procvardef,
  779. pointerdef :
  780. begin
  781. if is_pchar(lt) then
  782. vtype:=vtPChar
  783. else
  784. vtype:=vtPointer;
  785. end;
  786. classrefdef :
  787. vtype:=vtClass;
  788. objectdef :
  789. begin
  790. vtype:=vtObject;
  791. end;
  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. begin
  803. vtype:=vtAnsiString;
  804. freetemp:=false;
  805. end
  806. else
  807. if is_widestring(lt) then
  808. begin
  809. vtype:=vtWideString;
  810. freetemp:=false;
  811. end;
  812. end;
  813. end;
  814. if vtype=$ff then
  815. internalerror(14357);
  816. { write C style pushes or an pascal array }
  817. if nf_cargs in flags then
  818. begin
  819. if vaddr then
  820. begin
  821. location_force_mem(exprasmlist,hp.left.location);
  822. cg.a_paramaddr_ref(exprasmlist,hp.left.location.reference,paralocdummy);
  823. location_release(exprasmlist,hp.left.location);
  824. if freetemp then
  825. location_freetemp(exprasmlist,hp.left.location);
  826. end
  827. else
  828. cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
  829. inc(pushedparasize,pointer_size);
  830. end
  831. else
  832. begin
  833. { write changing field update href to the next element }
  834. inc(href.offset,4);
  835. if vaddr then
  836. begin
  837. location_force_mem(exprasmlist,hp.left.location);
  838. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  839. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  840. cg.a_load_reg_ref(exprasmlist,cg.reg_cgsize(tmpreg),tmpreg,href);
  841. cg.free_scratch_reg(exprasmlist,tmpreg);
  842. location_release(exprasmlist,hp.left.location);
  843. if freetemp then
  844. location_freetemp(exprasmlist,hp.left.location);
  845. end
  846. else
  847. begin
  848. location_release(exprasmlist,left.location);
  849. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  850. end;
  851. { update href to the vtype field and write it }
  852. dec(href.offset,4);
  853. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  854. { goto next array element }
  855. inc(href.offset,8);
  856. end;
  857. end
  858. else
  859. { normal array constructor of the same type }
  860. begin
  861. case elesize of
  862. 1,2,4 :
  863. begin
  864. location_release(exprasmlist,left.location);
  865. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  866. end;
  867. 8 :
  868. begin
  869. if hp.left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  870. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  871. else
  872. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  873. end;
  874. else
  875. begin
  876. { concatcopy only supports reference }
  877. if not(hp.left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  878. internalerror(200108012);
  879. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  880. end;
  881. end;
  882. inc(href.offset,elesize);
  883. end;
  884. end;
  885. { load next entry }
  886. hp:=tarrayconstructornode(hp.right);
  887. end;
  888. end;
  889. begin
  890. cloadnode:=tcgloadnode;
  891. cassignmentnode:=tcgassignmentnode;
  892. cfuncretnode:=tcgfuncretnode;
  893. carrayconstructornode:=tcgarrayconstructornode;
  894. end.
  895. {
  896. $Log$
  897. Revision 1.26 2002-08-25 19:25:18 peter
  898. * sym.insert_in_data removed
  899. * symtable.insertvardata/insertconstdata added
  900. * removed insert_in_data call from symtable.insert, it needs to be
  901. called separatly. This allows to deref the address calculation
  902. * procedures now calculate the parast addresses after the procedure
  903. directives are parsed. This fixes the cdecl parast problem
  904. * push_addr_param has an extra argument that specifies if cdecl is used
  905. or not
  906. Revision 1.25 2002/08/23 16:14:48 peter
  907. * tempgen cleanup
  908. * tt_noreuse temp type added that will be used in genentrycode
  909. Revision 1.24 2002/08/17 09:23:35 florian
  910. * first part of procinfo rewrite
  911. Revision 1.23 2002/08/14 18:13:28 jonas
  912. * adapted previous fix to Peter's asmsymbol patch
  913. Revision 1.22 2002/08/14 18:00:42 jonas
  914. * fixed tb0403
  915. Revision 1.21 2002/08/13 21:40:56 florian
  916. * more fixes for ppc calling conventions
  917. Revision 1.20 2002/08/11 14:32:26 peter
  918. * renamed current_library to objectlibrary
  919. Revision 1.19 2002/08/11 13:24:12 peter
  920. * saving of asmsymbols in ppu supported
  921. * asmsymbollist global is removed and moved into a new class
  922. tasmlibrarydata that will hold the info of a .a file which
  923. corresponds with a single module. Added librarydata to tmodule
  924. to keep the library info stored for the module. In the future the
  925. objectfiles will also be stored to the tasmlibrarydata class
  926. * all getlabel/newasmsymbol and friends are moved to the new class
  927. Revision 1.18 2002/08/06 20:55:21 florian
  928. * first part of ppc calling conventions fix
  929. Revision 1.17 2002/07/28 09:25:37 carl
  930. + correct size of parameter (64-bit portability)
  931. Revision 1.16 2002/07/27 19:53:51 jonas
  932. + generic implementation of tcg.g_flags2ref()
  933. * tcg.flags2xxx() now also needs a size parameter
  934. Revision 1.15 2002/07/20 11:57:54 florian
  935. * types.pas renamed to defbase.pas because D6 contains a types
  936. unit so this would conflicts if D6 programms are compiled
  937. + Willamette/SSE2 instructions to assembler added
  938. Revision 1.14 2002/07/16 09:17:44 florian
  939. * threadvar relocation result wasn't handled properly, it could cause
  940. a crash
  941. Revision 1.13 2002/07/11 14:41:28 florian
  942. * start of the new generic parameter handling
  943. Revision 1.12 2002/07/07 09:52:32 florian
  944. * powerpc target fixed, very simple units can be compiled
  945. * some basic stuff for better callparanode handling, far from being finished
  946. Revision 1.11 2002/07/01 18:46:23 peter
  947. * internal linker
  948. * reorganized aasm layer
  949. Revision 1.10 2002/07/01 16:23:53 peter
  950. * cg64 patch
  951. * basics for currency
  952. * asnode updates for class and interface (not finished)
  953. Revision 1.9 2002/05/20 13:30:40 carl
  954. * bugfix of hdisponen (base must be set, not index)
  955. * more portability fixes
  956. Revision 1.8 2002/05/18 13:34:09 peter
  957. * readded missing revisions
  958. Revision 1.7 2002/05/18 11:17:03 peter
  959. * fixed internalerror due to releasing an not initialized register
  960. Revision 1.6 2002/05/16 19:46:37 carl
  961. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  962. + try to fix temp allocation (still in ifdef)
  963. + generic constructor calls
  964. + start of tassembler / tmodulebase class cleanup
  965. Revision 1.5 2002/05/14 19:34:42 peter
  966. * removed old logs and updated copyright year
  967. Revision 1.4 2002/05/13 19:54:37 peter
  968. * removed n386ld and n386util units
  969. * maybe_save/maybe_restore added instead of the old maybe_push
  970. Revision 1.3 2002/05/12 16:53:07 peter
  971. * moved entry and exitcode to ncgutil and cgobj
  972. * foreach gets extra argument for passing local data to the
  973. iterator function
  974. * -CR checks also class typecasts at runtime by changing them
  975. into as
  976. * fixed compiler to cycle with the -CR option
  977. * fixed stabs with elf writer, finally the global variables can
  978. be watched
  979. * removed a lot of routines from cga unit and replaced them by
  980. calls to cgobj
  981. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  982. u32bit then the other is typecasted also to u32bit without giving
  983. a rangecheck warning/error.
  984. * fixed pascal calling method with reversing also the high tree in
  985. the parast, detected by tcalcst3 test
  986. Revision 1.2 2002/04/21 15:24:38 carl
  987. + a_jmp_cond -> a_jmp_always (a_jmp_cond is NOT portable)
  988. + changeregsize -> rg.makeregsize
  989. Revision 1.1 2002/04/19 15:39:34 peter
  990. * removed some more routines from cga
  991. * moved location_force_reg/mem to ncgutil
  992. * moved arrayconstructnode secondpass to ncgld
  993. }