cg386cnv.pas 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533
  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.2 2000-07-13 11:32:33 michael
  1413. + removed logs
  1414. }