ncgld.pas 41 KB

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