ncgld.pas 42 KB

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