cg386ld.pas 45 KB

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