ncgld.pas 47 KB

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