ncgld.pas 48 KB

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