ncgld.pas 49 KB

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