cg386ld.pas 47 KB

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