cg386ld.pas 47 KB

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