n386ld.pas 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080
  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. ti386arrayconstructornode = class(tarrayconstructornode)
  34. procedure pass_2;override;
  35. end;
  36. implementation
  37. uses
  38. globtype,systems,
  39. cobjects,verbose,globals,fmodule,
  40. symconst,symtype,symdef,symsym,symtable,aasm,types,
  41. hcodegen,temp_gen,pass_2,
  42. nmem,ncon,ncnv,
  43. cpubase,cpuasm,
  44. cgai386,tgeni386,n386cnv,n386util,cresstr;
  45. {*****************************************************************************
  46. SecondLoad
  47. *****************************************************************************}
  48. procedure ti386loadnode.pass_2;
  49. var
  50. hregister : tregister;
  51. symtabletype : tsymtabletype;
  52. i : longint;
  53. hp : preference;
  54. s : pasmsymbol;
  55. popeax : boolean;
  56. pushed : tpushed;
  57. hr : treference;
  58. begin
  59. simple_loadn:=true;
  60. reset_reference(location.reference);
  61. case symtableentry^.typ of
  62. { this is only for toasm and toaddr }
  63. absolutesym :
  64. begin
  65. location.reference.symbol:=nil;
  66. if (pabsolutesym(symtableentry)^.abstyp=toaddr) then
  67. begin
  68. if pabsolutesym(symtableentry)^.absseg then
  69. location.reference.segment:=R_FS;
  70. location.reference.offset:=pabsolutesym(symtableentry)^.address;
  71. end
  72. else
  73. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  74. end;
  75. constsym:
  76. begin
  77. if pconstsym(symtableentry)^.consttyp=constresourcestring then
  78. begin
  79. pushusedregisters(pushed,$ff);
  80. emit_const(A_PUSH,S_L,
  81. pconstsym(symtableentry)^.resstrindex);
  82. emit_sym(A_PUSH,S_L,newasmsymbol(pconstsym(symtableentry)^.owner^.name^+'_RESOURCESTRINGLIST'));
  83. emitcall('FPC_GETRESOURCESTRING');
  84. hregister:=getexplicitregister32(R_EAX);
  85. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  86. gettempansistringreference(hr);
  87. decrstringref(resulttype,hr);
  88. emit_reg_ref(A_MOV,S_L,hregister,
  89. newreference(hr));
  90. ungetregister32(hregister);
  91. popusedregisters(pushed);
  92. location.loc:=LOC_MEM;
  93. location.reference:=hr;
  94. end
  95. else
  96. internalerror(22798);
  97. end;
  98. varsym :
  99. begin
  100. hregister:=R_NO;
  101. { C variable }
  102. if (vo_is_C_var in pvarsym(symtableentry)^.varoptions) then
  103. begin
  104. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  105. end
  106. { DLL variable }
  107. else if (vo_is_dll_var in pvarsym(symtableentry)^.varoptions) then
  108. begin
  109. hregister:=getregister32;
  110. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  111. emit_ref_reg(A_MOV,S_L,newreference(location.reference),hregister);
  112. location.reference.symbol:=nil;
  113. location.reference.base:=hregister;
  114. end
  115. { external variable }
  116. else if (vo_is_external in pvarsym(symtableentry)^.varoptions) then
  117. begin
  118. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  119. end
  120. { thread variable }
  121. else if (vo_is_thread_var in pvarsym(symtableentry)^.varoptions) then
  122. begin
  123. popeax:=not(R_EAX in unused);
  124. if popeax then
  125. emit_reg(A_PUSH,S_L,R_EAX);
  126. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  127. emit_ref(A_PUSH,S_L,newreference(location.reference));
  128. { the called procedure isn't allowed to change }
  129. { any register except EAX }
  130. emitcall('FPC_RELOCATE_THREADVAR');
  131. reset_reference(location.reference);
  132. location.reference.base:=getregister32;
  133. emit_reg_reg(A_MOV,S_L,R_EAX,location.reference.base);
  134. if popeax then
  135. emit_reg(A_POP,S_L,R_EAX);
  136. end
  137. { normal variable }
  138. else
  139. begin
  140. symtabletype:=symtable^.symtabletype;
  141. { in case it is a register variable: }
  142. if pvarsym(symtableentry)^.reg<>R_NO then
  143. begin
  144. if pvarsym(symtableentry)^.reg in [R_ST0..R_ST7] then
  145. begin
  146. location.loc:=LOC_CFPUREGISTER;
  147. location.register:=pvarsym(symtableentry)^.reg;
  148. end
  149. else
  150. begin
  151. location.loc:=LOC_CREGISTER;
  152. location.register:=pvarsym(symtableentry)^.reg;
  153. unused:=unused-[pvarsym(symtableentry)^.reg];
  154. end;
  155. end
  156. else
  157. begin
  158. { first handle local and temporary variables }
  159. if (symtabletype in [parasymtable,inlinelocalsymtable,
  160. inlineparasymtable,localsymtable]) then
  161. begin
  162. location.reference.base:=procinfo^.framepointer;
  163. if (symtabletype in [inlinelocalsymtable,
  164. localsymtable]) then
  165. location.reference.offset:=
  166. pvarsym(symtableentry)^.address-symtable^.address_fixup
  167. else
  168. location.reference.offset:=
  169. pvarsym(symtableentry)^.address+symtable^.address_fixup;
  170. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  171. begin
  172. if use_esp_stackframe then
  173. dec(location.reference.offset,
  174. pvarsym(symtableentry)^.getvaluesize)
  175. else
  176. location.reference.offset:=-location.reference.offset;
  177. end;
  178. if (lexlevel>(symtable^.symtablelevel)) then
  179. begin
  180. hregister:=getregister32;
  181. { make a reference }
  182. hp:=new_reference(procinfo^.framepointer,
  183. procinfo^.framepointer_offset);
  184. emit_ref_reg(A_MOV,S_L,hp,hregister);
  185. simple_loadn:=false;
  186. i:=lexlevel-1;
  187. while i>(symtable^.symtablelevel) do
  188. begin
  189. { make a reference }
  190. hp:=new_reference(hregister,8);
  191. emit_ref_reg(A_MOV,S_L,hp,hregister);
  192. dec(i);
  193. end;
  194. location.reference.base:=hregister;
  195. end;
  196. end
  197. else
  198. case symtabletype of
  199. unitsymtable,globalsymtable,
  200. staticsymtable :
  201. begin
  202. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  203. end;
  204. stt_exceptsymtable:
  205. begin
  206. location.reference.base:=procinfo^.framepointer;
  207. location.reference.offset:=pvarsym(symtableentry)^.address;
  208. end;
  209. objectsymtable:
  210. begin
  211. getexplicitregister32(R_ESI);
  212. if (sp_static in pvarsym(symtableentry)^.symoptions) then
  213. begin
  214. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  215. end
  216. else
  217. begin
  218. location.reference.base:=R_ESI;
  219. location.reference.offset:=pvarsym(symtableentry)^.address;
  220. end;
  221. end;
  222. withsymtable:
  223. begin
  224. { make a reference }
  225. { symtable datasize field
  226. contains the offset of the temp
  227. stored }
  228. { hp:=new_reference(procinfo^.framepointer,
  229. symtable^.datasize);
  230. emit_ref_reg(A_MOV,S_L,hp,hregister);}
  231. if nf_islocal in tnode(pwithsymtable(symtable)^.withnode).flags then
  232. begin
  233. location.reference:=twithnode(pwithsymtable(symtable)^.withnode).withreference^;
  234. end
  235. else
  236. begin
  237. hregister:=getregister32;
  238. location.reference.base:=hregister;
  239. emit_ref_reg(A_MOV,S_L,
  240. newreference(twithnode(pwithsymtable(symtable)^.withnode).withreference^),
  241. hregister);
  242. end;
  243. inc(location.reference.offset,pvarsym(symtableentry)^.address);
  244. end;
  245. end;
  246. end;
  247. { in case call by reference, then calculate. Open array
  248. is always an reference! }
  249. if (pvarsym(symtableentry)^.varspez in [vs_var,vs_out]) or
  250. is_open_array(pvarsym(symtableentry)^.vartype.def) or
  251. is_array_of_const(pvarsym(symtableentry)^.vartype.def) or
  252. ((pvarsym(symtableentry)^.varspez=vs_const) and
  253. push_addr_param(pvarsym(symtableentry)^.vartype.def)) then
  254. begin
  255. simple_loadn:=false;
  256. if hregister=R_NO then
  257. hregister:=getregister32;
  258. if location.loc=LOC_CREGISTER then
  259. begin
  260. emit_reg_reg(A_MOV,S_L,
  261. location.register,hregister);
  262. location.loc:=LOC_REFERENCE;
  263. end
  264. else
  265. begin
  266. emit_ref_reg(A_MOV,S_L,
  267. newreference(location.reference),
  268. hregister);
  269. end;
  270. reset_reference(location.reference);
  271. location.reference.base:=hregister;
  272. end;
  273. end;
  274. end;
  275. procsym:
  276. begin
  277. if assigned(left) then
  278. begin
  279. secondpass(left);
  280. location.loc:=LOC_MEM;
  281. gettempofsizereference(8,location.reference);
  282. { load class instance address }
  283. case left.location.loc of
  284. LOC_CREGISTER,
  285. LOC_REGISTER:
  286. begin
  287. hregister:=left.location.register;
  288. ungetregister32(left.location.register);
  289. if is_object(left.resulttype) then
  290. CGMessage(cg_e_illegal_expression);
  291. end;
  292. LOC_MEM,
  293. LOC_REFERENCE:
  294. begin
  295. {$ifndef noAllocEdi}
  296. getexplicitregister32(R_EDI);
  297. {$endif noAllocEdi}
  298. hregister:=R_EDI;
  299. if is_class_or_interface(left.resulttype) then
  300. emit_ref_reg(A_MOV,S_L,
  301. newreference(left.location.reference),R_EDI)
  302. else
  303. emit_ref_reg(A_LEA,S_L,
  304. newreference(left.location.reference),R_EDI);
  305. del_reference(left.location.reference);
  306. ungetiftemp(left.location.reference);
  307. end;
  308. else internalerror(26019);
  309. end;
  310. { store the class instance address }
  311. new(hp);
  312. hp^:=location.reference;
  313. inc(hp^.offset,4);
  314. emit_reg_ref(A_MOV,S_L,
  315. hregister,hp);
  316. { virtual method ? }
  317. if (po_virtualmethod in pprocsym(symtableentry)^.definition^.procoptions) then
  318. begin
  319. new(hp);
  320. reset_reference(hp^);
  321. hp^.base:=hregister;
  322. { load vmt pointer }
  323. emit_ref_reg(A_MOV,S_L,
  324. hp,R_EDI);
  325. {$IfDef regallocfix}
  326. del_reference(hp^);
  327. {$EndIf regallocfix}
  328. { load method address }
  329. new(hp);
  330. reset_reference(hp^);
  331. hp^.base:=R_EDI;
  332. hp^.offset:=pprocsym(symtableentry)^.definition^._class^.vmtmethodoffset(
  333. pprocsym(symtableentry)^.definition^.extnumber);
  334. emit_ref_reg(A_MOV,S_L,
  335. hp,R_EDI);
  336. { ... and store it }
  337. emit_reg_ref(A_MOV,S_L,
  338. R_EDI,newreference(location.reference));
  339. {$ifndef noAllocEdi}
  340. ungetregister32(R_EDI);
  341. {$endif noAllocEdi}
  342. end
  343. else
  344. begin
  345. {$ifndef noAllocEdi}
  346. ungetregister32(R_EDI);
  347. {$endif noAllocEdi}
  348. s:=newasmsymbol(pprocsym(symtableentry)^.definition^.mangledname);
  349. emit_sym_ofs_ref(A_MOV,S_L,s,0,
  350. newreference(location.reference));
  351. end;
  352. end
  353. else
  354. begin
  355. {!!!!! Be aware, work on virtual methods too }
  356. location.reference.symbol:=newasmsymbol(pprocsym(symtableentry)^.definition^.mangledname);
  357. end;
  358. end;
  359. typedconstsym :
  360. begin
  361. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  362. end;
  363. else internalerror(4);
  364. end;
  365. end;
  366. {*****************************************************************************
  367. SecondAssignment
  368. *****************************************************************************}
  369. procedure ti386assignmentnode.pass_2;
  370. var
  371. opsize : topsize;
  372. otlabel,hlabel,oflabel : pasmlabel;
  373. fputyp : tfloattype;
  374. loc : tloc;
  375. r : preference;
  376. ai : paicpu;
  377. op : tasmop;
  378. pushed : boolean;
  379. regspushed : tpushed;
  380. regs_to_push: byte;
  381. ungettemp : boolean;
  382. begin
  383. otlabel:=truelabel;
  384. oflabel:=falselabel;
  385. getlabel(truelabel);
  386. getlabel(falselabel);
  387. { calculate left sides }
  388. if not(nf_concat_string in flags) then
  389. secondpass(left);
  390. if codegenerror then
  391. exit;
  392. if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  393. LOC_CREGISTER,LOC_CMMXREGISTER]) then
  394. begin
  395. CGMessage(cg_e_illegal_expression);
  396. exit;
  397. end;
  398. loc:=left.location.loc;
  399. { lets try to optimize this (PM) }
  400. { define a dest_loc that is the location }
  401. { and a ptree to verify that it is the right }
  402. { place to insert it }
  403. {$ifdef test_dest_loc}
  404. if (aktexprlevel<4) then
  405. begin
  406. dest_loc_known:=true;
  407. dest_loc:=left.location;
  408. dest_loc_tree:=right;
  409. end;
  410. {$endif test_dest_loc}
  411. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  412. { can be false }
  413. pushed:=maybe_push(right.registers32,left,false);
  414. secondpass(right);
  415. { restoring here is nonsense for LOC_JMP !! }
  416. { This generated code that was after a jmp and before any
  417. label => unreachable !!
  418. Could this be tested somehow ?? PM }
  419. if pushed and (right.location.loc <>LOC_JUMP) then
  420. restore(left,false);
  421. if codegenerror then
  422. exit;
  423. {$ifdef test_dest_loc}
  424. dest_loc_known:=false;
  425. if in_dest_loc then
  426. begin
  427. truelabel:=otlabel;
  428. falselabel:=oflabel;
  429. in_dest_loc:=false;
  430. exit;
  431. end;
  432. {$endif test_dest_loc}
  433. if left.resulttype^.deftype=stringdef then
  434. begin
  435. if is_ansistring(left.resulttype) then
  436. begin
  437. { before pushing any parameter, we have to save all used }
  438. { registers, but before that we have to release the }
  439. { registers of that node to save uneccessary pushed }
  440. { so be careful, if you think you can optimize that code (FK) }
  441. { nevertheless, this has to be changed, because otherwise the }
  442. { register is released before it's contents are pushed -> }
  443. { problems with the optimizer (JM) }
  444. del_reference(left.location.reference);
  445. ungettemp:=false;
  446. { Find out which registers have to be pushed (JM) }
  447. regs_to_push := $ff;
  448. remove_non_regvars_from_loc(right.location,regs_to_push);
  449. { And push them (JM) }
  450. pushusedregisters(regspushed,regs_to_push);
  451. case right.location.loc of
  452. LOC_REGISTER,LOC_CREGISTER:
  453. begin
  454. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,right.location.register)));
  455. ungetregister32(right.location.register);
  456. end;
  457. LOC_REFERENCE,LOC_MEM:
  458. begin
  459. { First release the registers because emit_push_mem may }
  460. { load the reference in edi before pushing and then the }
  461. { dealloc is too late (and optimizations are missed (JM) }
  462. del_reference(right.location.reference);
  463. { This one doesn't need extra registers (JM) }
  464. emit_push_mem(right.location.reference);
  465. ungettemp:=true;
  466. end;
  467. end;
  468. emitpushreferenceaddr(left.location.reference);
  469. del_reference(left.location.reference);
  470. emitcall('FPC_ANSISTR_ASSIGN');
  471. maybe_loadesi;
  472. popusedregisters(regspushed);
  473. if ungettemp then
  474. ungetiftemp(right.location.reference);
  475. end
  476. else
  477. if is_shortstring(left.resulttype) and
  478. not (nf_concat_string in flags) then
  479. begin
  480. if is_ansistring(right.resulttype) then
  481. begin
  482. if (right.nodetype=stringconstn) and
  483. (tstringconstnode(right).len=0) then
  484. begin
  485. emit_const_ref(A_MOV,S_B,
  486. 0,newreference(left.location.reference));
  487. del_reference(left.location.reference);
  488. end
  489. else
  490. loadansi2short(right,left);
  491. end
  492. else
  493. begin
  494. { we do not need destination anymore }
  495. del_reference(left.location.reference);
  496. {del_reference(right.location.reference);
  497. done in loadshortstring }
  498. loadshortstring(right,left);
  499. ungetiftemp(right.location.reference);
  500. end;
  501. end
  502. else if is_longstring(left.resulttype) then
  503. begin
  504. end
  505. else
  506. begin
  507. { its the only thing we have to do }
  508. del_reference(right.location.reference);
  509. end
  510. end
  511. else if is_interfacecom(left.resulttype) then
  512. begin
  513. loadinterfacecom(self);
  514. end
  515. else case right.location.loc of
  516. LOC_REFERENCE,
  517. LOC_MEM : begin
  518. { extra handling for ordinal constants }
  519. if (right.nodetype in [ordconstn,fixconstn]) or
  520. (loc=LOC_CREGISTER) then
  521. begin
  522. case left.resulttype^.size of
  523. 1 : opsize:=S_B;
  524. 2 : opsize:=S_W;
  525. 4 : opsize:=S_L;
  526. { S_L is correct, the copy is done }
  527. { with two moves }
  528. 8 : opsize:=S_L;
  529. end;
  530. if loc=LOC_CREGISTER then
  531. begin
  532. emit_ref_reg(A_MOV,opsize,
  533. newreference(right.location.reference),
  534. left.location.register);
  535. if is_64bitint(right.resulttype) then
  536. begin
  537. r:=newreference(right.location.reference);
  538. inc(r^.offset,4);
  539. emit_ref_reg(A_MOV,opsize,r,
  540. left.location.registerhigh);
  541. end;
  542. {$IfDef regallocfix}
  543. del_reference(right.location.reference);
  544. {$EndIf regallocfix}
  545. end
  546. else
  547. begin
  548. if is_64bitint(right.resulttype) then
  549. begin
  550. emit_const_ref(A_MOV,opsize,
  551. lo(tordconstnode(right).value),
  552. newreference(left.location.reference));
  553. r:=newreference(left.location.reference);
  554. inc(r^.offset,4);
  555. emit_const_ref(A_MOV,opsize,
  556. hi(tordconstnode(right).value),r);
  557. end
  558. else
  559. begin
  560. emit_const_ref(A_MOV,opsize,
  561. right.location.reference.offset,
  562. newreference(left.location.reference));
  563. end;
  564. {$IfDef regallocfix}
  565. del_reference(left.location.reference);
  566. {$EndIf regallocfix}
  567. {emit_const_loc(A_MOV,opsize,
  568. right.location.reference.offset,
  569. left.location);}
  570. end;
  571. end
  572. else if loc=LOC_CFPUREGISTER then
  573. begin
  574. floatloadops(pfloatdef(right.resulttype)^.typ,op,opsize);
  575. emit_ref(op,opsize,
  576. newreference(right.location.reference));
  577. emit_reg(A_FSTP,S_NO,
  578. correct_fpuregister(left.location.register,fpuvaroffset+1));
  579. end
  580. else
  581. begin
  582. if (right.resulttype^.needs_inittable) and
  583. not(is_class(right.resulttype)) then
  584. begin
  585. { this would be a problem }
  586. if not(left.resulttype^.needs_inittable) then
  587. internalerror(3457);
  588. { increment source reference counter }
  589. new(r);
  590. reset_reference(r^);
  591. r^.symbol:=pstoreddef(right.resulttype)^.get_inittable_label;
  592. emitpushreferenceaddr(r^);
  593. emitpushreferenceaddr(right.location.reference);
  594. emitcall('FPC_ADDREF');
  595. { decrement destination reference counter }
  596. new(r);
  597. reset_reference(r^);
  598. r^.symbol:=pstoreddef(left.resulttype)^.get_inittable_label;
  599. emitpushreferenceaddr(r^);
  600. emitpushreferenceaddr(left.location.reference);
  601. emitcall('FPC_DECREF');
  602. end;
  603. {$ifdef regallocfix}
  604. concatcopy(right.location.reference,
  605. left.location.reference,left.resulttype^.size,true,false);
  606. ungetiftemp(right.location.reference);
  607. {$Else regallocfix}
  608. concatcopy(right.location.reference,
  609. left.location.reference,left.resulttype^.size,false,false);
  610. ungetiftemp(right.location.reference);
  611. {$endif regallocfix}
  612. end;
  613. end;
  614. {$ifdef SUPPORT_MMX}
  615. LOC_CMMXREGISTER,
  616. LOC_MMXREGISTER:
  617. begin
  618. if loc=LOC_CMMXREGISTER then
  619. emit_reg_reg(A_MOVQ,S_NO,
  620. right.location.register,left.location.register)
  621. else
  622. emit_reg_ref(A_MOVQ,S_NO,
  623. right.location.register,newreference(left.location.reference));
  624. end;
  625. {$endif SUPPORT_MMX}
  626. LOC_REGISTER,
  627. LOC_CREGISTER : begin
  628. case right.resulttype^.size of
  629. 1 : opsize:=S_B;
  630. 2 : opsize:=S_W;
  631. 4 : opsize:=S_L;
  632. 8 : opsize:=S_L;
  633. end;
  634. { simplified with op_reg_loc }
  635. if loc=LOC_CREGISTER then
  636. begin
  637. emit_reg_reg(A_MOV,opsize,
  638. right.location.register,
  639. left.location.register);
  640. ungetregister(right.location.register);
  641. end
  642. else
  643. Begin
  644. emit_reg_ref(A_MOV,opsize,
  645. right.location.register,
  646. newreference(left.location.reference));
  647. ungetregister(right.location.register);
  648. {$IfDef regallocfix}
  649. del_reference(left.location.reference);
  650. {$EndIf regallocfix}
  651. end;
  652. if is_64bitint(right.resulttype) then
  653. begin
  654. { simplified with op_reg_loc }
  655. if loc=LOC_CREGISTER then
  656. emit_reg_reg(A_MOV,opsize,
  657. right.location.registerhigh,
  658. left.location.registerhigh)
  659. else
  660. begin
  661. r:=newreference(left.location.reference);
  662. inc(r^.offset,4);
  663. emit_reg_ref(A_MOV,opsize,
  664. right.location.registerhigh,r);
  665. end;
  666. end;
  667. {emit_reg_loc(A_MOV,opsize,
  668. right.location.register,
  669. left.location); }
  670. end;
  671. LOC_FPU : begin
  672. if (left.resulttype^.deftype=floatdef) then
  673. fputyp:=pfloatdef(left.resulttype)^.typ
  674. else
  675. if (right.resulttype^.deftype=floatdef) then
  676. fputyp:=pfloatdef(right.resulttype)^.typ
  677. else
  678. if (right.nodetype=typeconvn) and
  679. (ttypeconvnode(right).left.resulttype^.deftype=floatdef) then
  680. fputyp:=pfloatdef(ttypeconvnode(right).left.resulttype)^.typ
  681. else
  682. fputyp:=s32real;
  683. case loc of
  684. LOC_CFPUREGISTER:
  685. begin
  686. emit_reg(A_FSTP,S_NO,
  687. correct_fpuregister(left.location.register,fpuvaroffset));
  688. dec(fpuvaroffset);
  689. end;
  690. LOC_REFERENCE:
  691. floatstore(fputyp,left.location.reference);
  692. else
  693. internalerror(48991);
  694. end;
  695. end;
  696. LOC_CFPUREGISTER: begin
  697. if (left.resulttype^.deftype=floatdef) then
  698. fputyp:=pfloatdef(left.resulttype)^.typ
  699. else
  700. if (right.resulttype^.deftype=floatdef) then
  701. fputyp:=pfloatdef(right.resulttype)^.typ
  702. else
  703. if (right.nodetype=typeconvn) and
  704. (ttypeconvnode(right).left.resulttype^.deftype=floatdef) then
  705. fputyp:=pfloatdef(ttypeconvnode(right).left.resulttype)^.typ
  706. else
  707. fputyp:=s32real;
  708. emit_reg(A_FLD,S_NO,
  709. correct_fpuregister(right.location.register,fpuvaroffset));
  710. inc(fpuvaroffset);
  711. case loc of
  712. LOC_CFPUREGISTER:
  713. begin
  714. emit_reg(A_FSTP,S_NO,
  715. correct_fpuregister(right.location.register,fpuvaroffset));
  716. dec(fpuvaroffset);
  717. end;
  718. LOC_REFERENCE:
  719. floatstore(fputyp,left.location.reference);
  720. else
  721. internalerror(48992);
  722. end;
  723. end;
  724. LOC_JUMP : begin
  725. getlabel(hlabel);
  726. emitlab(truelabel);
  727. if pushed then
  728. restore(left,false);
  729. if loc=LOC_CREGISTER then
  730. emit_const_reg(A_MOV,S_B,
  731. 1,left.location.register)
  732. else
  733. emit_const_ref(A_MOV,S_B,
  734. 1,newreference(left.location.reference));
  735. {emit_const_loc(A_MOV,S_B,
  736. 1,left.location);}
  737. emitjmp(C_None,hlabel);
  738. emitlab(falselabel);
  739. if pushed then
  740. restore(left,false);
  741. if loc=LOC_CREGISTER then
  742. emit_reg_reg(A_XOR,S_B,
  743. left.location.register,
  744. left.location.register)
  745. else
  746. begin
  747. emit_const_ref(A_MOV,S_B,
  748. 0,newreference(left.location.reference));
  749. {$IfDef regallocfix}
  750. del_reference(left.location.reference);
  751. {$EndIf regallocfix}
  752. end;
  753. emitlab(hlabel);
  754. end;
  755. LOC_FLAGS : begin
  756. if loc=LOC_CREGISTER then
  757. emit_flag2reg(right.location.resflags,left.location.register)
  758. else
  759. begin
  760. ai:=new(paicpu,op_ref(A_Setcc,S_B,newreference(left.location.reference)));
  761. ai^.SetCondition(flag_2_cond[right.location.resflags]);
  762. exprasmlist^.concat(ai);
  763. end;
  764. {$IfDef regallocfix}
  765. del_reference(left.location.reference);
  766. {$EndIf regallocfix}
  767. end;
  768. end;
  769. truelabel:=otlabel;
  770. falselabel:=oflabel;
  771. end;
  772. {*****************************************************************************
  773. SecondFuncRet
  774. *****************************************************************************}
  775. procedure ti386funcretnode.pass_2;
  776. var
  777. hr : tregister;
  778. hp : preference;
  779. pp : pprocinfo;
  780. hr_valid : boolean;
  781. begin
  782. reset_reference(location.reference);
  783. hr_valid:=false;
  784. if (not inlining_procedure) and
  785. (procinfo<>pprocinfo(funcretprocinfo)) then
  786. begin
  787. hr:=getregister32;
  788. hr_valid:=true;
  789. hp:=new_reference(procinfo^.framepointer,
  790. procinfo^.framepointer_offset);
  791. emit_ref_reg(A_MOV,S_L,hp,hr);
  792. pp:=procinfo^.parent;
  793. { walk up the stack frame }
  794. while pp<>pprocinfo(funcretprocinfo) do
  795. begin
  796. hp:=new_reference(hr,
  797. pp^.framepointer_offset);
  798. emit_ref_reg(A_MOV,S_L,hp,hr);
  799. pp:=pp^.parent;
  800. end;
  801. location.reference.base:=hr;
  802. location.reference.offset:=pp^.return_offset;
  803. end
  804. else
  805. begin
  806. location.reference.base:=procinfo^.framepointer;
  807. location.reference.offset:=procinfo^.return_offset;
  808. end;
  809. if ret_in_param(rettype.def) then
  810. begin
  811. if not hr_valid then
  812. hr:=getregister32;
  813. emit_ref_reg(A_MOV,S_L,newreference(location.reference),hr);
  814. location.reference.base:=hr;
  815. location.reference.offset:=0;
  816. end;
  817. end;
  818. {*****************************************************************************
  819. SecondArrayConstruct
  820. *****************************************************************************}
  821. const
  822. vtInteger = 0;
  823. vtBoolean = 1;
  824. vtChar = 2;
  825. vtExtended = 3;
  826. vtString = 4;
  827. vtPointer = 5;
  828. vtPChar = 6;
  829. vtObject = 7;
  830. vtClass = 8;
  831. vtWideChar = 9;
  832. vtPWideChar = 10;
  833. vtAnsiString = 11;
  834. vtCurrency = 12;
  835. vtVariant = 13;
  836. vtInterface = 14;
  837. vtWideString = 15;
  838. vtInt64 = 16;
  839. vtQWord = 17;
  840. procedure ti386arrayconstructornode.pass_2;
  841. var
  842. hp : tarrayconstructornode;
  843. href : treference;
  844. lt : pdef;
  845. vaddr : boolean;
  846. vtype : longint;
  847. freetemp,
  848. dovariant : boolean;
  849. elesize : longint;
  850. begin
  851. dovariant:=(nf_forcevaria in flags) or parraydef(resulttype)^.isvariant;
  852. if dovariant then
  853. elesize:=8
  854. else
  855. begin
  856. elesize:=parraydef(resulttype)^.elesize;
  857. if elesize>4 then
  858. internalerror(8765678);
  859. end;
  860. if not(nf_cargs in flags) then
  861. begin
  862. reset_reference(location.reference);
  863. { Allocate always a temp, also if no elements are required, to
  864. be sure that location is valid (PFV) }
  865. if parraydef(resulttype)^.highrange=-1 then
  866. gettempofsizereference(elesize,location.reference)
  867. else
  868. gettempofsizereference((parraydef(resulttype)^.highrange+1)*elesize,location.reference);
  869. href:=location.reference;
  870. end;
  871. hp:=self;
  872. while assigned(hp) do
  873. begin
  874. if assigned(hp.left) then
  875. begin
  876. freetemp:=true;
  877. secondpass(hp.left);
  878. if codegenerror then
  879. exit;
  880. if dovariant then
  881. begin
  882. { find the correct vtype value }
  883. vtype:=$ff;
  884. vaddr:=false;
  885. lt:=hp.left.resulttype;
  886. case lt^.deftype of
  887. enumdef,
  888. orddef :
  889. begin
  890. if is_64bitint(lt) then
  891. begin
  892. case porddef(lt)^.typ of
  893. s64bit:
  894. vtype:=vtInt64;
  895. u64bit:
  896. vtype:=vtQWord;
  897. end;
  898. freetemp:=false;
  899. vaddr:=true;
  900. end
  901. else if (lt^.deftype=enumdef) or
  902. is_integer(lt) then
  903. vtype:=vtInteger
  904. else
  905. if is_boolean(lt) then
  906. vtype:=vtBoolean
  907. else
  908. if (lt^.deftype=orddef) and (porddef(lt)^.typ=uchar) then
  909. vtype:=vtChar;
  910. end;
  911. floatdef :
  912. begin
  913. vtype:=vtExtended;
  914. vaddr:=true;
  915. freetemp:=false;
  916. end;
  917. procvardef,
  918. pointerdef :
  919. begin
  920. if is_pchar(lt) then
  921. vtype:=vtPChar
  922. else
  923. vtype:=vtPointer;
  924. end;
  925. classrefdef :
  926. vtype:=vtClass;
  927. objectdef :
  928. begin
  929. vtype:=vtObject;
  930. end;
  931. stringdef :
  932. begin
  933. if is_shortstring(lt) then
  934. begin
  935. vtype:=vtString;
  936. vaddr:=true;
  937. freetemp:=false;
  938. end
  939. else
  940. if is_ansistring(lt) then
  941. begin
  942. vtype:=vtAnsiString;
  943. freetemp:=false;
  944. end;
  945. end;
  946. end;
  947. if vtype=$ff then
  948. internalerror(14357);
  949. { write C style pushes or an pascal array }
  950. if nf_cargs in flags then
  951. begin
  952. if vaddr then
  953. begin
  954. emit_to_mem(hp.left.location,hp.left.resulttype);
  955. emit_push_lea_loc(hp.left.location,freetemp);
  956. del_reference(hp.left.location.reference);
  957. end
  958. else
  959. emit_push_loc(hp.left.location);
  960. inc(pushedparasize);
  961. end
  962. else
  963. begin
  964. { write changing field update href to the next element }
  965. inc(href.offset,4);
  966. if vaddr then
  967. begin
  968. emit_to_mem(hp.left.location,hp.left.resulttype);
  969. emit_lea_loc_ref(hp.left.location,href,freetemp);
  970. end
  971. else
  972. begin
  973. emit_mov_loc_ref(hp.left.location,href,S_L,freetemp);
  974. end;
  975. { update href to the vtype field and write it }
  976. dec(href.offset,4);
  977. emit_const_ref(A_MOV,S_L,vtype,newreference(href));
  978. { goto next array element }
  979. inc(href.offset,8);
  980. end;
  981. end
  982. else
  983. { normal array constructor of the same type }
  984. begin
  985. case elesize of
  986. 1 :
  987. emit_mov_loc_ref(hp.left.location,href,S_B,freetemp);
  988. 2 :
  989. emit_mov_loc_ref(hp.left.location,href,S_W,freetemp);
  990. 4 :
  991. emit_mov_loc_ref(hp.left.location,href,S_L,freetemp);
  992. else
  993. internalerror(87656781);
  994. end;
  995. inc(href.offset,elesize);
  996. end;
  997. end;
  998. { load next entry }
  999. hp:=tarrayconstructornode(hp.right);
  1000. end;
  1001. end;
  1002. begin
  1003. cloadnode:=ti386loadnode;
  1004. cassignmentnode:=ti386assignmentnode;
  1005. cfuncretnode:=ti386funcretnode;
  1006. carrayconstructornode:=ti386arrayconstructornode;
  1007. end.
  1008. {
  1009. $Log$
  1010. Revision 1.3 2000-11-04 14:25:23 florian
  1011. + merged Attila's changes for interfaces, not tested yet
  1012. Revision 1.2 2000/10/31 22:02:56 peter
  1013. * symtable splitted, no real code changes
  1014. Revision 1.1 2000/10/15 09:33:31 peter
  1015. * moved n386*.pas to i386/ cpu_target dir
  1016. Revision 1.1 2000/10/14 10:14:49 peter
  1017. * moehrendorf oct 2000 rewrite
  1018. }