cg386cnv.pas 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627
  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. {$ifdef TP}
  19. {$E+,F+,N+,D+,L+,Y+}
  20. {$endif}
  21. unit cg386cnv;
  22. interface
  23. uses
  24. tree;
  25. procedure loadshortstring(p:ptree);
  26. procedure loadlongstring(p:ptree);
  27. procedure loadansi2short(source,dest : ptree);
  28. procedure secondtypeconv(var p : ptree);
  29. procedure secondas(var p : ptree);
  30. procedure secondis(var p : ptree);
  31. implementation
  32. uses
  33. cobjects,verbose,globtype,globals,systems,
  34. symconst,symtable,aasm,types,
  35. hcodegen,temp_gen,pass_2,pass_1,
  36. cpubase,cpuasm,
  37. cgai386,tgeni386;
  38. procedure push_shortstring_length(p:ptree);
  39. var
  40. hightree : ptree;
  41. begin
  42. if is_open_string(p^.resulttype) then
  43. begin
  44. getsymonlyin(p^.symtable,'high'+pvarsym(p^.symtableentry)^.name);
  45. hightree:=genloadnode(pvarsym(srsym),p^.symtable);
  46. firstpass(hightree);
  47. secondpass(hightree);
  48. push_value_para(hightree,false,false,0,4);
  49. disposetree(hightree);
  50. end
  51. else
  52. begin
  53. push_int(pstringdef(p^.resulttype)^.len);
  54. end;
  55. end;
  56. procedure loadshortstring(p:ptree);
  57. {
  58. Load a string, handles stringdef and orddef (char) types
  59. }
  60. begin
  61. case p^.right^.resulttype^.deftype of
  62. stringdef:
  63. begin
  64. if (p^.right^.treetype=stringconstn) and
  65. (str_length(p^.right)=0) then
  66. emit_const_ref(
  67. A_MOV,S_B,0,newreference(p^.left^.location.reference))
  68. else
  69. begin
  70. emitpushreferenceaddr(p^.left^.location.reference);
  71. emitpushreferenceaddr(p^.right^.location.reference);
  72. push_shortstring_length(p^.left);
  73. emitcall('FPC_SHORTSTR_COPY');
  74. maybe_loadesi;
  75. end;
  76. end;
  77. orddef:
  78. begin
  79. if p^.right^.treetype=ordconstn then
  80. emit_const_ref(
  81. A_MOV,S_W,p^.right^.value*256+1,newreference(p^.left^.location.reference))
  82. else
  83. begin
  84. { not so elegant (goes better with extra register }
  85. {$ifndef noAllocEdi}
  86. getexplicitregister32(R_EDI);
  87. {$endif noAllocEdi}
  88. if (p^.right^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  89. begin
  90. emit_reg_reg(A_MOV,S_L,makereg32(p^.right^.location.register),R_EDI);
  91. ungetregister(p^.right^.location.register);
  92. end
  93. else
  94. begin
  95. emit_ref_reg(A_MOV,S_L,newreference(p^.right^.location.reference),R_EDI);
  96. del_reference(p^.right^.location.reference);
  97. end;
  98. emit_const_reg(A_SHL,S_L,8,R_EDI);
  99. emit_const_reg(A_OR,S_L,1,R_EDI);
  100. emit_reg_ref(A_MOV,S_W,R_DI,newreference(p^.left^.location.reference));
  101. {$ifndef noAllocEdi}
  102. ungetregister32(R_EDI);
  103. {$endif noAllocEdi}
  104. end;
  105. end;
  106. else
  107. CGMessage(type_e_mismatch);
  108. end;
  109. end;
  110. procedure loadlongstring(p:ptree);
  111. {
  112. Load a string, handles stringdef and orddef (char) types
  113. }
  114. var
  115. r : preference;
  116. begin
  117. case p^.right^.resulttype^.deftype of
  118. stringdef:
  119. begin
  120. if (p^.right^.treetype=stringconstn) and
  121. (str_length(p^.right)=0) then
  122. emit_const_ref(A_MOV,S_L,0,newreference(p^.left^.location.reference))
  123. else
  124. begin
  125. emitpushreferenceaddr(p^.left^.location.reference);
  126. emitpushreferenceaddr(p^.right^.location.reference);
  127. push_shortstring_length(p^.left);
  128. emitcall('FPC_LONGSTR_COPY');
  129. maybe_loadesi;
  130. end;
  131. end;
  132. orddef:
  133. begin
  134. emit_const_ref(A_MOV,S_L,1,newreference(p^.left^.location.reference));
  135. r:=newreference(p^.left^.location.reference);
  136. inc(r^.offset,4);
  137. if p^.right^.treetype=ordconstn then
  138. emit_const_ref(A_MOV,S_B,p^.right^.value,r)
  139. else
  140. begin
  141. case p^.right^.location.loc of
  142. LOC_REGISTER,LOC_CREGISTER:
  143. begin
  144. emit_reg_ref(A_MOV,S_B,p^.right^.location.register,r);
  145. ungetregister(p^.right^.location.register);
  146. end;
  147. LOC_MEM,LOC_REFERENCE:
  148. begin
  149. if not(R_EAX in unused) then
  150. emit_reg(A_PUSH,S_L,R_EAX);
  151. emit_ref_reg(A_MOV,S_B,newreference(p^.right^.location.reference),R_AL);
  152. emit_reg_ref(A_MOV,S_B,R_AL,r);
  153. if not(R_EAX in unused) then
  154. emit_reg(A_POP,S_L,R_EAX);
  155. del_reference(p^.right^.location.reference);
  156. end
  157. else
  158. internalerror(20799);
  159. end;
  160. end;
  161. end;
  162. else
  163. CGMessage(type_e_mismatch);
  164. end;
  165. end;
  166. procedure loadansi2short(source,dest : ptree);
  167. var
  168. pushed : tpushed;
  169. regs_to_push: byte;
  170. begin
  171. { Find out which registers have to be pushed (JM) }
  172. regs_to_push := $ff;
  173. remove_non_regvars_from_loc(source^.location,regs_to_push);
  174. remove_non_regvars_from_loc(dest^.location,regs_to_push);
  175. { Push them (JM) }
  176. pushusedregisters(pushed,regs_to_push);
  177. case source^.location.loc of
  178. LOC_REFERENCE,LOC_MEM:
  179. begin
  180. { Now release the location and registers (see cgai386.pas: }
  181. { loadansistring for more info on the order) (JM) }
  182. ungetiftemp(source^.location.reference);
  183. del_reference(source^.location.reference);
  184. emit_push_mem(source^.location.reference);
  185. end;
  186. LOC_REGISTER,LOC_CREGISTER:
  187. begin
  188. emit_reg(A_PUSH,S_L,source^.location.register);
  189. { Now release the register (JM) }
  190. ungetregister32(source^.location.register);
  191. end;
  192. end;
  193. push_shortstring_length(dest);
  194. emitpushreferenceaddr(dest^.location.reference);
  195. { Only now release the destination (JM) }
  196. del_reference(dest^.location.reference);
  197. emitcall('FPC_ANSISTR_TO_SHORTSTR');
  198. popusedregisters(pushed);
  199. maybe_loadesi;
  200. end;
  201. {*****************************************************************************
  202. SecondTypeConv
  203. *****************************************************************************}
  204. type
  205. tsecondconvproc = procedure(var pto,pfrom : ptree;convtyp : tconverttype);
  206. procedure second_int_to_int(var pto,pfrom : ptree;convtyp : tconverttype);
  207. var
  208. op : tasmop;
  209. opsize : topsize;
  210. hregister,
  211. hregister2 : tregister;
  212. l : pasmlabel;
  213. begin
  214. { insert range check if not explicit conversion }
  215. if not(pto^.explizit) then
  216. emitrangecheck(pfrom,pto^.resulttype);
  217. { is the result size smaller ? }
  218. if pto^.resulttype^.size<pfrom^.resulttype^.size then
  219. begin
  220. { only need to set the new size of a register }
  221. if (pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  222. begin
  223. case pto^.resulttype^.size of
  224. 1 : pto^.location.register:=makereg8(pfrom^.location.register);
  225. 2 : pto^.location.register:=makereg16(pfrom^.location.register);
  226. 4 : pto^.location.register:=makereg32(pfrom^.location.register);
  227. end;
  228. { we can release the upper register }
  229. if is_64bitint(pfrom^.resulttype) then
  230. ungetregister32(pfrom^.location.registerhigh);
  231. end;
  232. end
  233. { is the result size bigger ? }
  234. else if pto^.resulttype^.size>pfrom^.resulttype^.size then
  235. begin
  236. { remove reference }
  237. if not(pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  238. begin
  239. del_reference(pfrom^.location.reference);
  240. { we can do this here as we need no temp inside }
  241. ungetiftemp(pfrom^.location.reference);
  242. end;
  243. { get op and opsize, handle separate for constants, because
  244. movz doesn't support constant values }
  245. if (pfrom^.location.loc=LOC_MEM) and (pfrom^.location.reference.is_immediate) then
  246. begin
  247. if is_64bitint(pto^.resulttype) then
  248. opsize:=S_L
  249. else
  250. opsize:=def_opsize(pto^.resulttype);
  251. op:=A_MOV;
  252. end
  253. else
  254. begin
  255. opsize:=def2def_opsize(pfrom^.resulttype,pto^.resulttype);
  256. if opsize in [S_B,S_W,S_L] then
  257. op:=A_MOV
  258. else
  259. if is_signed(pfrom^.resulttype) then
  260. op:=A_MOVSX
  261. else
  262. op:=A_MOVZX;
  263. end;
  264. { load the register we need }
  265. if pfrom^.location.loc<>LOC_REGISTER then
  266. hregister:=getregister32
  267. else
  268. hregister:=pfrom^.location.register;
  269. { set the correct register size and location }
  270. clear_location(pto^.location);
  271. pto^.location.loc:=LOC_REGISTER;
  272. { do we need a second register for a 64 bit type ? }
  273. if is_64bitint(pto^.resulttype) then
  274. begin
  275. hregister2:=getregister32;
  276. pto^.location.registerhigh:=hregister2;
  277. end;
  278. case pto^.resulttype^.size of
  279. 1:
  280. pto^.location.register:=makereg8(hregister);
  281. 2:
  282. pto^.location.register:=makereg16(hregister);
  283. 4,8:
  284. pto^.location.register:=makereg32(hregister);
  285. end;
  286. { insert the assembler code }
  287. if pfrom^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  288. emit_reg_reg(op,opsize,pfrom^.location.register,pto^.location.register)
  289. else
  290. emit_ref_reg(op,opsize,
  291. newreference(pfrom^.location.reference),pto^.location.register);
  292. { do we need a sign extension for int64? }
  293. if is_64bitint(pto^.resulttype) then
  294. begin
  295. emit_reg_reg(A_XOR,S_L,
  296. hregister2,hregister2);
  297. if (porddef(pto^.resulttype)^.typ=s64bit) and
  298. is_signed(pfrom^.resulttype) then
  299. begin
  300. getlabel(l);
  301. emit_const_reg(A_TEST,S_L,$80000000,makereg32(hregister));
  302. emitjmp(C_Z,l);
  303. emit_reg(A_NOT,S_L,
  304. hregister2);
  305. emitlab(l);
  306. end;
  307. end;
  308. end;
  309. end;
  310. procedure second_string_to_string(var pto,pfrom : ptree;convtyp : tconverttype);
  311. var
  312. pushed : tpushed;
  313. begin
  314. { does anybody know a better solution than this big case statement ? }
  315. { ok, a proc table would do the job }
  316. case pstringdef(pto^.resulttype)^.string_typ of
  317. st_shortstring:
  318. case pstringdef(pfrom^.resulttype)^.string_typ of
  319. st_shortstring:
  320. begin
  321. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  322. copyshortstring(pto^.location.reference,pfrom^.location.reference,
  323. pstringdef(pto^.resulttype)^.len,false,true);
  324. { done by copyshortstring now (JM) }
  325. { del_reference(pfrom^.location.reference); }
  326. ungetiftemp(pfrom^.location.reference);
  327. end;
  328. st_longstring:
  329. begin
  330. {!!!!!!!}
  331. internalerror(8888);
  332. end;
  333. st_ansistring:
  334. begin
  335. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  336. loadansi2short(pfrom,pto);
  337. { this is done in secondtypeconv (FK)
  338. removetemps(exprasmlist,temptoremove);
  339. destroys:=true;
  340. }
  341. end;
  342. st_widestring:
  343. begin
  344. {!!!!!!!}
  345. internalerror(8888);
  346. end;
  347. end;
  348. st_longstring:
  349. case pstringdef(pfrom^.resulttype)^.string_typ of
  350. st_shortstring:
  351. begin
  352. {!!!!!!!}
  353. internalerror(8888);
  354. end;
  355. st_ansistring:
  356. begin
  357. {!!!!!!!}
  358. internalerror(8888);
  359. end;
  360. st_widestring:
  361. begin
  362. {!!!!!!!}
  363. internalerror(8888);
  364. end;
  365. end;
  366. st_ansistring:
  367. case pstringdef(pfrom^.resulttype)^.string_typ of
  368. st_shortstring:
  369. begin
  370. clear_location(pto^.location);
  371. pto^.location.loc:=LOC_REFERENCE;
  372. gettempansistringreference(pto^.location.reference);
  373. decrstringref(cansistringdef,pto^.location.reference);
  374. pushusedregisters(pushed,$ff);
  375. emit_push_lea_loc(pfrom^.location,true);
  376. emit_push_lea_loc(pto^.location,false);
  377. emitcall('FPC_SHORTSTR_TO_ANSISTR');
  378. maybe_loadesi;
  379. popusedregisters(pushed);
  380. end;
  381. st_longstring:
  382. begin
  383. {!!!!!!!}
  384. internalerror(8888);
  385. end;
  386. st_widestring:
  387. begin
  388. {!!!!!!!}
  389. internalerror(8888);
  390. end;
  391. end;
  392. st_widestring:
  393. case pstringdef(pfrom^.resulttype)^.string_typ of
  394. st_shortstring:
  395. begin
  396. {!!!!!!!}
  397. internalerror(8888);
  398. end;
  399. st_longstring:
  400. begin
  401. {!!!!!!!}
  402. internalerror(8888);
  403. end;
  404. st_ansistring:
  405. begin
  406. {!!!!!!!}
  407. internalerror(8888);
  408. end;
  409. st_widestring:
  410. begin
  411. {!!!!!!!}
  412. internalerror(8888);
  413. end;
  414. end;
  415. end;
  416. end;
  417. procedure second_cstring_to_pchar(var pto,pfrom : ptree;convtyp : tconverttype);
  418. var
  419. hr : preference;
  420. begin
  421. clear_location(pto^.location);
  422. pto^.location.loc:=LOC_REGISTER;
  423. pto^.location.register:=getregister32;
  424. case pstringdef(pfrom^.resulttype)^.string_typ of
  425. st_shortstring :
  426. begin
  427. inc(pfrom^.location.reference.offset);
  428. emit_ref_reg(A_LEA,S_L,newreference(pfrom^.location.reference),
  429. pto^.location.register);
  430. end;
  431. st_ansistring :
  432. begin
  433. if (pfrom^.treetype=stringconstn) and
  434. (str_length(pfrom)=0) then
  435. begin
  436. new(hr);
  437. reset_reference(hr^);
  438. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  439. emit_ref_reg(A_LEA,S_L,hr,pto^.location.register);
  440. end
  441. else
  442. emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  443. pto^.location.register);
  444. end;
  445. st_longstring:
  446. begin
  447. {!!!!!!!}
  448. internalerror(8888);
  449. end;
  450. st_widestring:
  451. begin
  452. {!!!!!!!}
  453. internalerror(8888);
  454. end;
  455. end;
  456. end;
  457. procedure second_string_to_chararray(var pto,pfrom : ptree;convtyp : tconverttype);
  458. var
  459. l1 : pasmlabel;
  460. hr : preference;
  461. begin
  462. case pstringdef(pfrom^.resulttype)^.string_typ of
  463. st_shortstring :
  464. begin
  465. inc(pto^.location.reference.offset);
  466. end;
  467. st_ansistring :
  468. begin
  469. clear_location(pto^.location);
  470. pto^.location.loc:=LOC_REFERENCE;
  471. reset_reference(pto^.location.reference);
  472. getlabel(l1);
  473. case pfrom^.location.loc of
  474. LOC_CREGISTER,LOC_REGISTER:
  475. pto^.location.reference.base:=pfrom^.location.register;
  476. LOC_MEM,LOC_REFERENCE:
  477. begin
  478. pto^.location.reference.base:=getregister32;
  479. emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  480. pto^.location.reference.base);
  481. del_reference(pfrom^.location.reference);
  482. end;
  483. end;
  484. emit_const_reg(A_CMP,S_L,0,pto^.location.reference.base);
  485. emitjmp(C_NZ,l1);
  486. new(hr);
  487. reset_reference(hr^);
  488. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  489. emit_ref_reg(A_LEA,S_L,hr,pto^.location.reference.base);
  490. emitlab(l1);
  491. end;
  492. st_longstring:
  493. begin
  494. {!!!!!!!}
  495. internalerror(8888);
  496. end;
  497. st_widestring:
  498. begin
  499. {!!!!!!!}
  500. internalerror(8888);
  501. end;
  502. end;
  503. end;
  504. procedure second_array_to_pointer(var pto,pfrom : ptree;convtyp : tconverttype);
  505. begin
  506. del_reference(pfrom^.location.reference);
  507. clear_location(pto^.location);
  508. pto^.location.loc:=LOC_REGISTER;
  509. pto^.location.register:=getregister32;
  510. emit_ref_reg(A_LEA,S_L,newreference(pfrom^.location.reference),
  511. pto^.location.register);
  512. end;
  513. procedure second_pointer_to_array(var pto,pfrom : ptree;convtyp : tconverttype);
  514. begin
  515. clear_location(pto^.location);
  516. pto^.location.loc:=LOC_REFERENCE;
  517. reset_reference(pto^.location.reference);
  518. case pfrom^.location.loc of
  519. LOC_REGISTER :
  520. pto^.location.reference.base:=pfrom^.location.register;
  521. LOC_CREGISTER :
  522. begin
  523. pto^.location.reference.base:=getregister32;
  524. emit_reg_reg(A_MOV,S_L,pfrom^.location.register,pto^.location.reference.base);
  525. end
  526. else
  527. begin
  528. del_reference(pfrom^.location.reference);
  529. pto^.location.reference.base:=getregister32;
  530. emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  531. pto^.location.reference.base);
  532. end;
  533. end;
  534. end;
  535. { generates the code for the type conversion from an array of char }
  536. { to a string }
  537. procedure second_chararray_to_string(var pto,pfrom : ptree;convtyp : tconverttype);
  538. var
  539. pushed : tpushed;
  540. l : longint;
  541. begin
  542. { calc the length of the array }
  543. l:=parraydef(pfrom^.resulttype)^.highrange-parraydef(pfrom^.resulttype)^.lowrange+1;
  544. { this is a type conversion which copies the data, so we can't }
  545. { return a reference }
  546. clear_location(pto^.location);
  547. pto^.location.loc:=LOC_MEM;
  548. case pstringdef(pto^.resulttype)^.string_typ of
  549. st_shortstring :
  550. begin
  551. if l>255 then
  552. begin
  553. CGMessage(type_e_mismatch);
  554. l:=255;
  555. end;
  556. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  557. pushusedregisters(pushed,$ff);
  558. if l>=pto^.resulttype^.size then
  559. push_int(pto^.resulttype^.size-1)
  560. else
  561. push_int(l);
  562. { we've also to release the registers ... }
  563. del_reference(pfrom^.location.reference);
  564. { ... here only the temp. location is released }
  565. emit_push_lea_loc(pfrom^.location,true);
  566. emitpushreferenceaddr(pto^.location.reference);
  567. emitcall('FPC_CHARARRAY_TO_SHORTSTR');
  568. maybe_loadesi;
  569. popusedregisters(pushed);
  570. end;
  571. st_ansistring :
  572. begin
  573. gettempansistringreference(pto^.location.reference);
  574. decrstringref(cansistringdef,pto^.location.reference);
  575. release_loc(pfrom^.location);
  576. pushusedregisters(pushed,$ff);
  577. push_int(l);
  578. emitpushreferenceaddr(pfrom^.location.reference);
  579. emitpushreferenceaddr(pto^.location.reference);
  580. emitcall('FPC_CHARARRAY_TO_ANSISTR');
  581. popusedregisters(pushed);
  582. maybe_loadesi;
  583. end;
  584. st_longstring:
  585. begin
  586. {!!!!!!!}
  587. internalerror(8888);
  588. end;
  589. st_widestring:
  590. begin
  591. {!!!!!!!}
  592. internalerror(8888);
  593. end;
  594. end;
  595. end;
  596. procedure second_char_to_string(var pto,pfrom : ptree;convtyp : tconverttype);
  597. var
  598. pushed : tpushed;
  599. begin
  600. clear_location(pto^.location);
  601. pto^.location.loc:=LOC_MEM;
  602. case pstringdef(pto^.resulttype)^.string_typ of
  603. st_shortstring :
  604. begin
  605. gettempofsizereference(256,pto^.location.reference);
  606. { call loadstring with correct left and right }
  607. pto^.right:=pfrom;
  608. pto^.left:=pto;
  609. loadshortstring(pto);
  610. pto^.left:=nil; { reset left tree, which is empty }
  611. { pto^.right is not disposed for typeconv !! PM }
  612. disposetree(pto^.right);
  613. pto^.right:=nil;
  614. end;
  615. st_ansistring :
  616. begin
  617. gettempansistringreference(pto^.location.reference);
  618. decrstringref(cansistringdef,pto^.location.reference);
  619. release_loc(pfrom^.location);
  620. pushusedregisters(pushed,$ff);
  621. emit_pushw_loc(pfrom^.location);
  622. emitpushreferenceaddr(pto^.location.reference);
  623. emitcall('FPC_CHAR_TO_ANSISTR');
  624. popusedregisters(pushed);
  625. maybe_loadesi;
  626. end;
  627. else
  628. internalerror(4179);
  629. end;
  630. end;
  631. procedure second_int_to_real(var pto,pfrom : ptree;convtyp : tconverttype);
  632. var
  633. r : preference;
  634. hregister : tregister;
  635. l1,l2 : pasmlabel;
  636. begin
  637. { for u32bit a solution is to push $0 and to load a comp }
  638. { does this first, it destroys maybe EDI }
  639. hregister:=R_EDI;
  640. if porddef(pfrom^.resulttype)^.typ=u32bit then
  641. push_int(0);
  642. if (pfrom^.location.loc=LOC_REGISTER) or
  643. (pfrom^.location.loc=LOC_CREGISTER) then
  644. begin
  645. {$ifndef noAllocEdi}
  646. if not (porddef(pfrom^.resulttype)^.typ in [u32bit,s32bit,u64bit,s64bit]) then
  647. getexplicitregister32(R_EDI);
  648. {$endif noAllocEdi}
  649. case porddef(pfrom^.resulttype)^.typ of
  650. s8bit : emit_reg_reg(A_MOVSX,S_BL,pfrom^.location.register,R_EDI);
  651. u8bit : emit_reg_reg(A_MOVZX,S_BL,pfrom^.location.register,R_EDI);
  652. s16bit : emit_reg_reg(A_MOVSX,S_WL,pfrom^.location.register,R_EDI);
  653. u16bit : emit_reg_reg(A_MOVZX,S_WL,pfrom^.location.register,R_EDI);
  654. u32bit,s32bit:
  655. hregister:=pfrom^.location.register;
  656. u64bit,s64bit:
  657. begin
  658. emit_reg(A_PUSH,S_L,pfrom^.location.registerhigh);
  659. hregister:=pfrom^.location.registerlow;
  660. end;
  661. end;
  662. ungetregister(pfrom^.location.register);
  663. end
  664. else
  665. begin
  666. r:=newreference(pfrom^.location.reference);
  667. {$ifndef noAllocEdi}
  668. getexplicitregister32(R_EDI);
  669. {$endif noAllocEdi}
  670. case porddef(pfrom^.resulttype)^.typ of
  671. s8bit:
  672. emit_ref_reg(A_MOVSX,S_BL,r,R_EDI);
  673. u8bit:
  674. emit_ref_reg(A_MOVZX,S_BL,r,R_EDI);
  675. s16bit:
  676. emit_ref_reg(A_MOVSX,S_WL,r,R_EDI);
  677. u16bit:
  678. emit_ref_reg(A_MOVZX,S_WL,r,R_EDI);
  679. u32bit,s32bit:
  680. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  681. u64bit,s64bit:
  682. begin
  683. inc(r^.offset,4);
  684. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  685. emit_reg(A_PUSH,S_L,R_EDI);
  686. r:=newreference(pfrom^.location.reference);
  687. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  688. end;
  689. end;
  690. del_reference(pfrom^.location.reference);
  691. ungetiftemp(pfrom^.location.reference);
  692. end;
  693. { for 64 bit integers, the high dword is already pushed }
  694. emit_reg(A_PUSH,S_L,hregister);
  695. {$ifndef noAllocEdi}
  696. if hregister = R_EDI then
  697. ungetregister32(R_EDI);
  698. {$endif noAllocEdi}
  699. r:=new_reference(R_ESP,0);
  700. case porddef(pfrom^.resulttype)^.typ of
  701. u32bit:
  702. begin
  703. emit_ref(A_FILD,S_IQ,r);
  704. emit_const_reg(A_ADD,S_L,8,R_ESP);
  705. end;
  706. s64bit:
  707. begin
  708. emit_ref(A_FILD,S_IQ,r);
  709. emit_const_reg(A_ADD,S_L,8,R_ESP);
  710. end;
  711. u64bit:
  712. begin
  713. { unsigned 64 bit ints are harder to handle: }
  714. { we load bits 0..62 and then check bit 63: }
  715. { if it is 1 then we add $80000000 000000000 }
  716. { as double }
  717. inc(r^.offset,4);
  718. {$ifndef noAllocEdi}
  719. getexplicitregister32(R_EDI);
  720. {$endif noAllocEdi}
  721. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  722. r:=new_reference(R_ESP,4);
  723. emit_const_ref(A_AND,S_L,$7fffffff,r);
  724. emit_const_reg(A_TEST,S_L,$80000000,R_EDI);
  725. {$ifndef noAllocEdi}
  726. ungetregister32(R_EDI);
  727. {$endif noAllocEdi}
  728. r:=new_reference(R_ESP,0);
  729. emit_ref(A_FILD,S_IQ,r);
  730. getdatalabel(l1);
  731. getlabel(l2);
  732. emitjmp(C_Z,l2);
  733. consts^.concat(new(pai_label,init(l1)));
  734. { I got this constant from a test progtram (FK) }
  735. consts^.concat(new(pai_const,init_32bit(0)));
  736. consts^.concat(new(pai_const,init_32bit(1138753536)));
  737. r:=new_reference(R_NO,0);
  738. r^.symbol:=l1;
  739. emit_ref(A_FADD,S_FL,r);
  740. emitlab(l2);
  741. emit_const_reg(A_ADD,S_L,8,R_ESP);
  742. end
  743. else
  744. begin
  745. emit_ref(A_FILD,S_IL,r);
  746. {$ifndef noAllocEdi}
  747. getexplicitregister32(R_EDI);
  748. {$endif noAllocEdi}
  749. emit_reg(A_POP,S_L,R_EDI);
  750. {$ifndef noAllocEdi}
  751. ungetregister32(R_EDI);
  752. {$endif noAllocEdi}
  753. end;
  754. end;
  755. inc(fpuvaroffset);
  756. clear_location(pto^.location);
  757. pto^.location.loc:=LOC_FPU;
  758. end;
  759. procedure second_real_to_fix(var pto,pfrom : ptree;convtyp : tconverttype);
  760. var
  761. rreg : tregister;
  762. ref : treference;
  763. begin
  764. { real must be on fpu stack }
  765. if (pfrom^.location.loc<>LOC_FPU) then
  766. emit_ref(A_FLD,S_FL,newreference(pfrom^.location.reference));
  767. push_int($1f3f);
  768. push_int(65536);
  769. reset_reference(ref);
  770. ref.base:=R_ESP;
  771. emit_ref(A_FIMUL,S_IL,newreference(ref));
  772. ref.offset:=4;
  773. emit_ref(A_FSTCW,S_NO,newreference(ref));
  774. ref.offset:=6;
  775. emit_ref(A_FLDCW,S_NO,newreference(ref));
  776. ref.offset:=0;
  777. emit_ref(A_FISTP,S_IL,newreference(ref));
  778. ref.offset:=4;
  779. emit_ref(A_FLDCW,S_NO,newreference(ref));
  780. rreg:=getregister32;
  781. emit_reg(A_POP,S_L,rreg);
  782. { better than an add on all processors }
  783. {$ifndef noAllocEdi}
  784. getexplicitregister32(R_EDI);
  785. {$endif noAllocEdi}
  786. emit_reg(A_POP,S_L,R_EDI);
  787. {$ifndef noAllocEdi}
  788. ungetregister32(R_EDI);
  789. {$endif noAllocEdi}
  790. clear_location(pto^.location);
  791. pto^.location.loc:=LOC_REGISTER;
  792. pto^.location.register:=rreg;
  793. inc(fpuvaroffset);
  794. end;
  795. procedure second_real_to_real(var pto,pfrom : ptree;convtyp : tconverttype);
  796. begin
  797. case pfrom^.location.loc of
  798. LOC_FPU : ;
  799. LOC_CFPUREGISTER:
  800. begin
  801. pto^.location:=pfrom^.location;
  802. exit;
  803. end;
  804. LOC_MEM,
  805. LOC_REFERENCE:
  806. begin
  807. floatload(pfloatdef(pfrom^.resulttype)^.typ,
  808. pfrom^.location.reference);
  809. { we have to free the reference }
  810. del_reference(pfrom^.location.reference);
  811. end;
  812. end;
  813. clear_location(pto^.location);
  814. pto^.location.loc:=LOC_FPU;
  815. end;
  816. procedure second_fix_to_real(var pto,pfrom : ptree;convtyp : tconverttype);
  817. var
  818. popeax,popebx,popecx,popedx : boolean;
  819. startreg : tregister;
  820. hl : pasmlabel;
  821. r : treference;
  822. begin
  823. if (pfrom^.location.loc=LOC_REGISTER) or
  824. (pfrom^.location.loc=LOC_CREGISTER) then
  825. begin
  826. startreg:=pfrom^.location.register;
  827. ungetregister(startreg);
  828. popeax:=(startreg<>R_EAX) and not (R_EAX in unused);
  829. if popeax then
  830. emit_reg(A_PUSH,S_L,R_EAX);
  831. { mov eax,eax is removed by emit_reg_reg }
  832. emit_reg_reg(A_MOV,S_L,startreg,R_EAX);
  833. end
  834. else
  835. begin
  836. emit_ref_reg(A_MOV,S_L,newreference(
  837. pfrom^.location.reference),R_EAX);
  838. del_reference(pfrom^.location.reference);
  839. startreg:=R_NO;
  840. end;
  841. popebx:=(startreg<>R_EBX) and not (R_EBX in unused);
  842. if popebx then
  843. emit_reg(A_PUSH,S_L,R_EBX);
  844. popecx:=(startreg<>R_ECX) and not (R_ECX in unused);
  845. if popecx then
  846. emit_reg(A_PUSH,S_L,R_ECX);
  847. popedx:=(startreg<>R_EDX) and not (R_EDX in unused);
  848. if popedx then
  849. emit_reg(A_PUSH,S_L,R_EDX);
  850. emit_none(A_CDQ,S_NO);
  851. emit_reg_reg(A_XOR,S_L,R_EDX,R_EAX);
  852. emit_reg_reg(A_MOV,S_L,R_EAX,R_EBX);
  853. emit_reg_reg(A_SUB,S_L,R_EDX,R_EAX);
  854. getlabel(hl);
  855. emitjmp(C_Z,hl);
  856. emit_const_reg(A_RCL,S_L,1,R_EBX);
  857. emit_reg_reg(A_BSR,S_L,R_EAX,R_EDX);
  858. emit_const_reg(A_MOV,S_B,32,R_CL);
  859. emit_reg_reg(A_SUB,S_B,R_DL,R_CL);
  860. emit_reg_reg(A_SHL,S_L,R_CL,R_EAX);
  861. emit_const_reg(A_ADD,S_W,1007,R_DX);
  862. emit_const_reg(A_SHL,S_W,5,R_DX);
  863. emit_const_reg_reg(A_SHLD,S_W,11,R_DX,R_BX);
  864. emit_const_reg_reg(A_SHLD,S_L,20,R_EAX,R_EBX);
  865. emit_const_reg(A_SHL,S_L,20,R_EAX);
  866. emitlab(hl);
  867. { better than an add on all processors }
  868. emit_reg(A_PUSH,S_L,R_EBX);
  869. emit_reg(A_PUSH,S_L,R_EAX);
  870. reset_reference(r);
  871. r.base:=R_ESP;
  872. emit_ref(A_FLD,S_FL,newreference(r));
  873. emit_const_reg(A_ADD,S_L,8,R_ESP);
  874. if popedx then
  875. emit_reg(A_POP,S_L,R_EDX);
  876. if popecx then
  877. emit_reg(A_POP,S_L,R_ECX);
  878. if popebx then
  879. emit_reg(A_POP,S_L,R_EBX);
  880. if popeax then
  881. emit_reg(A_POP,S_L,R_EAX);
  882. clear_location(pto^.location);
  883. pto^.location.loc:=LOC_FPU;
  884. end;
  885. procedure second_cord_to_pointer(var pto,pfrom : ptree;convtyp : tconverttype);
  886. begin
  887. { this can't happend, because constants are already processed in
  888. pass 1 }
  889. internalerror(47423985);
  890. end;
  891. procedure second_int_to_fix(var pto,pfrom : ptree;convtyp : tconverttype);
  892. var
  893. hregister : tregister;
  894. begin
  895. if (pfrom^.location.loc=LOC_REGISTER) then
  896. hregister:=pfrom^.location.register
  897. else if (pfrom^.location.loc=LOC_CREGISTER) then
  898. hregister:=getregister32
  899. else
  900. begin
  901. del_reference(pfrom^.location.reference);
  902. hregister:=getregister32;
  903. case porddef(pfrom^.resulttype)^.typ of
  904. s8bit : emit_ref_reg(A_MOVSX,S_BL,newreference(pfrom^.location.reference),
  905. hregister);
  906. u8bit : emit_ref_reg(A_MOVZX,S_BL,newreference(pfrom^.location.reference),
  907. hregister);
  908. s16bit : emit_ref_reg(A_MOVSX,S_WL,newreference(pfrom^.location.reference),
  909. hregister);
  910. u16bit : emit_ref_reg(A_MOVZX,S_WL,newreference(pfrom^.location.reference),
  911. hregister);
  912. u32bit,s32bit : emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  913. hregister);
  914. {!!!! u32bit }
  915. end;
  916. end;
  917. emit_const_reg(A_SHL,S_L,16,hregister);
  918. clear_location(pto^.location);
  919. pto^.location.loc:=LOC_REGISTER;
  920. pto^.location.register:=hregister;
  921. end;
  922. procedure second_proc_to_procvar(var pto,pfrom : ptree;convtyp : tconverttype);
  923. begin
  924. { method pointer ? }
  925. if assigned(pfrom^.left) then
  926. begin
  927. set_location(pto^.location,pfrom^.location);
  928. end
  929. else
  930. begin
  931. clear_location(pto^.location);
  932. pto^.location.loc:=LOC_REGISTER;
  933. pto^.location.register:=getregister32;
  934. del_reference(pfrom^.location.reference);
  935. emit_ref_reg(A_LEA,S_L,
  936. newreference(pfrom^.location.reference),pto^.location.register);
  937. end;
  938. end;
  939. procedure second_bool_to_int(var pto,pfrom : ptree;convtyp : tconverttype);
  940. var
  941. oldtruelabel,oldfalselabel,hlabel : pasmlabel;
  942. hregister : tregister;
  943. newsize,
  944. opsize : topsize;
  945. op : tasmop;
  946. begin
  947. oldtruelabel:=truelabel;
  948. oldfalselabel:=falselabel;
  949. getlabel(truelabel);
  950. getlabel(falselabel);
  951. secondpass(pfrom);
  952. { byte(boolean) or word(wordbool) or longint(longbool) must
  953. be accepted for var parameters }
  954. if (pto^.explizit) and
  955. (pfrom^.resulttype^.size=pto^.resulttype^.size) and
  956. (pfrom^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  957. begin
  958. set_location(pto^.location,pfrom^.location);
  959. truelabel:=oldtruelabel;
  960. falselabel:=oldfalselabel;
  961. exit;
  962. end;
  963. clear_location(pto^.location);
  964. pto^.location.loc:=LOC_REGISTER;
  965. del_reference(pfrom^.location.reference);
  966. case pfrom^.resulttype^.size of
  967. 1 : begin
  968. case pto^.resulttype^.size of
  969. 1 : opsize:=S_B;
  970. 2 : opsize:=S_BW;
  971. 4 : opsize:=S_BL;
  972. end;
  973. end;
  974. 2 : begin
  975. case pto^.resulttype^.size of
  976. 1 : begin
  977. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  978. pfrom^.location.register:=reg16toreg8(pfrom^.location.register);
  979. opsize:=S_B;
  980. end;
  981. 2 : opsize:=S_W;
  982. 4 : opsize:=S_WL;
  983. end;
  984. end;
  985. 4 : begin
  986. case pto^.resulttype^.size of
  987. 1 : begin
  988. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  989. pfrom^.location.register:=reg32toreg8(pfrom^.location.register);
  990. opsize:=S_B;
  991. end;
  992. 2 : begin
  993. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  994. pfrom^.location.register:=reg32toreg16(pfrom^.location.register);
  995. opsize:=S_W;
  996. end;
  997. 4 : opsize:=S_L;
  998. end;
  999. end;
  1000. end;
  1001. if opsize in [S_B,S_W,S_L] then
  1002. op:=A_MOV
  1003. else
  1004. if is_signed(pto^.resulttype) then
  1005. op:=A_MOVSX
  1006. else
  1007. op:=A_MOVZX;
  1008. hregister:=getregister32;
  1009. case pto^.resulttype^.size of
  1010. 1 : begin
  1011. pto^.location.register:=reg32toreg8(hregister);
  1012. newsize:=S_B;
  1013. end;
  1014. 2 : begin
  1015. pto^.location.register:=reg32toreg16(hregister);
  1016. newsize:=S_W;
  1017. end;
  1018. 4 : begin
  1019. pto^.location.register:=hregister;
  1020. newsize:=S_L;
  1021. end;
  1022. else
  1023. internalerror(10060);
  1024. end;
  1025. case pfrom^.location.loc of
  1026. LOC_MEM,
  1027. LOC_REFERENCE : emit_ref_reg(op,opsize,
  1028. newreference(pfrom^.location.reference),pto^.location.register);
  1029. LOC_REGISTER,
  1030. LOC_CREGISTER : begin
  1031. { remove things like movb %al,%al }
  1032. if pfrom^.location.register<>pto^.location.register then
  1033. emit_reg_reg(op,opsize,
  1034. pfrom^.location.register,pto^.location.register);
  1035. end;
  1036. LOC_FLAGS : begin
  1037. emit_flag2reg(pfrom^.location.resflags,pto^.location.register);
  1038. end;
  1039. LOC_JUMP : begin
  1040. getlabel(hlabel);
  1041. emitlab(truelabel);
  1042. emit_const_reg(A_MOV,newsize,1,pto^.location.register);
  1043. emitjmp(C_None,hlabel);
  1044. emitlab(falselabel);
  1045. emit_reg_reg(A_XOR,newsize,pto^.location.register,
  1046. pto^.location.register);
  1047. emitlab(hlabel);
  1048. end;
  1049. else
  1050. internalerror(10061);
  1051. end;
  1052. truelabel:=oldtruelabel;
  1053. falselabel:=oldfalselabel;
  1054. end;
  1055. procedure second_int_to_bool(var pto,pfrom : ptree;convtyp : tconverttype);
  1056. var
  1057. hregister : tregister;
  1058. flags : tresflags;
  1059. opsize : topsize;
  1060. begin
  1061. clear_location(pto^.location);
  1062. { byte(boolean) or word(wordbool) or longint(longbool) must
  1063. be accepted for var parameters }
  1064. if (pto^.explizit) and
  1065. (pfrom^.resulttype^.size=pto^.resulttype^.size) and
  1066. (pfrom^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  1067. begin
  1068. set_location(pto^.location,pfrom^.location);
  1069. exit;
  1070. end;
  1071. pto^.location.loc:=LOC_REGISTER;
  1072. del_reference(pfrom^.location.reference);
  1073. opsize:=def_opsize(pfrom^.resulttype);
  1074. case pfrom^.location.loc of
  1075. LOC_MEM,LOC_REFERENCE :
  1076. begin
  1077. hregister:=def_getreg(pfrom^.resulttype);
  1078. emit_ref_reg(A_MOV,opsize,
  1079. newreference(pfrom^.location.reference),hregister);
  1080. emit_reg_reg(A_OR,opsize,hregister,hregister);
  1081. flags:=F_NE;
  1082. end;
  1083. LOC_FLAGS :
  1084. begin
  1085. hregister:=getregister32;
  1086. flags:=pfrom^.location.resflags;
  1087. end;
  1088. LOC_REGISTER,LOC_CREGISTER :
  1089. begin
  1090. hregister:=pfrom^.location.register;
  1091. emit_reg_reg(A_OR,opsize,hregister,hregister);
  1092. flags:=F_NE;
  1093. end;
  1094. else
  1095. internalerror(10062);
  1096. end;
  1097. case pto^.resulttype^.size of
  1098. 1 : pto^.location.register:=makereg8(hregister);
  1099. 2 : pto^.location.register:=makereg16(hregister);
  1100. 4 : pto^.location.register:=makereg32(hregister);
  1101. else
  1102. internalerror(10064);
  1103. end;
  1104. emit_flag2reg(flags,pto^.location.register);
  1105. end;
  1106. procedure second_load_smallset(var pto,pfrom : ptree;convtyp : tconverttype);
  1107. var
  1108. href : treference;
  1109. pushedregs : tpushed;
  1110. begin
  1111. href.symbol:=nil;
  1112. pushusedregisters(pushedregs,$ff);
  1113. gettempofsizereference(32,href);
  1114. emitpushreferenceaddr(pfrom^.location.reference);
  1115. emitpushreferenceaddr(href);
  1116. emitcall('FPC_SET_LOAD_SMALL');
  1117. maybe_loadesi;
  1118. popusedregisters(pushedregs);
  1119. clear_location(pto^.location);
  1120. pto^.location.loc:=LOC_MEM;
  1121. pto^.location.reference:=href;
  1122. end;
  1123. procedure second_ansistring_to_pchar(var pto,pfrom : ptree;convtyp : tconverttype);
  1124. var
  1125. l1 : pasmlabel;
  1126. hr : preference;
  1127. begin
  1128. clear_location(pto^.location);
  1129. pto^.location.loc:=LOC_REGISTER;
  1130. getlabel(l1);
  1131. case pfrom^.location.loc of
  1132. LOC_CREGISTER,LOC_REGISTER:
  1133. pto^.location.register:=pfrom^.location.register;
  1134. LOC_MEM,LOC_REFERENCE:
  1135. begin
  1136. pto^.location.register:=getregister32;
  1137. emit_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  1138. pto^.location.register);
  1139. del_reference(pfrom^.location.reference);
  1140. end;
  1141. end;
  1142. emit_const_reg(A_CMP,S_L,0,pto^.location.register);
  1143. emitjmp(C_NZ,l1);
  1144. new(hr);
  1145. reset_reference(hr^);
  1146. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  1147. emit_ref_reg(A_LEA,S_L,hr,pto^.location.register);
  1148. emitlab(l1);
  1149. end;
  1150. procedure second_pchar_to_string(var pto,pfrom : ptree;convtyp : tconverttype);
  1151. var
  1152. pushed : tpushed;
  1153. regs_to_push: byte;
  1154. begin
  1155. case pstringdef(pto^.resulttype)^.string_typ of
  1156. st_shortstring:
  1157. begin
  1158. pto^.location.loc:=LOC_REFERENCE;
  1159. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  1160. pushusedregisters(pushed,$ff);
  1161. case pfrom^.location.loc of
  1162. LOC_REGISTER,LOC_CREGISTER:
  1163. begin
  1164. emit_reg(A_PUSH,S_L,pfrom^.location.register);
  1165. ungetregister32(pfrom^.location.register);
  1166. end;
  1167. LOC_REFERENCE,LOC_MEM:
  1168. begin
  1169. { Now release the registers (see cgai386.pas: }
  1170. { loadansistring for more info on the order) (JM) }
  1171. del_reference(pfrom^.location.reference);
  1172. emit_push_mem(pfrom^.location.reference);
  1173. end;
  1174. end;
  1175. emitpushreferenceaddr(pto^.location.reference);
  1176. emitcall('FPC_PCHAR_TO_SHORTSTR');
  1177. maybe_loadesi;
  1178. popusedregisters(pushed);
  1179. end;
  1180. st_ansistring:
  1181. begin
  1182. pto^.location.loc:=LOC_REFERENCE;
  1183. gettempansistringreference(pto^.location.reference);
  1184. decrstringref(cansistringdef,pto^.location.reference);
  1185. { Find out which regs have to be pushed (JM) }
  1186. regs_to_push := $ff;
  1187. remove_non_regvars_from_loc(pfrom^.location,regs_to_push);
  1188. pushusedregisters(pushed,regs_to_push);
  1189. case pfrom^.location.loc of
  1190. LOC_REFERENCE,LOC_MEM:
  1191. begin
  1192. { Now release the registers (see cgai386.pas: }
  1193. { loadansistring for more info on the order) (JM) }
  1194. del_reference(pfrom^.location.reference);
  1195. emit_push_mem(pfrom^.location.reference);
  1196. end;
  1197. LOC_REGISTER,LOC_CREGISTER:
  1198. begin
  1199. { Now release the registers (see cgai386.pas: }
  1200. { loadansistring for more info on the order) (JM) }
  1201. emit_reg(A_PUSH,S_L,pfrom^.location.register);
  1202. ungetregister32(pfrom^.location.register);
  1203. end;
  1204. end;
  1205. emitpushreferenceaddr(pto^.location.reference);
  1206. emitcall('FPC_PCHAR_TO_ANSISTR');
  1207. maybe_loadesi;
  1208. popusedregisters(pushed);
  1209. end;
  1210. else
  1211. begin
  1212. internalerror(12121);
  1213. end;
  1214. end;
  1215. end;
  1216. procedure second_nothing(var pto,pfrom : ptree;convtyp : tconverttype);
  1217. begin
  1218. end;
  1219. {****************************************************************************
  1220. SecondTypeConv
  1221. ****************************************************************************}
  1222. procedure secondtypeconv(var p : ptree);
  1223. const
  1224. secondconvert : array[tconverttype] of tsecondconvproc = (
  1225. second_nothing, {equal}
  1226. second_nothing, {not_possible}
  1227. second_string_to_string,
  1228. second_char_to_string,
  1229. second_pchar_to_string,
  1230. second_nothing, {cchar_to_pchar}
  1231. second_cstring_to_pchar,
  1232. second_ansistring_to_pchar,
  1233. second_string_to_chararray,
  1234. second_chararray_to_string,
  1235. second_array_to_pointer,
  1236. second_pointer_to_array,
  1237. second_int_to_int,
  1238. second_int_to_bool,
  1239. second_bool_to_int, { bool_to_bool }
  1240. second_bool_to_int,
  1241. second_real_to_real,
  1242. second_int_to_real,
  1243. second_int_to_fix,
  1244. second_real_to_fix,
  1245. second_fix_to_real,
  1246. second_proc_to_procvar,
  1247. second_nothing, {arrayconstructor_to_set}
  1248. second_load_smallset,
  1249. second_cord_to_pointer
  1250. );
  1251. {$ifdef TESTOBJEXT2}
  1252. var
  1253. r : preference;
  1254. nillabel : plabel;
  1255. {$endif TESTOBJEXT2}
  1256. begin
  1257. { this isn't good coding, I think tc_bool_2_int, shouldn't be }
  1258. { type conversion (FK) }
  1259. if not(p^.convtyp in [tc_bool_2_int,tc_bool_2_bool]) then
  1260. begin
  1261. secondpass(p^.left);
  1262. set_location(p^.location,p^.left^.location);
  1263. if codegenerror then
  1264. exit;
  1265. end;
  1266. { the second argument only is for maybe_range_checking !}
  1267. secondconvert[p^.convtyp](p,p^.left,p^.convtyp);
  1268. {$ifdef TESTOBJEXT2}
  1269. { Check explicit conversions to objects pointers !! }
  1270. if p^.explizit and
  1271. (p^.resulttype^.deftype=pointerdef) and
  1272. (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) and not
  1273. (pobjectdef(ppointerdef(p^.resulttype)^.definition)^.isclass) and
  1274. ((pobjectdef(ppointerdef(p^.resulttype)^.definition)^.options and oo_hasvmt)<>0) and
  1275. (cs_check_range in aktlocalswitches) then
  1276. begin
  1277. new(r);
  1278. reset_reference(r^);
  1279. if p^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1280. r^.base:=p^.location.register
  1281. else
  1282. begin
  1283. {$ifndef noAllocEdi}
  1284. getexplicitregister32(R_EDI);
  1285. {$endif noAllocEdi}
  1286. emit_mov_loc_reg(p^.location,R_EDI);
  1287. r^.base:=R_EDI;
  1288. end;
  1289. { NIL must be accepted !! }
  1290. emit_reg_reg(A_OR,S_L,r^.base,r^.base);
  1291. {$ifndef noAllocEdi}
  1292. ungetregister32(R_EDI);
  1293. {$endif noAllocEdi}
  1294. getlabel(nillabel);
  1295. emitjmp(C_E,nillabel);
  1296. { this is one point where we need vmt_offset (PM) }
  1297. r^.offset:= pobjectdef(ppointerdef(p^.resulttype)^.definition)^.vmt_offset;
  1298. {$ifndef noAllocEdi}
  1299. getexplicitregister32(R_EDI);
  1300. {$endif noAllocEdi}
  1301. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  1302. emit_sym(A_PUSH,S_L,
  1303. newasmsymbol(pobjectdef(ppointerdef(p^.resulttype)^.definition)^.vmt_mangledname));
  1304. emit_reg(A_PUSH,S_L,R_EDI);
  1305. {$ifndef noAllocEdi}
  1306. ungetregister32(R_EDI);
  1307. {$endif noAllocEdi}
  1308. emitcall('FPC_CHECK_OBJECT_EXT');
  1309. emitlab(nillabel);
  1310. end;
  1311. {$endif TESTOBJEXT2}
  1312. end;
  1313. {*****************************************************************************
  1314. SecondIs
  1315. *****************************************************************************}
  1316. procedure secondis(var p : ptree);
  1317. var
  1318. pushed : tpushed;
  1319. begin
  1320. { save all used registers }
  1321. pushusedregisters(pushed,$ff);
  1322. secondpass(p^.left);
  1323. clear_location(p^.location);
  1324. p^.location.loc:=LOC_FLAGS;
  1325. p^.location.resflags:=F_NE;
  1326. { push instance to check: }
  1327. case p^.left^.location.loc of
  1328. LOC_REGISTER,LOC_CREGISTER:
  1329. begin
  1330. emit_reg(A_PUSH,
  1331. S_L,p^.left^.location.register);
  1332. ungetregister32(p^.left^.location.register);
  1333. end;
  1334. LOC_MEM,LOC_REFERENCE:
  1335. begin
  1336. emit_ref(A_PUSH,
  1337. S_L,newreference(p^.left^.location.reference));
  1338. del_reference(p^.left^.location.reference);
  1339. end;
  1340. else internalerror(100);
  1341. end;
  1342. { generate type checking }
  1343. secondpass(p^.right);
  1344. case p^.right^.location.loc of
  1345. LOC_REGISTER,LOC_CREGISTER:
  1346. begin
  1347. emit_reg(A_PUSH,
  1348. S_L,p^.right^.location.register);
  1349. ungetregister32(p^.right^.location.register);
  1350. end;
  1351. LOC_MEM,LOC_REFERENCE:
  1352. begin
  1353. emit_ref(A_PUSH,
  1354. S_L,newreference(p^.right^.location.reference));
  1355. del_reference(p^.right^.location.reference);
  1356. end;
  1357. else internalerror(100);
  1358. end;
  1359. emitcall('FPC_DO_IS');
  1360. emit_reg_reg(A_OR,S_B,R_AL,R_AL);
  1361. popusedregisters(pushed);
  1362. maybe_loadesi;
  1363. end;
  1364. {*****************************************************************************
  1365. SecondAs
  1366. *****************************************************************************}
  1367. procedure secondas(var p : ptree);
  1368. var
  1369. pushed : tpushed;
  1370. begin
  1371. secondpass(p^.left);
  1372. { save all used registers }
  1373. pushusedregisters(pushed,$ff);
  1374. { push instance to check: }
  1375. case p^.left^.location.loc of
  1376. LOC_REGISTER,LOC_CREGISTER:
  1377. emit_reg(A_PUSH,
  1378. S_L,p^.left^.location.register);
  1379. LOC_MEM,LOC_REFERENCE:
  1380. emit_ref(A_PUSH,
  1381. S_L,newreference(p^.left^.location.reference));
  1382. else internalerror(100);
  1383. end;
  1384. { we doesn't modifiy the left side, we check only the type }
  1385. set_location(p^.location,p^.left^.location);
  1386. { generate type checking }
  1387. secondpass(p^.right);
  1388. case p^.right^.location.loc of
  1389. LOC_REGISTER,LOC_CREGISTER:
  1390. begin
  1391. emit_reg(A_PUSH,
  1392. S_L,p^.right^.location.register);
  1393. ungetregister32(p^.right^.location.register);
  1394. end;
  1395. LOC_MEM,LOC_REFERENCE:
  1396. begin
  1397. emit_ref(A_PUSH,
  1398. S_L,newreference(p^.right^.location.reference));
  1399. del_reference(p^.right^.location.reference);
  1400. end;
  1401. else internalerror(100);
  1402. end;
  1403. emitcall('FPC_DO_AS');
  1404. { restore register, this restores automatically the }
  1405. { result }
  1406. popusedregisters(pushed);
  1407. maybe_loadesi;
  1408. end;
  1409. end.
  1410. {
  1411. $Log$
  1412. Revision 1.106 2000-05-26 20:16:00 jonas
  1413. * fixed wrong register deallocations in several ansistring related
  1414. procedures. The IDE's now function fine when compiled with -OG3p3r
  1415. Revision 1.105 2000/04/10 12:23:19 jonas
  1416. * modified copyshortstring so it takes an extra paramter which allows it
  1417. to delete the sref itself (so the reg deallocations are put in the
  1418. right place for the optimizer)
  1419. Revision 1.104 2000/03/31 22:56:45 pierre
  1420. * fix the handling of value parameters in cdecl function
  1421. Revision 1.103 2000/02/19 10:12:47 florian
  1422. * fixed one more internalerror 10
  1423. Revision 1.102 2000/02/09 13:22:46 peter
  1424. * log truncated
  1425. Revision 1.101 2000/01/13 16:52:48 jonas
  1426. * moved deallocation of registers used in reference that points to string after
  1427. copyshortstring (this routine doesn't require extra regs)
  1428. Revision 1.100 2000/01/09 12:35:00 jonas
  1429. * changed edi allocation to use getexplicitregister32/ungetregister
  1430. (adapted tgeni386 a bit for this) and enabled it by default
  1431. * fixed very big and stupid bug of mine in cg386mat that broke the
  1432. include() code (and make cycle :( ) if you compiled without
  1433. -dnewoptimizations
  1434. Revision 1.99 2000/01/09 01:44:19 jonas
  1435. + (de)allocation info for EDI to fix reported bug on mailinglist.
  1436. Also some (de)allocation info for ESI added. Between -dallocEDI
  1437. because at this time of the night bugs could easily slip in ;)
  1438. Revision 1.98 2000/01/07 01:14:20 peter
  1439. * updated copyright to 2000
  1440. Revision 1.97 1999/12/22 01:01:46 peter
  1441. - removed freelabel()
  1442. * added undefined label detection in internal assembler, this prevents
  1443. a lot of ld crashes and wrong .o files
  1444. * .o files aren't written anymore if errors have occured
  1445. * inlining of assembler labels is now correct
  1446. Revision 1.96 1999/12/21 11:49:51 pierre
  1447. * array of char to short string bug fixed
  1448. Revision 1.95 1999/12/01 12:42:31 peter
  1449. * fixed bug 698
  1450. * removed some notes about unused vars
  1451. Revision 1.94 1999/11/29 22:15:25 pierre
  1452. * fix for internalerror(12) on ord(booleanarray[1])
  1453. Revision 1.93 1999/11/06 14:34:17 peter
  1454. * truncated log to 20 revs
  1455. Revision 1.92 1999/10/25 10:32:43 peter
  1456. * ansistring 2 chararray support
  1457. * optimized ansitring 2 pchar
  1458. Revision 1.91 1999/10/22 14:36:04 peter
  1459. * fixed esi reload with as
  1460. Revision 1.90 1999/10/06 08:32:00 peter
  1461. * fixed empty const ansistring 2 pchar
  1462. Revision 1.89 1999/09/26 21:30:15 peter
  1463. + constant pointer support which can happend with typecasting like
  1464. const p=pointer(1)
  1465. * better procvar parsing in typed consts
  1466. Revision 1.88 1999/09/26 13:26:04 florian
  1467. * exception patch of Romio nevertheless the excpetion handling
  1468. needs some corections regarding register saving
  1469. * gettempansistring is again a procedure
  1470. Revision 1.87 1999/09/23 21:20:37 peter
  1471. * fixed temp allocation for short->ansi
  1472. Revision 1.86 1999/09/01 09:42:13 peter
  1473. * update for new push_lea_loc
  1474. Revision 1.85 1999/08/19 13:08:46 pierre
  1475. * emit_??? used
  1476. Revision 1.84 1999/08/05 14:58:03 florian
  1477. * some fixes for the floating point registers
  1478. * more things for the new code generator
  1479. Revision 1.83 1999/08/04 13:45:19 florian
  1480. + floating point register variables !!
  1481. * pairegalloc is now generated for register variables
  1482. Revision 1.82 1999/08/04 00:22:43 florian
  1483. * renamed i386asm and i386base to cpuasm and cpubase
  1484. }