ncgld.pas 46 KB

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