cg386ld.pas 48 KB

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