ncgld.pas 43 KB

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