n386ld.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for load/assignment nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit n386ld;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,nld;
  23. type
  24. ti386loadnode = class(tloadnode)
  25. procedure pass_2;override;
  26. end;
  27. ti386assignmentnode = class(tassignmentnode)
  28. procedure pass_2;override;
  29. end;
  30. ti386funcretnode = class(tfuncretnode)
  31. procedure pass_2;override;
  32. end;
  33. implementation
  34. uses
  35. systems,
  36. verbose,globals,
  37. symconst,symtype,symdef,symsym,symtable,aasm,types,
  38. cginfo,cgbase,pass_2,
  39. nmem,ncon,ncnv,
  40. cpubase,cpuasm,
  41. cga,tgobj,n386util,ncgutil,regvars,cgobj,cg64f32,rgobj,rgcpu;
  42. {*****************************************************************************
  43. SecondLoad
  44. *****************************************************************************}
  45. procedure ti386loadnode.pass_2;
  46. var
  47. hregister : tregister;
  48. symtabletype : tsymtabletype;
  49. i : longint;
  50. href : treference;
  51. s : tasmsymbol;
  52. newsize : tcgsize;
  53. popeax : boolean;
  54. begin
  55. { we don't know the size of all arrays }
  56. newsize:=def_cgsize(resulttype.def);
  57. location_reset(location,LOC_REFERENCE,newsize);
  58. case symtableentry.typ of
  59. { this is only for toasm and toaddr }
  60. absolutesym :
  61. begin
  62. location.reference.symbol:=nil;
  63. if (tabsolutesym(symtableentry).abstyp=toaddr) then
  64. begin
  65. if tabsolutesym(symtableentry).absseg then
  66. location.reference.segment:=R_FS;
  67. location.reference.offset:=tabsolutesym(symtableentry).address;
  68. end
  69. else
  70. location.reference.symbol:=newasmsymbol(tabsolutesym(symtableentry).mangledname);
  71. end;
  72. constsym:
  73. begin
  74. if tconstsym(symtableentry).consttyp=constresourcestring then
  75. begin
  76. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  77. location.reference.symbol:=newasmsymbol(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
  78. location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
  79. end
  80. else
  81. internalerror(22798);
  82. end;
  83. varsym :
  84. begin
  85. hregister:=R_NO;
  86. { C variable }
  87. if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
  88. begin
  89. location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
  90. end
  91. { DLL variable }
  92. else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  93. begin
  94. hregister:=rg.getregisterint(exprasmlist);
  95. location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
  96. emit_ref_reg(A_MOV,S_L,location.reference,hregister);
  97. location.reference.symbol:=nil;
  98. location.reference.base:=hregister;
  99. end
  100. { external variable }
  101. else if (vo_is_external in tvarsym(symtableentry).varoptions) then
  102. begin
  103. location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
  104. end
  105. { thread variable }
  106. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  107. begin
  108. popeax:=not(R_EAX in rg.unusedregsint);
  109. if popeax then
  110. emit_reg(A_PUSH,S_L,R_EAX);
  111. reference_reset_symbol(href,newasmsymbol(tvarsym(symtableentry).mangledname),0);
  112. emit_ref(A_PUSH,S_L,href);
  113. { the called procedure isn't allowed to change }
  114. { any register except EAX }
  115. emitcall('FPC_RELOCATE_THREADVAR');
  116. location.reference.base:=rg.getregisterint(exprasmlist);
  117. emit_reg_reg(A_MOV,S_L,R_EAX,location.reference.base);
  118. if popeax then
  119. emit_reg(A_POP,S_L,R_EAX);
  120. end
  121. { normal variable }
  122. else
  123. begin
  124. symtabletype:=symtable.symtabletype;
  125. { in case it is a register variable: }
  126. if tvarsym(symtableentry).reg<>R_NO then
  127. begin
  128. if tvarsym(symtableentry).reg in [R_ST0..R_ST7] then
  129. begin
  130. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  131. location.register:=tvarsym(symtableentry).reg;
  132. end
  133. else
  134. if not(rg.makeregsize(tvarsym(symtableentry).reg,OS_INT) in [R_EAX..R_EBX]) or
  135. rg.regvar_loaded[rg.makeregsize(tvarsym(symtableentry).reg,OS_INT)] then
  136. begin
  137. location_reset(location,LOC_CREGISTER,
  138. cg.reg_cgsize(tvarsym(symtableentry).reg));
  139. location.register:=tvarsym(symtableentry).reg;
  140. exclude(rg.unusedregsint,rg.makeregsize(tvarsym(symtableentry).reg,OS_INT));
  141. end
  142. else
  143. begin
  144. load_regvar(exprasmlist,tvarsym(symtableentry));
  145. location_reset(location,LOC_CREGISTER,
  146. cg.reg_cgsize(tvarsym(symtableentry).reg));
  147. location.register:=tvarsym(symtableentry).reg;
  148. exclude(rg.unusedregsint,rg.makeregsize(tvarsym(symtableentry).reg,OS_INT));
  149. end
  150. end
  151. else
  152. begin
  153. { first handle local and temporary variables }
  154. if (symtabletype in [parasymtable,inlinelocalsymtable,
  155. inlineparasymtable,localsymtable]) then
  156. begin
  157. location.reference.base:=procinfo^.framepointer;
  158. if (symtabletype in [inlinelocalsymtable,
  159. localsymtable]) then
  160. location.reference.offset:=
  161. tvarsym(symtableentry).address-symtable.address_fixup
  162. else
  163. location.reference.offset:=
  164. tvarsym(symtableentry).address+symtable.address_fixup;
  165. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  166. begin
  167. if use_esp_stackframe then
  168. dec(location.reference.offset,
  169. tvarsym(symtableentry).getvaluesize)
  170. else
  171. location.reference.offset:=-location.reference.offset;
  172. end;
  173. if (lexlevel>symtable.symtablelevel) then
  174. begin
  175. hregister:=rg.getregisterint(exprasmlist);
  176. { make a reference }
  177. reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
  178. emit_ref_reg(A_MOV,S_L,href,hregister);
  179. i:=lexlevel-1;
  180. while (i>symtable.symtablelevel) do
  181. begin
  182. { make a reference }
  183. reference_reset_base(href,hregister,8);
  184. emit_ref_reg(A_MOV,S_L,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. rg.getexplicitregisterint(exprasmlist,R_ESI);
  205. if (sp_static in tvarsym(symtableentry).symoptions) then
  206. begin
  207. location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
  208. end
  209. else
  210. begin
  211. location.reference.base:=R_ESI;
  212. location.reference.offset:=tvarsym(symtableentry).address;
  213. end;
  214. end;
  215. withsymtable:
  216. begin
  217. { make a reference }
  218. { symtable datasize field
  219. contains the offset of the temp
  220. stored }
  221. { hp:=reference_new_base(procinfo^.framepointer,
  222. symtable.datasize);
  223. emit_ref_reg(A_MOV,S_L,hp,hregister);}
  224. if nf_islocal in tnode(twithsymtable(symtable).withnode).flags then
  225. begin
  226. location.reference:=twithnode(twithsymtable(symtable).withnode).withreference;
  227. end
  228. else
  229. begin
  230. hregister:=rg.getregisterint(exprasmlist);
  231. location.reference.base:=hregister;
  232. emit_ref_reg(A_MOV,S_L,
  233. twithnode(twithsymtable(symtable).withnode).withreference,
  234. hregister);
  235. end;
  236. inc(location.reference.offset,tvarsym(symtableentry).address);
  237. end;
  238. end;
  239. end;
  240. { in case call by reference, then calculate. Open array
  241. is always an reference! }
  242. if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  243. is_open_array(tvarsym(symtableentry).vartype.def) or
  244. is_array_of_const(tvarsym(symtableentry).vartype.def) or
  245. ((tvarsym(symtableentry).varspez=vs_const) and
  246. push_addr_param(tvarsym(symtableentry).vartype.def)) then
  247. begin
  248. if hregister=R_NO then
  249. hregister:=rg.getregisterint(exprasmlist);
  250. case location.loc of
  251. LOC_CREGISTER :
  252. emit_reg_reg(A_MOV,S_L,location.register,hregister);
  253. LOC_REFERENCE,
  254. LOC_CREFERENCE :
  255. emit_ref_reg(A_MOV,S_L,location.reference,hregister);
  256. else
  257. internalerror(2002032218);
  258. end;
  259. location_reset(location,LOC_REFERENCE,newsize);
  260. location.reference.base:=hregister;
  261. end;
  262. end;
  263. end;
  264. procsym:
  265. begin
  266. if assigned(left) then
  267. begin
  268. location_reset(location,LOC_CREFERENCE,OS_64);
  269. tg.gettempofsizereference(exprasmlist,8,location.reference);
  270. if left.nodetype=typen then
  271. begin
  272. if left.resulttype.def.deftype<>objectdef then
  273. internalerror(200103261);
  274. hregister:=rg.getexplicitregisterint(exprasmlist,R_EDI);
  275. emit_sym_ofs_reg(A_MOV,S_L,
  276. newasmsymbol(tobjectdef(left.resulttype.def).vmt_mangledname),0,R_EDI);
  277. end
  278. else
  279. begin
  280. secondpass(left);
  281. { load class instance address }
  282. case left.location.loc of
  283. LOC_CREGISTER,
  284. LOC_REGISTER:
  285. begin
  286. hregister:=left.location.register;
  287. if is_object(left.resulttype.def) then
  288. CGMessage(cg_e_illegal_expression);
  289. end;
  290. LOC_CREFERENCE,
  291. LOC_REFERENCE:
  292. begin
  293. rg.getexplicitregisterint(exprasmlist,R_EDI);
  294. hregister:=R_EDI;
  295. if is_class_or_interface(left.resulttype.def) then
  296. emit_ref_reg(A_MOV,S_L,left.location.reference,R_EDI)
  297. else
  298. emit_ref_reg(A_LEA,S_L,left.location.reference,R_EDI);
  299. end;
  300. else internalerror(26019);
  301. end;
  302. location_release(exprasmlist,left.location);
  303. location_freetemp(exprasmlist,left.location);
  304. end;
  305. { store the class instance address }
  306. href:=location.reference;
  307. inc(href.offset,4);
  308. emit_reg_ref(A_MOV,S_L,hregister,href);
  309. { virtual method ? }
  310. if (po_virtualmethod in tprocdef(resulttype.def).procoptions) then
  311. begin
  312. reference_reset_base(href,hregister,0);
  313. { load vmt pointer }
  314. emit_ref_reg(A_MOV,S_L,href,R_EDI);
  315. {$IfDef regallocfix}
  316. rg.del_reference(exprasmlist,hp^);
  317. {$EndIf regallocfix}
  318. { load method address }
  319. reference_reset_base(href,R_EDI,tprocdef(resulttype.def)._class.vmtmethodoffset(
  320. tprocdef(resulttype.def).extnumber));
  321. emit_ref_reg(A_MOV,S_L,href,R_EDI);
  322. { ... and store it }
  323. emit_reg_ref(A_MOV,S_L,R_EDI,location.reference);
  324. rg.ungetregisterint(exprasmlist,R_EDI);
  325. end
  326. else
  327. begin
  328. rg.ungetregisterint(exprasmlist,R_EDI);
  329. s:=newasmsymbol(tprocdef(resulttype.def).mangledname);
  330. emit_sym_ofs_ref(A_MOV,S_L,s,0,location.reference);
  331. end;
  332. end
  333. else
  334. begin
  335. {!!!!! Be aware, work on virtual methods too }
  336. location.reference.symbol:=newasmsymbol(tprocdef(resulttype.def).mangledname);
  337. end;
  338. end;
  339. typedconstsym :
  340. begin
  341. location.reference.symbol:=newasmsymbol(ttypedconstsym(symtableentry).mangledname);
  342. end;
  343. else internalerror(4);
  344. end;
  345. end;
  346. {*****************************************************************************
  347. SecondAssignment
  348. *****************************************************************************}
  349. procedure ti386assignmentnode.pass_2;
  350. var
  351. regs_to_push: tregisterset;
  352. otlabel,hlabel,oflabel : tasmlabel;
  353. fputyp : tfloattype;
  354. loc : tloc;
  355. href : treference;
  356. ai : taicpu;
  357. releaseright,
  358. pushed : boolean;
  359. regspushed : tpushedsaved;
  360. cgsize : tcgsize;
  361. begin
  362. otlabel:=truelabel;
  363. oflabel:=falselabel;
  364. getlabel(truelabel);
  365. getlabel(falselabel);
  366. {
  367. in most cases we can process first the right node which contains
  368. the most complex code. But not when the result is in the flags, then
  369. loading the left node afterwards can destroy the flags.
  370. when the right node returns as LOC_JUMP then we will generate
  371. the following code:
  372. rightnode
  373. true:
  374. leftnode
  375. assign 1
  376. false:
  377. leftnode
  378. assign 0
  379. }
  380. { Try to determine which side to calculate first, }
  381. if (right.location.loc<>LOC_FLAGS) and
  382. ((right.location.loc=LOC_JUMP) or
  383. (right.registers32>=left.registers32)) then
  384. begin
  385. secondpass(right);
  386. if codegenerror then
  387. exit;
  388. { We skip the generation of the left node when it's a jump, see
  389. explanation above }
  390. if (right.location.loc<>LOC_JUMP) and
  391. not(nf_concat_string in flags) then
  392. begin
  393. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  394. { can be false }
  395. pushed:=maybe_push(left.registers32,right,false);
  396. secondpass(left);
  397. if pushed then
  398. restore(right,false);
  399. if codegenerror then
  400. exit;
  401. end;
  402. end
  403. else
  404. begin
  405. { calculate left sides }
  406. { don't do it yet if it's a crgister (JM) }
  407. if not(nf_concat_string in flags) then
  408. begin
  409. secondpass(left);
  410. if codegenerror then
  411. exit;
  412. end;
  413. {$ifdef test_dest_loc}
  414. { lets try to optimize this (PM) }
  415. { define a dest_loc that is the location }
  416. { and a ptree to verify that it is the right }
  417. { place to insert it }
  418. if (aktexprlevel<4) then
  419. begin
  420. dest_loc_known:=true;
  421. dest_loc:=left.location;
  422. dest_loc_tree:=right;
  423. end;
  424. {$endif test_dest_loc}
  425. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  426. { can be false }
  427. pushed:=maybe_push(right.registers32,left,is_64bitint(right.resulttype.def));
  428. secondpass(right);
  429. if pushed then
  430. restore(left,false);
  431. if codegenerror then
  432. exit;
  433. {$ifdef test_dest_loc}
  434. dest_loc_known:=false;
  435. if in_dest_loc then
  436. begin
  437. truelabel:=otlabel;
  438. falselabel:=oflabel;
  439. in_dest_loc:=false;
  440. exit;
  441. end;
  442. {$endif test_dest_loc}
  443. end;
  444. if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  445. LOC_CREGISTER,LOC_CMMXREGISTER]) then
  446. begin
  447. CGMessage(cg_e_illegal_expression);
  448. exit;
  449. end;
  450. loc:=left.location.loc;
  451. if left.resulttype.def.deftype=stringdef then
  452. begin
  453. if is_ansistring(left.resulttype.def) or
  454. is_widestring(left.resulttype.def) then
  455. begin
  456. { before pushing any parameter, we have to save all used }
  457. { registers, but before that we have to release the }
  458. { registers of that node to save uneccessary pushed }
  459. { so be careful, if you think you can optimize that code (FK) }
  460. { nevertheless, this has to be changed, because otherwise the }
  461. { register is released before it's contents are pushed -> }
  462. { problems with the optimizer (JM) }
  463. { Find out which registers have to be pushed (JM) }
  464. regs_to_push := all_registers;
  465. remove_non_regvars_from_loc(right.location,regs_to_push);
  466. remove_non_regvars_from_loc(left.location,regs_to_push);
  467. { And push them (JM) }
  468. rg.saveusedregisters(exprasmlist,regspushed,regs_to_push);
  469. location_release(exprasmlist,right.location);
  470. cg.a_param_loc(exprasmlist,right.location,2);
  471. location_release(exprasmlist,left.location);
  472. cg.a_paramaddr_ref(exprasmlist,left.location.reference,1);
  473. rg.saveregvars(exprasmlist,all_registers);
  474. if is_ansistring(left.resulttype.def) then
  475. emitcall('FPC_ANSISTR_ASSIGN')
  476. else
  477. emitcall('FPC_WIDESTR_ASSIGN');
  478. maybe_loadself;
  479. rg.restoreusedregisters(exprasmlist,regspushed);
  480. location_freetemp(exprasmlist,right.location);
  481. end
  482. else if is_shortstring(left.resulttype.def) and
  483. not (nf_concat_string in flags) then
  484. begin
  485. if is_ansistring(right.resulttype.def) then
  486. begin
  487. if (right.nodetype=stringconstn) and
  488. (tstringconstnode(right).len=0) then
  489. begin
  490. emit_const_ref(A_MOV,S_B,0,left.location.reference);
  491. location_release(exprasmlist,left.location);
  492. end
  493. else
  494. loadansi2short(right,left);
  495. end
  496. else
  497. begin
  498. { we do not need destination anymore }
  499. location_release(exprasmlist,left.location);
  500. {del_reference(right.location.reference);
  501. done in loadshortstring }
  502. loadshortstring(right,left);
  503. location_freetemp(exprasmlist,right.location);
  504. end;
  505. end
  506. else if is_longstring(left.resulttype.def) then
  507. begin
  508. internalerror(200105261);
  509. end
  510. else
  511. begin
  512. { its the only thing we have to do }
  513. location_release(exprasmlist,right.location);
  514. end
  515. end
  516. else if is_interfacecom(left.resulttype.def) then
  517. begin
  518. loadinterfacecom(self);
  519. end
  520. else
  521. begin
  522. releaseright:=true;
  523. case right.location.loc of
  524. LOC_CONSTANT :
  525. begin
  526. if right.location.size in [OS_64,OS_S64] then
  527. tcg64f32(cg).a_load64_const_loc(exprasmlist,
  528. right.location.valuelow,right.location.valuehigh,left.location)
  529. else
  530. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  531. end;
  532. LOC_REFERENCE,
  533. LOC_CREFERENCE :
  534. begin
  535. case loc of
  536. LOC_CREGISTER :
  537. begin
  538. cgsize:=def_cgsize(left.resulttype.def);
  539. if cgsize in [OS_64,OS_S64] then
  540. tcg64f32(cg).a_load64_ref_reg(exprasmlist,
  541. right.location.reference,left.location.registerlow,left.location.registerhigh)
  542. else
  543. cg.a_load_ref_reg(exprasmlist,cgsize,
  544. right.location.reference,left.location.register);
  545. location_release(exprasmlist,right.location);
  546. end;
  547. LOC_CFPUREGISTER :
  548. begin
  549. cg.a_loadfpu_ref_reg(exprasmlist,
  550. def_cgsize(right.resulttype.def),
  551. right.location.reference,
  552. left.location.register);
  553. end;
  554. LOC_REFERENCE,
  555. LOC_CREFERENCE :
  556. begin
  557. if (right.resulttype.def.needs_inittable) then
  558. begin
  559. { this would be a problem }
  560. if not(left.resulttype.def.needs_inittable) then
  561. internalerror(3457);
  562. { increment source reference counter }
  563. reference_reset_symbol(href,tstoreddef(right.resulttype.def).get_rtti_label(initrtti),0);
  564. cg.a_paramaddr_ref(exprasmlist,href,2);
  565. cg.a_paramaddr_ref(exprasmlist,right.location.reference,1);
  566. emitcall('FPC_ADDREF');
  567. { decrement destination reference counter }
  568. reference_reset_symbol(href,tstoreddef(left.resulttype.def).get_rtti_label(initrtti),0);
  569. cg.a_paramaddr_ref(exprasmlist,href,2);
  570. cg.a_paramaddr_ref(exprasmlist,left.location.reference,1);
  571. emitcall('FPC_DECREF');
  572. end;
  573. concatcopy(right.location.reference,
  574. left.location.reference,left.resulttype.def.size,true,false);
  575. { right.location is already released by concatcopy }
  576. releaseright:=false;
  577. end;
  578. else
  579. internalerror(200203284);
  580. end;
  581. end;
  582. {$ifdef SUPPORT_MMX}
  583. LOC_CMMXREGISTER,
  584. LOC_MMXREGISTER:
  585. begin
  586. if loc=LOC_CMMXREGISTER then
  587. emit_reg_reg(A_MOVQ,S_NO,right.location.register,left.location.register)
  588. else
  589. emit_reg_ref(A_MOVQ,S_NO,right.location.register,left.location.reference);
  590. end;
  591. {$endif SUPPORT_MMX}
  592. LOC_REGISTER,
  593. LOC_CREGISTER :
  594. begin
  595. cgsize:=def_cgsize(left.resulttype.def);
  596. if cgsize in [OS_64,OS_S64] then
  597. tcg64f32(cg).a_load64_reg_loc(exprasmlist,
  598. right.location.registerlow,right.location.registerhigh,left.location)
  599. else
  600. cg.a_load_reg_loc(exprasmlist,right.location.register,left.location);
  601. end;
  602. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  603. begin
  604. if (left.resulttype.def.deftype=floatdef) then
  605. fputyp:=tfloatdef(left.resulttype.def).typ
  606. else
  607. if (right.resulttype.def.deftype=floatdef) then
  608. fputyp:=tfloatdef(right.resulttype.def).typ
  609. else
  610. if (right.nodetype=typeconvn) and
  611. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  612. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  613. else
  614. fputyp:=s32real;
  615. cg.a_loadfpu_reg_loc(exprasmlist,
  616. tfloat2tcgsize[fputyp],
  617. right.location.register,left.location);
  618. end;
  619. LOC_JUMP :
  620. begin
  621. cgsize:=def_cgsize(left.resulttype.def);
  622. getlabel(hlabel);
  623. { generate the leftnode for the true case, and
  624. release the location }
  625. emitlab(truelabel);
  626. pushed:=maybe_push(left.registers32,right,false);
  627. secondpass(left);
  628. if pushed then
  629. restore(right,false);
  630. if codegenerror then
  631. exit;
  632. cg.a_load_const_loc(exprasmlist,1,left.location);
  633. emitjmp(C_None,hlabel);
  634. if not(left.location.loc in [LOC_CREGISTER{$ifdef SUPPORT_MMX},LOC_CMMXREGISTER{$endif SUPPORT_MMX}]) then
  635. location_release(exprasmlist,left.location);
  636. { generate the leftnode for the false case }
  637. emitlab(falselabel);
  638. pushed:=maybe_push(left.registers32,right,false);
  639. secondpass(left);
  640. if pushed then
  641. restore(right,false);
  642. if codegenerror then
  643. exit;
  644. cg.a_load_const_loc(exprasmlist,0,left.location);
  645. emitlab(hlabel);
  646. end;
  647. LOC_FLAGS :
  648. begin
  649. if loc=LOC_CREGISTER then
  650. cg.g_flags2reg(exprasmlist,right.location.resflags,left.location.register)
  651. else
  652. begin
  653. if not(loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  654. internalerror(200203273);
  655. ai:=Taicpu.Op_ref(A_Setcc,S_B,left.location.reference);
  656. ai.SetCondition(flags_to_cond(right.location.resflags));
  657. exprasmList.concat(ai);
  658. end;
  659. end;
  660. end;
  661. { we don't need the locations anymore. Only for
  662. CREGISTER we need to keep the new location available }
  663. if releaseright then
  664. location_release(exprasmlist,right.location);
  665. if not(left.location.loc in [LOC_CREGISTER{$ifdef SUPPORT_MMX},LOC_CMMXREGISTER{$endif SUPPORT_MMX}]) then
  666. location_release(exprasmlist,left.location);
  667. end;
  668. truelabel:=otlabel;
  669. falselabel:=oflabel;
  670. end;
  671. {*****************************************************************************
  672. SecondFuncRet
  673. *****************************************************************************}
  674. procedure ti386funcretnode.pass_2;
  675. var
  676. hreg : tregister;
  677. href : treference;
  678. pp : pprocinfo;
  679. hr_valid : boolean;
  680. i : integer;
  681. begin
  682. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  683. hr_valid:=false;
  684. if (not inlining_procedure) and
  685. (lexlevel<>funcretsym.owner.symtablelevel) then
  686. begin
  687. hreg:=rg.getregisterint(exprasmlist);
  688. hr_valid:=true;
  689. reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
  690. emit_ref_reg(A_MOV,S_L,href,hreg);
  691. { walk up the stack frame }
  692. pp:=procinfo^.parent;
  693. i:=lexlevel-1;
  694. while i>funcretsym.owner.symtablelevel do
  695. begin
  696. reference_reset_base(href,hreg,pp^.framepointer_offset);
  697. emit_ref_reg(A_MOV,S_L,href,hreg);
  698. pp:=pp^.parent;
  699. dec(i);
  700. end;
  701. location.reference.base:=hreg;
  702. location.reference.offset:=pp^.return_offset;
  703. end
  704. else
  705. begin
  706. location.reference.base:=procinfo^.framepointer;
  707. location.reference.offset:=procinfo^.return_offset;
  708. end;
  709. if ret_in_param(resulttype.def) then
  710. begin
  711. if not hr_valid then
  712. hreg:=rg.getregisterint(exprasmlist);
  713. emit_ref_reg(A_MOV,S_L,location.reference,hreg);
  714. location.reference.base:=hreg;
  715. location.reference.offset:=0;
  716. end;
  717. end;
  718. begin
  719. cloadnode:=ti386loadnode;
  720. cassignmentnode:=ti386assignmentnode;
  721. cfuncretnode:=ti386funcretnode;
  722. end.
  723. {
  724. $Log$
  725. Revision 1.37 2002-04-21 15:36:13 carl
  726. * changeregsize -> rg.makeregsize
  727. Revision 1.36 2002/04/19 15:39:35 peter
  728. * removed some more routines from cga
  729. * moved location_force_reg/mem to ncgutil
  730. * moved arrayconstructnode secondpass to ncgld
  731. Revision 1.35 2002/04/15 19:44:21 peter
  732. * fixed stackcheck that would be called recursively when a stack
  733. error was found
  734. * generic changeregsize(reg,size) for i386 register resizing
  735. * removed some more routines from cga unit
  736. * fixed returnvalue handling
  737. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  738. Revision 1.34 2002/04/07 09:16:07 carl
  739. - remove unused variable
  740. Revision 1.33 2002/04/04 19:06:12 peter
  741. * removed unused units
  742. * use tlocation.size in cg.a_*loc*() routines
  743. Revision 1.32 2002/04/03 10:43:37 jonas
  744. * fixed regvar-related bugs (the load node set the location to
  745. LOC_REGISTER instead of LOC_CREGISTER and the assignment node didn't
  746. support loading constants in LOC_CREGISTER's)
  747. Revision 1.31 2002/04/02 17:11:36 peter
  748. * tlocation,treference update
  749. * LOC_CONSTANT added for better constant handling
  750. * secondadd splitted in multiple routines
  751. * location_force_reg added for loading a location to a register
  752. of a specified size
  753. * secondassignment parses now first the right and then the left node
  754. (this is compatible with Kylix). This saves a lot of push/pop especially
  755. with string operations
  756. * adapted some routines to use the new cg methods
  757. Revision 1.30 2002/03/31 20:26:39 jonas
  758. + a_loadfpu_* and a_loadmm_* methods in tcg
  759. * register allocation is now handled by a class and is mostly processor
  760. independent (+rgobj.pas and i386/rgcpu.pas)
  761. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  762. * some small improvements and fixes to the optimizer
  763. * some register allocation fixes
  764. * some fpuvaroffset fixes in the unary minus node
  765. * push/popusedregisters is now called rg.save/restoreusedregisters and
  766. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  767. also better optimizable)
  768. * fixed and optimized register saving/restoring for new/dispose nodes
  769. * LOC_FPU locations now also require their "register" field to be set to
  770. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  771. - list field removed of the tnode class because it's not used currently
  772. and can cause hard-to-find bugs
  773. Revision 1.29 2002/03/04 19:10:14 peter
  774. * removed compiler warnings
  775. Revision 1.28 2001/12/30 17:24:46 jonas
  776. * range checking is now processor independent (part in cgobj,
  777. part in cg64f32) and should work correctly again (it needed
  778. some changes after the changes of the low and high of
  779. tordef's to int64)
  780. * maketojumpbool() is now processor independent (in ncgutil)
  781. * getregister32 is now called getregisterint
  782. Revision 1.27 2001/12/17 23:16:05 florian
  783. * array of const can now take widestring parameters as well
  784. Revision 1.26 2001/11/02 22:58:11 peter
  785. * procsym definition rewrite
  786. Revision 1.25 2001/10/28 17:22:25 peter
  787. * allow assignment of overloaded procedures to procvars when we know
  788. which procedure to take
  789. Revision 1.24 2001/10/14 11:49:51 jonas
  790. * finetuned register allocation info for assignments
  791. Revision 1.23 2001/10/04 14:33:28 jonas
  792. * fixed range check errors
  793. Revision 1.22 2001/09/09 08:51:09 jonas
  794. * fixed bug with assigning ansistrings (left^.location was released too
  795. early, caused bug reported by Aleksey V. Vaneev in mailing list on
  796. 2001/09/07 regarding 'problems with nested procedures and local vars'
  797. ("merged" from cga.pas in the fixes branch)
  798. Revision 1.21 2001/08/30 20:13:57 peter
  799. * rtti/init table updates
  800. * rttisym for reusable global rtti/init info
  801. * support published for interfaces
  802. Revision 1.20 2001/08/30 11:57:20 michael
  803. + Patch for wrong paramsize
  804. Revision 1.19 2001/08/26 13:36:59 florian
  805. * some cg reorganisation
  806. * some PPC updates
  807. Revision 1.18 2001/08/06 21:40:50 peter
  808. * funcret moved from tprocinfo to tprocdef
  809. Revision 1.17 2001/08/05 13:19:51 peter
  810. * partly fix for proc of obj=nil
  811. Revision 1.15 2001/07/28 15:13:17 peter
  812. * fixed opsize for assignment with LOC_JUMP
  813. Revision 1.14 2001/05/27 14:30:56 florian
  814. + some widestring stuff added
  815. Revision 1.13 2001/04/13 01:22:19 peter
  816. * symtable change to classes
  817. * range check generation and errors fixed, make cycle DEBUG=1 works
  818. * memory leaks fixed
  819. Revision 1.12 2001/04/02 21:20:37 peter
  820. * resulttype rewrite
  821. Revision 1.11 2000/12/25 00:07:33 peter
  822. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  823. tlinkedlist objects)
  824. Revision 1.10 2000/12/05 11:44:33 jonas
  825. + new integer regvar handling, should be much more efficient
  826. Revision 1.9 2000/11/29 00:30:48 florian
  827. * unused units removed from uses clause
  828. * some changes for widestrings
  829. Revision 1.8 2000/11/13 14:44:36 jonas
  830. * fixes so no more range errors with improved range checking code
  831. Revision 1.7 2000/11/12 23:24:15 florian
  832. * interfaces are basically running
  833. Revision 1.6 2000/11/11 22:59:20 florian
  834. * fixed resourcestrings, made a stupid mistake yesterday
  835. Revision 1.5 2000/11/09 18:52:06 florian
  836. * resourcestrings doesn't need the helper anymore they
  837. access the table now direct
  838. Revision 1.4 2000/11/06 23:15:02 peter
  839. * added copyvaluepara call again
  840. Revision 1.3 2000/11/04 14:25:23 florian
  841. + merged Attila's changes for interfaces, not tested yet
  842. Revision 1.2 2000/10/31 22:02:56 peter
  843. * symtable splitted, no real code changes
  844. Revision 1.1 2000/10/15 09:33:31 peter
  845. * moved n386*.pas to i386/ cpu_target dir
  846. Revision 1.1 2000/10/14 10:14:49 peter
  847. * moehrendorf oct 2000 rewrite
  848. }