2
0

n386cnv.pas 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for type converting 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 n386cnv;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,ncnv,types;
  23. type
  24. ti386typeconvnode = class(ttypeconvnode)
  25. procedure second_int_to_int;virtual;
  26. procedure second_string_to_string;virtual;
  27. procedure second_cstring_to_pchar;virtual;
  28. procedure second_string_to_chararray;virtual;
  29. procedure second_array_to_pointer;virtual;
  30. procedure second_pointer_to_array;virtual;
  31. procedure second_chararray_to_string;virtual;
  32. procedure second_char_to_string;virtual;
  33. procedure second_int_to_real;virtual;
  34. procedure second_real_to_real;virtual;
  35. procedure second_cord_to_pointer;virtual;
  36. procedure second_proc_to_procvar;virtual;
  37. procedure second_bool_to_int;virtual;
  38. procedure second_int_to_bool;virtual;
  39. procedure second_load_smallset;virtual;
  40. procedure second_ansistring_to_pchar;virtual;
  41. procedure second_pchar_to_string;virtual;
  42. procedure second_class_to_intf;virtual;
  43. procedure second_char_to_char;virtual;
  44. procedure second_nothing;virtual;
  45. procedure pass_2;override;
  46. procedure second_call_helper(c : tconverttype);
  47. end;
  48. ti386asnode = class(tasnode)
  49. procedure pass_2;override;
  50. end;
  51. ti386isnode = class(tisnode)
  52. procedure pass_2;override;
  53. end;
  54. implementation
  55. uses
  56. verbose,globals,systems,
  57. symconst,symdef,aasm,
  58. hcodegen,temp_gen,pass_2,
  59. ncon,ncal,
  60. cpubase,cpuasm,
  61. cgai386,tgcpu,n386util;
  62. {*****************************************************************************
  63. SecondTypeConv
  64. *****************************************************************************}
  65. procedure ti386typeconvnode.second_int_to_int;
  66. var
  67. op : tasmop;
  68. opsize : topsize;
  69. hregister,
  70. hregister2 : tregister;
  71. l : tasmlabel;
  72. begin
  73. { insert range check if not explicit conversion }
  74. if not(nf_explizit in flags) then
  75. emitrangecheck(left,resulttype.def);
  76. { is the result size smaller ? }
  77. if resulttype.def.size<left.resulttype.def.size then
  78. begin
  79. { only need to set the new size of a register }
  80. if (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  81. begin
  82. case resulttype.def.size of
  83. 1 : location.register:=makereg8(left.location.register);
  84. 2 : location.register:=makereg16(left.location.register);
  85. 4 : location.register:=makereg32(left.location.register);
  86. end;
  87. { we can release the upper register }
  88. if is_64bitint(left.resulttype.def) then
  89. ungetregister32(left.location.registerhigh);
  90. end;
  91. end
  92. { is the result size bigger ? }
  93. else if resulttype.def.size>left.resulttype.def.size then
  94. begin
  95. { remove reference }
  96. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  97. begin
  98. del_reference(left.location.reference);
  99. { we can do this here as we need no temp inside }
  100. ungetiftemp(left.location.reference);
  101. end;
  102. { get op and opsize, handle separate for constants, because
  103. movz doesn't support constant values }
  104. if (left.location.loc=LOC_MEM) and (left.location.reference.is_immediate) then
  105. begin
  106. if is_64bitint(resulttype.def) then
  107. opsize:=S_L
  108. else
  109. opsize:=def_opsize(resulttype.def);
  110. op:=A_MOV;
  111. end
  112. else
  113. begin
  114. opsize:=def2def_opsize(left.resulttype.def,resulttype.def);
  115. if opsize in [S_B,S_W,S_L] then
  116. op:=A_MOV
  117. else
  118. if is_signed(left.resulttype.def) then
  119. op:=A_MOVSX
  120. else
  121. op:=A_MOVZX;
  122. end;
  123. { load the register we need }
  124. if left.location.loc<>LOC_REGISTER then
  125. hregister:=getregister32
  126. else
  127. hregister:=left.location.register;
  128. { set the correct register size and location }
  129. clear_location(location);
  130. location.loc:=LOC_REGISTER;
  131. { do we need a second register for a 64 bit type ? }
  132. if is_64bitint(resulttype.def) then
  133. begin
  134. hregister2:=getregister32;
  135. location.registerhigh:=hregister2;
  136. end;
  137. case resulttype.def.size of
  138. 1:
  139. location.register:=makereg8(hregister);
  140. 2:
  141. location.register:=makereg16(hregister);
  142. 4,8:
  143. location.register:=makereg32(hregister);
  144. end;
  145. { insert the assembler code }
  146. if left.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  147. emit_reg_reg(op,opsize,left.location.register,location.register)
  148. else
  149. emit_ref_reg(op,opsize,
  150. newreference(left.location.reference),location.register);
  151. { do we need a sign extension for int64? }
  152. if is_64bitint(resulttype.def) then
  153. { special case for constants (JM) }
  154. if is_constintnode(left) then
  155. begin
  156. if tordconstnode(left).value >= 0 then
  157. emit_reg_reg(A_XOR,S_L,
  158. hregister2,hregister2)
  159. else
  160. emit_const_reg(A_MOV,S_L,longint($ffffffff),hregister2);
  161. end
  162. else
  163. begin
  164. emit_reg_reg(A_XOR,S_L,
  165. hregister2,hregister2);
  166. if (torddef(resulttype.def).typ=s64bit) and
  167. is_signed(left.resulttype.def) then
  168. begin
  169. getlabel(l);
  170. emit_const_reg(A_TEST,S_L,longint($80000000),makereg32(hregister));
  171. emitjmp(C_Z,l);
  172. emit_reg(A_NOT,S_L,
  173. hregister2);
  174. emitlab(l);
  175. end;
  176. end;
  177. end;
  178. end;
  179. procedure ti386typeconvnode.second_string_to_string;
  180. var
  181. pushed : tpushed;
  182. regs_to_push: byte;
  183. begin
  184. { does anybody know a better solution than this big case statement ? }
  185. { ok, a proc table would do the job }
  186. case tstringdef(resulttype.def).string_typ of
  187. st_shortstring:
  188. case tstringdef(left.resulttype.def).string_typ of
  189. st_shortstring:
  190. begin
  191. gettempofsizereference(resulttype.def.size,location.reference);
  192. copyshortstring(location.reference,left.location.reference,
  193. tstringdef(resulttype.def).len,false,true);
  194. ungetiftemp(left.location.reference);
  195. end;
  196. st_ansistring:
  197. begin
  198. gettempofsizereference(resulttype.def.size,location.reference);
  199. loadansi2short(left,self);
  200. end;
  201. st_widestring:
  202. begin
  203. gettempofsizereference(resulttype.def.size,location.reference);
  204. loadwide2short(left,self);
  205. end;
  206. st_longstring:
  207. begin
  208. {!!!!!!!}
  209. internalerror(8888);
  210. end;
  211. end;
  212. st_ansistring:
  213. case tstringdef(left.resulttype.def).string_typ of
  214. st_shortstring:
  215. begin
  216. clear_location(location);
  217. location.loc:=LOC_REFERENCE;
  218. gettempansistringreference(location.reference);
  219. decrstringref(cansistringtype.def,location.reference);
  220. { We don't need the source regs anymore (JM) }
  221. regs_to_push := $ff;
  222. remove_non_regvars_from_loc(left.location,regs_to_push);
  223. pushusedregisters(pushed,regs_to_push);
  224. release_loc(left.location);
  225. emit_push_lea_loc(left.location,true);
  226. emit_push_lea_loc(location,false);
  227. saveregvars(regs_to_push);
  228. emitcall('FPC_SHORTSTR_TO_ANSISTR');
  229. maybe_loadself;
  230. popusedregisters(pushed);
  231. end;
  232. st_widestring:
  233. begin
  234. clear_location(location);
  235. location.loc:=LOC_REFERENCE;
  236. gettempansistringreference(location.reference);
  237. decrstringref(cansistringtype.def,location.reference);
  238. { We don't need the source regs anymore (JM) }
  239. regs_to_push := $ff;
  240. remove_non_regvars_from_loc(left.location,regs_to_push);
  241. pushusedregisters(pushed,regs_to_push);
  242. release_loc(left.location);
  243. emit_push_loc(left.location);
  244. emit_push_lea_loc(location,false);
  245. saveregvars(regs_to_push);
  246. emitcall('FPC_WIDESTR_TO_ANSISTR');
  247. maybe_loadself;
  248. popusedregisters(pushed);
  249. end;
  250. st_longstring:
  251. begin
  252. {!!!!!!!}
  253. internalerror(8888);
  254. end;
  255. end;
  256. st_widestring:
  257. case tstringdef(left.resulttype.def).string_typ of
  258. st_shortstring:
  259. begin
  260. clear_location(location);
  261. location.loc:=LOC_REFERENCE;
  262. gettempwidestringreference(location.reference);
  263. decrstringref(cwidestringtype.def,location.reference);
  264. { We don't need the source regs anymore (JM) }
  265. regs_to_push := $ff;
  266. remove_non_regvars_from_loc(left.location,regs_to_push);
  267. pushusedregisters(pushed,regs_to_push);
  268. release_loc(left.location);
  269. emit_push_lea_loc(left.location,true);
  270. emit_push_lea_loc(location,false);
  271. saveregvars(regs_to_push);
  272. emitcall('FPC_SHORTSTR_TO_WIDESTR');
  273. maybe_loadself;
  274. popusedregisters(pushed);
  275. end;
  276. st_ansistring:
  277. begin
  278. clear_location(location);
  279. location.loc:=LOC_REFERENCE;
  280. gettempwidestringreference(location.reference);
  281. decrstringref(cwidestringtype.def,location.reference);
  282. { We don't need the source regs anymore (JM) }
  283. regs_to_push := $ff;
  284. remove_non_regvars_from_loc(left.location,regs_to_push);
  285. pushusedregisters(pushed,regs_to_push);
  286. release_loc(left.location);
  287. emit_push_loc(left.location);
  288. emit_push_lea_loc(location,false);
  289. saveregvars(regs_to_push);
  290. emitcall('FPC_ANSISTR_TO_WIDESTR');
  291. maybe_loadself;
  292. popusedregisters(pushed);
  293. end;
  294. st_longstring:
  295. begin
  296. {!!!!!!!}
  297. internalerror(8888);
  298. end;
  299. end;
  300. st_longstring:
  301. case tstringdef(left.resulttype.def).string_typ of
  302. st_shortstring:
  303. begin
  304. {!!!!!!!}
  305. internalerror(8888);
  306. end;
  307. st_ansistring:
  308. begin
  309. {!!!!!!!}
  310. internalerror(8888);
  311. end;
  312. st_widestring:
  313. begin
  314. {!!!!!!!}
  315. internalerror(8888);
  316. end;
  317. end;
  318. end;
  319. end;
  320. procedure ti386typeconvnode.second_cstring_to_pchar;
  321. var
  322. hr : preference;
  323. begin
  324. clear_location(location);
  325. location.loc:=LOC_REGISTER;
  326. location.register:=getregister32;
  327. case tstringdef(left.resulttype.def).string_typ of
  328. st_shortstring :
  329. begin
  330. inc(left.location.reference.offset);
  331. emit_ref_reg(A_LEA,S_L,newreference(left.location.reference),
  332. location.register);
  333. end;
  334. st_ansistring :
  335. begin
  336. if (left.nodetype=stringconstn) and
  337. (str_length(left)=0) then
  338. begin
  339. new(hr);
  340. reset_reference(hr^);
  341. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  342. emit_ref_reg(A_LEA,S_L,hr,location.register);
  343. end
  344. else
  345. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  346. location.register);
  347. end;
  348. st_longstring:
  349. begin
  350. {!!!!!!!}
  351. internalerror(8888);
  352. end;
  353. st_widestring:
  354. begin
  355. if (left.nodetype=stringconstn) and
  356. (str_length(left)=0) then
  357. begin
  358. new(hr);
  359. reset_reference(hr^);
  360. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  361. emit_ref_reg(A_LEA,S_L,hr,location.register);
  362. end
  363. else
  364. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  365. location.register);
  366. end;
  367. end;
  368. end;
  369. procedure ti386typeconvnode.second_string_to_chararray;
  370. var
  371. pushedregs: tpushed;
  372. //l1 : tasmlabel;
  373. //hr : preference;
  374. arrsize, strtype: longint;
  375. regstopush: byte;
  376. begin
  377. with tarraydef(resulttype.def) do
  378. begin
  379. if highrange<lowrange then
  380. internalerror(75432653);
  381. arrsize := highrange-lowrange+1;
  382. end;
  383. if (left.nodetype = stringconstn) and
  384. { left.length+1 since there's always a terminating #0 character (JM) }
  385. (tstringconstnode(left).len+1 >= arrsize) and
  386. (tstringdef(left.resulttype.def).string_typ=st_shortstring) then
  387. begin
  388. inc(location.reference.offset);
  389. exit;
  390. end;
  391. clear_location(location);
  392. location.loc := LOC_REFERENCE;
  393. gettempofsizereference(arrsize,location.reference);
  394. regstopush := $ff;
  395. remove_non_regvars_from_loc(left.location,regstopush);
  396. pushusedregisters(pushedregs,regstopush);
  397. emit_push_lea_loc(location,false);
  398. case tstringdef(left.resulttype.def).string_typ of
  399. st_shortstring :
  400. begin
  401. { 0 means shortstring }
  402. strtype := 0;
  403. del_reference(left.location.reference);
  404. emit_push_lea_loc(left.location,true);
  405. ungetiftemp(left.location.reference);
  406. end;
  407. st_ansistring :
  408. begin
  409. { 1 means ansistring }
  410. strtype := 1;
  411. case left.location.loc of
  412. LOC_CREGISTER,LOC_REGISTER:
  413. begin
  414. ungetregister(left.location.register);
  415. emit_push_loc(left.location);
  416. end;
  417. LOC_MEM,LOC_REFERENCE:
  418. begin
  419. del_reference(left.location.reference);
  420. emit_push_loc(left.location);
  421. ungetiftemp(left.location.reference);
  422. end;
  423. end;
  424. end;
  425. st_longstring:
  426. begin
  427. {!!!!!!!}
  428. { 2 means longstring, but still needs support in FPC_STR_TO_CHARARRAY,
  429. which is in i386.inc and/or generic.inc (JM) }
  430. strtype := 2;
  431. internalerror(8888);
  432. end;
  433. st_widestring:
  434. begin
  435. {!!!!!!!}
  436. { 3 means widestring, but still needs support in FPC_STR_TO_CHARARRAY,
  437. which is in i386.inc and/or generic.inc (JM) }
  438. strtype := 3;
  439. internalerror(8888);
  440. end;
  441. end;
  442. push_int(arrsize);
  443. push_int(strtype);
  444. saveregvars(regstopush);
  445. emitcall('FPC_STR_TO_CHARARRAY');
  446. popusedregisters(pushedregs);
  447. end;
  448. procedure ti386typeconvnode.second_array_to_pointer;
  449. begin
  450. del_reference(left.location.reference);
  451. clear_location(location);
  452. location.loc:=LOC_REGISTER;
  453. location.register:=getregister32;
  454. emit_ref_reg(A_LEA,S_L,newreference(left.location.reference),
  455. location.register);
  456. end;
  457. procedure ti386typeconvnode.second_pointer_to_array;
  458. begin
  459. clear_location(location);
  460. location.loc:=LOC_REFERENCE;
  461. reset_reference(location.reference);
  462. case left.location.loc of
  463. LOC_REGISTER :
  464. location.reference.base:=left.location.register;
  465. LOC_CREGISTER :
  466. begin
  467. location.reference.base:=getregister32;
  468. emit_reg_reg(A_MOV,S_L,left.location.register,location.reference.base);
  469. end
  470. else
  471. begin
  472. del_reference(left.location.reference);
  473. location.reference.base:=getregister32;
  474. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  475. location.reference.base);
  476. end;
  477. end;
  478. end;
  479. { generates the code for the type conversion from an array of char }
  480. { to a string }
  481. procedure ti386typeconvnode.second_chararray_to_string;
  482. var
  483. pushed : tpushed;
  484. regstopush: byte;
  485. l : longint;
  486. begin
  487. { calc the length of the array }
  488. l:=tarraydef(left.resulttype.def).highrange-tarraydef(left.resulttype.def).lowrange+1;
  489. { this is a type conversion which copies the data, so we can't }
  490. { return a reference }
  491. clear_location(location);
  492. location.loc:=LOC_MEM;
  493. case tstringdef(resulttype.def).string_typ of
  494. st_shortstring :
  495. begin
  496. if l>255 then
  497. begin
  498. CGMessage(type_e_mismatch);
  499. l:=255;
  500. end;
  501. gettempofsizereference(resulttype.def.size,location.reference);
  502. { we've also to release the registers ... }
  503. { Yes, but before pushusedregisters since that one resets unused! }
  504. { This caused web bug 1073 (JM) }
  505. regstopush := $ff;
  506. remove_non_regvars_from_loc(left.location,regstopush);
  507. pushusedregisters(pushed,regstopush);
  508. if l>=resulttype.def.size then
  509. push_int(resulttype.def.size-1)
  510. else
  511. push_int(l);
  512. { ... here only the temp. location is released }
  513. emit_push_lea_loc(left.location,true);
  514. del_reference(left.location.reference);
  515. emitpushreferenceaddr(location.reference);
  516. saveregvars(regstopush);
  517. emitcall('FPC_CHARARRAY_TO_SHORTSTR');
  518. maybe_loadself;
  519. popusedregisters(pushed);
  520. end;
  521. st_ansistring :
  522. begin
  523. gettempansistringreference(location.reference);
  524. decrstringref(cansistringtype.def,location.reference);
  525. regstopush := $ff;
  526. remove_non_regvars_from_loc(left.location,regstopush);
  527. pushusedregisters(pushed,regstopush);
  528. push_int(l);
  529. emitpushreferenceaddr(left.location.reference);
  530. release_loc(left.location);
  531. emitpushreferenceaddr(location.reference);
  532. saveregvars(regstopush);
  533. emitcall('FPC_CHARARRAY_TO_ANSISTR');
  534. popusedregisters(pushed);
  535. maybe_loadself;
  536. end;
  537. st_widestring :
  538. begin
  539. gettempwidestringreference(location.reference);
  540. decrstringref(cwidestringtype.def,location.reference);
  541. regstopush := $ff;
  542. remove_non_regvars_from_loc(left.location,regstopush);
  543. pushusedregisters(pushed,regstopush);
  544. push_int(l);
  545. emitpushreferenceaddr(left.location.reference);
  546. release_loc(left.location);
  547. emitpushreferenceaddr(location.reference);
  548. saveregvars(regstopush);
  549. emitcall('FPC_CHARARRAY_TO_WIDESTR');
  550. popusedregisters(pushed);
  551. maybe_loadself;
  552. end;
  553. st_longstring:
  554. begin
  555. {!!!!!!!}
  556. internalerror(8888);
  557. end;
  558. end;
  559. end;
  560. procedure ti386typeconvnode.second_char_to_string;
  561. var
  562. pushed : tpushed;
  563. begin
  564. clear_location(location);
  565. location.loc:=LOC_MEM;
  566. case tstringdef(resulttype.def).string_typ of
  567. st_shortstring :
  568. begin
  569. gettempofsizereference(256,location.reference);
  570. loadshortstring(left,self);
  571. end;
  572. st_ansistring :
  573. begin
  574. gettempansistringreference(location.reference);
  575. decrstringref(cansistringtype.def,location.reference);
  576. release_loc(left.location);
  577. pushusedregisters(pushed,$ff);
  578. emit_pushw_loc(left.location);
  579. emitpushreferenceaddr(location.reference);
  580. saveregvars($ff);
  581. emitcall('FPC_CHAR_TO_ANSISTR');
  582. popusedregisters(pushed);
  583. maybe_loadself;
  584. end;
  585. st_widestring :
  586. begin
  587. gettempwidestringreference(location.reference);
  588. decrstringref(cwidestringtype.def,location.reference);
  589. release_loc(left.location);
  590. pushusedregisters(pushed,$ff);
  591. emit_pushw_loc(left.location);
  592. emitpushreferenceaddr(location.reference);
  593. saveregvars($ff);
  594. emitcall('FPC_CHAR_TO_WIDESTR');
  595. popusedregisters(pushed);
  596. maybe_loadself;
  597. end;
  598. else
  599. internalerror(4179);
  600. end;
  601. end;
  602. procedure ti386typeconvnode.second_int_to_real;
  603. var
  604. r : preference;
  605. hregister : tregister;
  606. l1,l2 : tasmlabel;
  607. begin
  608. { for u32bit a solution is to push $0 and to load a comp }
  609. { does this first, it destroys maybe EDI }
  610. hregister:=R_EDI;
  611. if torddef(left.resulttype.def).typ=u32bit then
  612. push_int(0);
  613. if (left.location.loc=LOC_REGISTER) or
  614. (left.location.loc=LOC_CREGISTER) then
  615. begin
  616. if not (torddef(left.resulttype.def).typ in [u32bit,s32bit,u64bit,s64bit]) then
  617. getexplicitregister32(R_EDI);
  618. case torddef(left.resulttype.def).typ of
  619. s8bit : emit_reg_reg(A_MOVSX,S_BL,left.location.register,R_EDI);
  620. u8bit : emit_reg_reg(A_MOVZX,S_BL,left.location.register,R_EDI);
  621. s16bit : emit_reg_reg(A_MOVSX,S_WL,left.location.register,R_EDI);
  622. u16bit : emit_reg_reg(A_MOVZX,S_WL,left.location.register,R_EDI);
  623. u32bit,s32bit:
  624. hregister:=left.location.register;
  625. u64bit,s64bit:
  626. begin
  627. emit_reg(A_PUSH,S_L,left.location.registerhigh);
  628. hregister:=left.location.registerlow;
  629. end;
  630. end;
  631. ungetregister(left.location.register);
  632. end
  633. else
  634. begin
  635. r:=newreference(left.location.reference);
  636. getexplicitregister32(R_EDI);
  637. case torddef(left.resulttype.def).typ of
  638. s8bit:
  639. emit_ref_reg(A_MOVSX,S_BL,r,R_EDI);
  640. u8bit:
  641. emit_ref_reg(A_MOVZX,S_BL,r,R_EDI);
  642. s16bit:
  643. emit_ref_reg(A_MOVSX,S_WL,r,R_EDI);
  644. u16bit:
  645. emit_ref_reg(A_MOVZX,S_WL,r,R_EDI);
  646. u32bit,s32bit:
  647. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  648. u64bit,s64bit:
  649. begin
  650. inc(r^.offset,4);
  651. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  652. emit_reg(A_PUSH,S_L,R_EDI);
  653. r:=newreference(left.location.reference);
  654. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  655. end;
  656. end;
  657. del_reference(left.location.reference);
  658. ungetiftemp(left.location.reference);
  659. end;
  660. { for 64 bit integers, the high dword is already pushed }
  661. emit_reg(A_PUSH,S_L,hregister);
  662. if hregister = R_EDI then
  663. ungetregister32(R_EDI);
  664. r:=new_reference(R_ESP,0);
  665. case torddef(left.resulttype.def).typ of
  666. u32bit:
  667. begin
  668. emit_ref(A_FILD,S_IQ,r);
  669. emit_const_reg(A_ADD,S_L,8,R_ESP);
  670. end;
  671. s64bit:
  672. begin
  673. emit_ref(A_FILD,S_IQ,r);
  674. emit_const_reg(A_ADD,S_L,8,R_ESP);
  675. end;
  676. u64bit:
  677. begin
  678. { unsigned 64 bit ints are harder to handle: }
  679. { we load bits 0..62 and then check bit 63: }
  680. { if it is 1 then we add $80000000 000000000 }
  681. { as double }
  682. inc(r^.offset,4);
  683. getexplicitregister32(R_EDI);
  684. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  685. r:=new_reference(R_ESP,4);
  686. emit_const_ref(A_AND,S_L,$7fffffff,r);
  687. emit_const_reg(A_TEST,S_L,longint($80000000),R_EDI);
  688. ungetregister32(R_EDI);
  689. r:=new_reference(R_ESP,0);
  690. emit_ref(A_FILD,S_IQ,r);
  691. getdatalabel(l1);
  692. getlabel(l2);
  693. emitjmp(C_Z,l2);
  694. Consts.concat(Tai_label.Create(l1));
  695. { I got this constant from a test progtram (FK) }
  696. Consts.concat(Tai_const.Create_32bit(0));
  697. Consts.concat(Tai_const.Create_32bit(1138753536));
  698. r:=new_reference(R_NO,0);
  699. r^.symbol:=l1;
  700. emit_ref(A_FADD,S_FL,r);
  701. emitlab(l2);
  702. emit_const_reg(A_ADD,S_L,8,R_ESP);
  703. end
  704. else
  705. begin
  706. emit_ref(A_FILD,S_IL,r);
  707. getexplicitregister32(R_EDI);
  708. emit_reg(A_POP,S_L,R_EDI);
  709. ungetregister32(R_EDI);
  710. end;
  711. end;
  712. inc(fpuvaroffset);
  713. clear_location(location);
  714. location.loc:=LOC_FPU;
  715. end;
  716. procedure ti386typeconvnode.second_real_to_real;
  717. begin
  718. case left.location.loc of
  719. LOC_FPU : ;
  720. LOC_CFPUREGISTER:
  721. begin
  722. location:=left.location;
  723. exit;
  724. end;
  725. LOC_MEM,
  726. LOC_REFERENCE:
  727. begin
  728. floatload(tfloatdef(left.resulttype.def).typ,
  729. left.location.reference);
  730. { we have to free the reference }
  731. del_reference(left.location.reference);
  732. end;
  733. end;
  734. clear_location(location);
  735. location.loc:=LOC_FPU;
  736. end;
  737. procedure ti386typeconvnode.second_cord_to_pointer;
  738. begin
  739. { this can't happend, because constants are already processed in
  740. pass 1 }
  741. internalerror(47423985);
  742. end;
  743. procedure ti386typeconvnode.second_proc_to_procvar;
  744. begin
  745. { method pointer ? }
  746. if assigned(tcallnode(left).left) then
  747. begin
  748. set_location(location,left.location);
  749. end
  750. else
  751. begin
  752. clear_location(location);
  753. location.loc:=LOC_REGISTER;
  754. location.register:=getregister32;
  755. del_reference(left.location.reference);
  756. emit_ref_reg(A_LEA,S_L,
  757. newreference(left.location.reference),location.register);
  758. end;
  759. end;
  760. procedure ti386typeconvnode.second_bool_to_int;
  761. var
  762. oldtruelabel,oldfalselabel,hlabel : tasmlabel;
  763. hregister : tregister;
  764. newsize,
  765. opsize : topsize;
  766. op : tasmop;
  767. begin
  768. oldtruelabel:=truelabel;
  769. oldfalselabel:=falselabel;
  770. getlabel(truelabel);
  771. getlabel(falselabel);
  772. secondpass(left);
  773. { byte(boolean) or word(wordbool) or longint(longbool) must
  774. be accepted for var parameters }
  775. if (nf_explizit in flags) and
  776. (left.resulttype.def.size=resulttype.def.size) and
  777. (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  778. begin
  779. set_location(location,left.location);
  780. truelabel:=oldtruelabel;
  781. falselabel:=oldfalselabel;
  782. exit;
  783. end;
  784. clear_location(location);
  785. location.loc:=LOC_REGISTER;
  786. del_reference(left.location.reference);
  787. case left.resulttype.def.size of
  788. 1 : begin
  789. case resulttype.def.size of
  790. 1 : opsize:=S_B;
  791. 2 : opsize:=S_BW;
  792. 4 : opsize:=S_BL;
  793. end;
  794. end;
  795. 2 : begin
  796. case resulttype.def.size of
  797. 1 : begin
  798. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  799. left.location.register:=reg16toreg8(left.location.register);
  800. opsize:=S_B;
  801. end;
  802. 2 : opsize:=S_W;
  803. 4 : opsize:=S_WL;
  804. end;
  805. end;
  806. 4 : begin
  807. case resulttype.def.size of
  808. 1 : begin
  809. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  810. left.location.register:=reg32toreg8(left.location.register);
  811. opsize:=S_B;
  812. end;
  813. 2 : begin
  814. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  815. left.location.register:=reg32toreg16(left.location.register);
  816. opsize:=S_W;
  817. end;
  818. 4 : opsize:=S_L;
  819. end;
  820. end;
  821. end;
  822. if opsize in [S_B,S_W,S_L] then
  823. op:=A_MOV
  824. else
  825. if is_signed(resulttype.def) then
  826. op:=A_MOVSX
  827. else
  828. op:=A_MOVZX;
  829. hregister:=getregister32;
  830. case resulttype.def.size of
  831. 1 : begin
  832. location.register:=reg32toreg8(hregister);
  833. newsize:=S_B;
  834. end;
  835. 2 : begin
  836. location.register:=reg32toreg16(hregister);
  837. newsize:=S_W;
  838. end;
  839. 4 : begin
  840. location.register:=hregister;
  841. newsize:=S_L;
  842. end;
  843. else
  844. internalerror(10060);
  845. end;
  846. case left.location.loc of
  847. LOC_MEM,
  848. LOC_REFERENCE : emit_ref_reg(op,opsize,
  849. newreference(left.location.reference),location.register);
  850. LOC_REGISTER,
  851. LOC_CREGISTER : begin
  852. { remove things like movb %al,%al }
  853. if left.location.register<>location.register then
  854. emit_reg_reg(op,opsize,
  855. left.location.register,location.register);
  856. end;
  857. LOC_FLAGS : begin
  858. emit_flag2reg(left.location.resflags,location.register);
  859. end;
  860. LOC_JUMP : begin
  861. getlabel(hlabel);
  862. emitlab(truelabel);
  863. emit_const_reg(A_MOV,newsize,1,location.register);
  864. emitjmp(C_None,hlabel);
  865. emitlab(falselabel);
  866. emit_reg_reg(A_XOR,newsize,location.register,
  867. location.register);
  868. emitlab(hlabel);
  869. end;
  870. else
  871. internalerror(10061);
  872. end;
  873. truelabel:=oldtruelabel;
  874. falselabel:=oldfalselabel;
  875. end;
  876. procedure ti386typeconvnode.second_int_to_bool;
  877. var
  878. hregister : tregister;
  879. resflags : tresflags;
  880. opsize : topsize;
  881. begin
  882. clear_location(location);
  883. { byte(boolean) or word(wordbool) or longint(longbool) must
  884. be accepted for var parameters }
  885. if (nf_explizit in flags) and
  886. (left.resulttype.def.size=resulttype.def.size) and
  887. (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  888. begin
  889. set_location(location,left.location);
  890. exit;
  891. end;
  892. location.loc:=LOC_REGISTER;
  893. del_reference(left.location.reference);
  894. opsize:=def_opsize(left.resulttype.def);
  895. case left.location.loc of
  896. LOC_MEM,LOC_REFERENCE :
  897. begin
  898. hregister:=def_getreg(left.resulttype.def);
  899. emit_ref_reg(A_MOV,opsize,
  900. newreference(left.location.reference),hregister);
  901. emit_reg_reg(A_OR,opsize,hregister,hregister);
  902. resflags:=F_NE;
  903. end;
  904. LOC_FLAGS :
  905. begin
  906. hregister:=getregister32;
  907. resflags:=left.location.resflags;
  908. end;
  909. LOC_REGISTER,LOC_CREGISTER :
  910. begin
  911. hregister:=left.location.register;
  912. emit_reg_reg(A_OR,opsize,hregister,hregister);
  913. resflags:=F_NE;
  914. end;
  915. else
  916. internalerror(10062);
  917. end;
  918. case resulttype.def.size of
  919. 1 : location.register:=makereg8(hregister);
  920. 2 : location.register:=makereg16(hregister);
  921. 4 : location.register:=makereg32(hregister);
  922. else
  923. internalerror(10064);
  924. end;
  925. emit_flag2reg(resflags,location.register);
  926. end;
  927. procedure ti386typeconvnode.second_load_smallset;
  928. var
  929. href : treference;
  930. pushedregs : tpushed;
  931. begin
  932. href.symbol:=nil;
  933. pushusedregisters(pushedregs,$ff);
  934. gettempofsizereference(32,href);
  935. emit_push_mem_size(left.location.reference,4);
  936. emitpushreferenceaddr(href);
  937. saveregvars($ff);
  938. emitcall('FPC_SET_LOAD_SMALL');
  939. maybe_loadself;
  940. popusedregisters(pushedregs);
  941. clear_location(location);
  942. location.loc:=LOC_MEM;
  943. location.reference:=href;
  944. end;
  945. procedure ti386typeconvnode.second_ansistring_to_pchar;
  946. var
  947. l1 : tasmlabel;
  948. hr : preference;
  949. begin
  950. clear_location(location);
  951. location.loc:=LOC_REGISTER;
  952. getlabel(l1);
  953. case left.location.loc of
  954. LOC_CREGISTER,LOC_REGISTER:
  955. location.register:=left.location.register;
  956. LOC_MEM,LOC_REFERENCE:
  957. begin
  958. location.register:=getregister32;
  959. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  960. location.register);
  961. del_reference(left.location.reference);
  962. end;
  963. end;
  964. emit_const_reg(A_CMP,S_L,0,location.register);
  965. emitjmp(C_NZ,l1);
  966. new(hr);
  967. reset_reference(hr^);
  968. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  969. emit_ref_reg(A_LEA,S_L,hr,location.register);
  970. emitlab(l1);
  971. end;
  972. procedure ti386typeconvnode.second_pchar_to_string;
  973. var
  974. pushed : tpushed;
  975. regs_to_push: byte;
  976. begin
  977. case tstringdef(resulttype.def).string_typ of
  978. st_shortstring:
  979. begin
  980. location.loc:=LOC_REFERENCE;
  981. gettempofsizereference(resulttype.def.size,location.reference);
  982. pushusedregisters(pushed,$ff);
  983. case left.location.loc of
  984. LOC_REGISTER,LOC_CREGISTER:
  985. begin
  986. emit_reg(A_PUSH,S_L,left.location.register);
  987. ungetregister32(left.location.register);
  988. end;
  989. LOC_REFERENCE,LOC_MEM:
  990. begin
  991. { Now release the registers (see cgai386.pas: }
  992. { loadansistring for more info on the order) (JM) }
  993. del_reference(left.location.reference);
  994. emit_push_mem(left.location.reference);
  995. end;
  996. end;
  997. emitpushreferenceaddr(location.reference);
  998. saveregvars($ff);
  999. emitcall('FPC_PCHAR_TO_SHORTSTR');
  1000. maybe_loadself;
  1001. popusedregisters(pushed);
  1002. end;
  1003. st_ansistring:
  1004. begin
  1005. location.loc:=LOC_REFERENCE;
  1006. gettempansistringreference(location.reference);
  1007. decrstringref(cansistringtype.def,location.reference);
  1008. { Find out which regs have to be pushed (JM) }
  1009. regs_to_push := $ff;
  1010. remove_non_regvars_from_loc(left.location,regs_to_push);
  1011. pushusedregisters(pushed,regs_to_push);
  1012. case left.location.loc of
  1013. LOC_REFERENCE,LOC_MEM:
  1014. begin
  1015. { Now release the registers (see cgai386.pas: }
  1016. { loadansistring for more info on the order) (JM) }
  1017. del_reference(left.location.reference);
  1018. emit_push_mem(left.location.reference);
  1019. end;
  1020. LOC_REGISTER,LOC_CREGISTER:
  1021. begin
  1022. { Now release the registers (see cgai386.pas: }
  1023. { loadansistring for more info on the order) (JM) }
  1024. emit_reg(A_PUSH,S_L,left.location.register);
  1025. ungetregister32(left.location.register);
  1026. end;
  1027. end;
  1028. emitpushreferenceaddr(location.reference);
  1029. saveregvars(regs_to_push);
  1030. emitcall('FPC_PCHAR_TO_ANSISTR');
  1031. maybe_loadself;
  1032. popusedregisters(pushed);
  1033. end;
  1034. st_widestring:
  1035. begin
  1036. location.loc:=LOC_REFERENCE;
  1037. gettempwidestringreference(location.reference);
  1038. decrstringref(cwidestringtype.def,location.reference);
  1039. { Find out which regs have to be pushed (JM) }
  1040. regs_to_push := $ff;
  1041. remove_non_regvars_from_loc(left.location,regs_to_push);
  1042. pushusedregisters(pushed,regs_to_push);
  1043. case left.location.loc of
  1044. LOC_REFERENCE,LOC_MEM:
  1045. begin
  1046. { Now release the registers (see cgai386.pas: }
  1047. { loadansistring for more info on the order) (JM) }
  1048. del_reference(left.location.reference);
  1049. emit_push_mem(left.location.reference);
  1050. end;
  1051. LOC_REGISTER,LOC_CREGISTER:
  1052. begin
  1053. { Now release the registers (see cgai386.pas: }
  1054. { loadansistring for more info on the order) (JM) }
  1055. emit_reg(A_PUSH,S_L,left.location.register);
  1056. ungetregister32(left.location.register);
  1057. end;
  1058. end;
  1059. emitpushreferenceaddr(location.reference);
  1060. saveregvars(regs_to_push);
  1061. emitcall('FPC_PCHAR_TO_WIDESTR');
  1062. maybe_loadself;
  1063. popusedregisters(pushed);
  1064. end;
  1065. else
  1066. begin
  1067. internalerror(12121);
  1068. end;
  1069. end;
  1070. end;
  1071. procedure ti386typeconvnode.second_class_to_intf;
  1072. var
  1073. hreg : tregister;
  1074. l1 : tasmlabel;
  1075. begin
  1076. case left.location.loc of
  1077. LOC_MEM,
  1078. LOC_REFERENCE:
  1079. begin
  1080. del_reference(left.location.reference);
  1081. hreg:=getregister32;
  1082. exprasmList.concat(Taicpu.Op_ref_reg(
  1083. A_MOV,S_L,newreference(left.location.reference),hreg));
  1084. end;
  1085. LOC_CREGISTER:
  1086. begin
  1087. hreg:=getregister32;
  1088. exprasmList.concat(Taicpu.Op_reg_reg(
  1089. A_MOV,S_L,left.location.register,hreg));
  1090. end;
  1091. LOC_REGISTER:
  1092. hreg:=left.location.register;
  1093. else internalerror(121120001);
  1094. end;
  1095. emit_reg_reg(A_TEST,S_L,hreg,hreg);
  1096. getlabel(l1);
  1097. emitjmp(C_Z,l1);
  1098. emit_const_reg(A_ADD,S_L,tobjectdef(left.resulttype.def).implementedinterfaces.ioffsets(
  1099. tobjectdef(left.resulttype.def).implementedinterfaces.searchintf(resulttype.def))^,hreg);
  1100. emitlab(l1);
  1101. location.loc:=LOC_REGISTER;
  1102. location.register:=hreg;
  1103. end;
  1104. procedure ti386typeconvnode.second_char_to_char;
  1105. begin
  1106. {$warning todo: add RTL routine for widechar-char conversion }
  1107. { Quick hack to atleast generate 'working' code (PFV) }
  1108. second_int_to_int;
  1109. end;
  1110. procedure ti386typeconvnode.second_nothing;
  1111. begin
  1112. end;
  1113. {****************************************************************************
  1114. TI386TYPECONVNODE
  1115. ****************************************************************************}
  1116. procedure ti386typeconvnode.second_call_helper(c : tconverttype);
  1117. const
  1118. secondconvert : array[tconverttype] of pointer = (
  1119. @ti386typeconvnode.second_nothing, {equal}
  1120. @ti386typeconvnode.second_nothing, {not_possible}
  1121. @ti386typeconvnode.second_string_to_string,
  1122. @ti386typeconvnode.second_char_to_string,
  1123. @ti386typeconvnode.second_pchar_to_string,
  1124. @ti386typeconvnode.second_nothing, {cchar_to_pchar}
  1125. @ti386typeconvnode.second_cstring_to_pchar,
  1126. @ti386typeconvnode.second_ansistring_to_pchar,
  1127. @ti386typeconvnode.second_string_to_chararray,
  1128. @ti386typeconvnode.second_chararray_to_string,
  1129. @ti386typeconvnode.second_array_to_pointer,
  1130. @ti386typeconvnode.second_pointer_to_array,
  1131. @ti386typeconvnode.second_int_to_int,
  1132. @ti386typeconvnode.second_int_to_bool,
  1133. @ti386typeconvnode.second_bool_to_int, { bool_to_bool }
  1134. @ti386typeconvnode.second_bool_to_int,
  1135. @ti386typeconvnode.second_real_to_real,
  1136. @ti386typeconvnode.second_int_to_real,
  1137. @ti386typeconvnode.second_proc_to_procvar,
  1138. @ti386typeconvnode.second_nothing, {arrayconstructor_to_set}
  1139. @ti386typeconvnode.second_load_smallset,
  1140. @ti386typeconvnode.second_cord_to_pointer,
  1141. @ti386typeconvnode.second_nothing, { interface 2 string }
  1142. @ti386typeconvnode.second_nothing, { interface 2 guid }
  1143. @ti386typeconvnode.second_class_to_intf,
  1144. @ti386typeconvnode.second_char_to_char
  1145. );
  1146. type
  1147. tprocedureofobject = procedure of object;
  1148. var
  1149. r : packed record
  1150. proc : pointer;
  1151. obj : pointer;
  1152. end;
  1153. begin
  1154. { this is a little bit dirty but it works }
  1155. { and should be quite portable too }
  1156. r.proc:=secondconvert[c];
  1157. r.obj:=self;
  1158. tprocedureofobject(r){$ifdef FPC}();{$endif FPC}
  1159. end;
  1160. procedure ti386typeconvnode.pass_2;
  1161. {$ifdef TESTOBJEXT2}
  1162. var
  1163. r : preference;
  1164. nillabel : plabel;
  1165. {$endif TESTOBJEXT2}
  1166. begin
  1167. { this isn't good coding, I think tc_bool_2_int, shouldn't be }
  1168. { type conversion (FK) }
  1169. if not(convtype in [tc_bool_2_int,tc_bool_2_bool]) then
  1170. begin
  1171. secondpass(left);
  1172. set_location(location,left.location);
  1173. if codegenerror then
  1174. exit;
  1175. end;
  1176. second_call_helper(convtype);
  1177. {$ifdef TESTOBJEXT2}
  1178. { Check explicit conversions to objects pointers !! }
  1179. if p^.explizit and
  1180. (p^.resulttype.def.deftype=pointerdef) and
  1181. (tpointerdef(p^.resulttype.def).definition.deftype=objectdef) and not
  1182. (tobjectdef(tpointerdef(p^.resulttype.def).definition).isclass) and
  1183. ((tobjectdef(tpointerdef(p^.resulttype.def).definition).options and oo_hasvmt)<>0) and
  1184. (cs_check_range in aktlocalswitches) then
  1185. begin
  1186. new(r);
  1187. reset_reference(r^);
  1188. if p^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1189. r^.base:=p^.location.register
  1190. else
  1191. begin
  1192. getexplicitregister32(R_EDI);
  1193. emit_mov_loc_reg(p^.location,R_EDI);
  1194. r^.base:=R_EDI;
  1195. end;
  1196. { NIL must be accepted !! }
  1197. emit_reg_reg(A_OR,S_L,r^.base,r^.base);
  1198. ungetregister32(R_EDI);
  1199. getlabel(nillabel);
  1200. emitjmp(C_E,nillabel);
  1201. { this is one point where we need vmt_offset (PM) }
  1202. r^.offset:= tobjectdef(tpointerdef(p^.resulttype.def).definition).vmt_offset;
  1203. getexplicitregister32(R_EDI);
  1204. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  1205. emit_sym(A_PUSH,S_L,
  1206. newasmsymbol(tobjectdef(tpointerdef(p^.resulttype.def).definition).vmt_mangledname));
  1207. emit_reg(A_PUSH,S_L,R_EDI);
  1208. ungetregister32(R_EDI);
  1209. emitcall('FPC_CHECK_OBJECT_EXT');
  1210. emitlab(nillabel);
  1211. end;
  1212. {$endif TESTOBJEXT2}
  1213. end;
  1214. {*****************************************************************************
  1215. TI386ISNODE
  1216. *****************************************************************************}
  1217. procedure ti386isnode.pass_2;
  1218. var
  1219. pushed : tpushed;
  1220. begin
  1221. { save all used registers }
  1222. pushusedregisters(pushed,$ff);
  1223. secondpass(left);
  1224. clear_location(location);
  1225. location.loc:=LOC_FLAGS;
  1226. location.resflags:=F_NE;
  1227. { push instance to check: }
  1228. case left.location.loc of
  1229. LOC_REGISTER,LOC_CREGISTER:
  1230. begin
  1231. emit_reg(A_PUSH,
  1232. S_L,left.location.register);
  1233. ungetregister32(left.location.register);
  1234. end;
  1235. LOC_MEM,LOC_REFERENCE:
  1236. begin
  1237. emit_ref(A_PUSH,
  1238. S_L,newreference(left.location.reference));
  1239. del_reference(left.location.reference);
  1240. end;
  1241. else internalerror(100);
  1242. end;
  1243. { generate type checking }
  1244. secondpass(right);
  1245. case right.location.loc of
  1246. LOC_REGISTER,LOC_CREGISTER:
  1247. begin
  1248. emit_reg(A_PUSH,
  1249. S_L,right.location.register);
  1250. ungetregister32(right.location.register);
  1251. end;
  1252. LOC_MEM,LOC_REFERENCE:
  1253. begin
  1254. emit_ref(A_PUSH,
  1255. S_L,newreference(right.location.reference));
  1256. del_reference(right.location.reference);
  1257. end;
  1258. else internalerror(100);
  1259. end;
  1260. saveregvars($ff);
  1261. emitcall('FPC_DO_IS');
  1262. emit_reg_reg(A_OR,S_B,R_AL,R_AL);
  1263. popusedregisters(pushed);
  1264. maybe_loadself;
  1265. end;
  1266. {*****************************************************************************
  1267. TI386ASNODE
  1268. *****************************************************************************}
  1269. procedure ti386asnode.pass_2;
  1270. var
  1271. pushed : tpushed;
  1272. begin
  1273. secondpass(left);
  1274. { save all used registers }
  1275. pushusedregisters(pushed,$ff);
  1276. { push instance to check: }
  1277. case left.location.loc of
  1278. LOC_REGISTER,LOC_CREGISTER:
  1279. emit_reg(A_PUSH,
  1280. S_L,left.location.register);
  1281. LOC_MEM,LOC_REFERENCE:
  1282. emit_ref(A_PUSH,
  1283. S_L,newreference(left.location.reference));
  1284. else internalerror(100);
  1285. end;
  1286. { we doesn't modifiy the left side, we check only the type }
  1287. set_location(location,left.location);
  1288. { generate type checking }
  1289. secondpass(right);
  1290. case right.location.loc of
  1291. LOC_REGISTER,LOC_CREGISTER:
  1292. begin
  1293. emit_reg(A_PUSH,
  1294. S_L,right.location.register);
  1295. ungetregister32(right.location.register);
  1296. end;
  1297. LOC_MEM,LOC_REFERENCE:
  1298. begin
  1299. emit_ref(A_PUSH,
  1300. S_L,newreference(right.location.reference));
  1301. del_reference(right.location.reference);
  1302. end;
  1303. else internalerror(100);
  1304. end;
  1305. saveregvars($ff);
  1306. emitcall('FPC_DO_AS');
  1307. { restore register, this restores automatically the }
  1308. { result }
  1309. popusedregisters(pushed);
  1310. maybe_loadself;
  1311. end;
  1312. begin
  1313. ctypeconvnode:=ti386typeconvnode;
  1314. cisnode:=ti386isnode;
  1315. casnode:=ti386asnode;
  1316. end.
  1317. {
  1318. $Log$
  1319. Revision 1.16 2001-07-08 21:00:17 peter
  1320. * various widestring updates, it works now mostly without charset
  1321. mapping supported
  1322. Revision 1.15 2001/05/08 21:06:33 florian
  1323. * some more support for widechars commited especially
  1324. regarding type casting and constants
  1325. Revision 1.14 2001/04/13 01:22:18 peter
  1326. * symtable change to classes
  1327. * range check generation and errors fixed, make cycle DEBUG=1 works
  1328. * memory leaks fixed
  1329. Revision 1.13 2001/04/02 21:20:36 peter
  1330. * resulttype rewrite
  1331. Revision 1.12 2001/01/08 21:45:11 peter
  1332. * internalerror for string to chararray
  1333. Revision 1.11 2000/12/25 00:07:32 peter
  1334. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1335. tlinkedlist objects)
  1336. Revision 1.10 2000/12/07 17:19:46 jonas
  1337. * new constant handling: from now on, hex constants >$7fffffff are
  1338. parsed as unsigned constants (otherwise, $80000000 got sign extended
  1339. and became $ffffffff80000000), all constants in the longint range
  1340. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  1341. are cardinals and the rest are int64's.
  1342. * added lots of longint typecast to prevent range check errors in the
  1343. compiler and rtl
  1344. * type casts of symbolic ordinal constants are now preserved
  1345. * fixed bug where the original resulttype.def wasn't restored correctly
  1346. after doing a 64bit rangecheck
  1347. Revision 1.9 2000/12/05 11:44:33 jonas
  1348. + new integer regvar handling, should be much more efficient
  1349. Revision 1.8 2000/11/29 00:30:46 florian
  1350. * unused units removed from uses clause
  1351. * some changes for widestrings
  1352. Revision 1.7 2000/11/16 15:27:48 jonas
  1353. * fixed web bug 1242
  1354. Revision 1.6 2000/11/13 11:30:56 florian
  1355. * some bugs with interfaces and NIL fixed
  1356. Revision 1.5 2000/11/12 23:24:14 florian
  1357. * interfaces are basically running
  1358. Revision 1.4 2000/11/11 16:00:10 jonas
  1359. * optimize converting of 8/16/32 bit constants to 64bit ones
  1360. Revision 1.3 2000/11/04 14:25:23 florian
  1361. + merged Attila's changes for interfaces, not tested yet
  1362. Revision 1.2 2000/10/31 22:02:56 peter
  1363. * symtable splitted, no real code changes
  1364. Revision 1.1 2000/10/15 09:33:31 peter
  1365. * moved n386*.pas to i386/ cpu_target dir
  1366. Revision 1.1 2000/10/14 10:14:48 peter
  1367. * moehrendorf oct 2000 rewrite
  1368. }