ncgcnv.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Generate assembler for nodes that handle type conversions which are
  4. the same for all (most) processors
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgcnv;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,ncnv,defutil,defcmp;
  23. type
  24. { tcgtypeconvnode }
  25. tcgtypeconvnode = class(ttypeconvnode)
  26. procedure second_int_to_int;override;
  27. procedure second_cstring_to_pchar;override;
  28. procedure second_cstring_to_int;override;
  29. procedure second_string_to_chararray;override;
  30. procedure second_array_to_pointer;override;
  31. procedure second_pointer_to_array;override;
  32. procedure second_char_to_string;override;
  33. procedure second_real_to_real;override;
  34. procedure second_cord_to_pointer;override;
  35. procedure second_proc_to_procvar;override;
  36. procedure second_nil_to_methodprocvar;override;
  37. procedure second_bool_to_int;override;
  38. procedure second_bool_to_bool;override;
  39. procedure second_ansistring_to_pchar;override;
  40. procedure second_class_to_intf;override;
  41. procedure second_char_to_char;override;
  42. procedure second_nothing;override;
  43. procedure pass_generate_code;override;
  44. procedure second_int_to_bool;override;
  45. end;
  46. tcgasnode = class(tasnode)
  47. procedure pass_generate_code;override;
  48. end;
  49. implementation
  50. uses
  51. cutils,verbose,globtype,globals,
  52. aasmbase,aasmtai,aasmdata,aasmcpu,symconst,symdef,paramgr,
  53. nutils,ncon,ncal,
  54. cpubase,systems,
  55. procinfo,pass_2,
  56. cgbase,
  57. cgutils,cgobj,
  58. ncgutil,
  59. tgobj
  60. ;
  61. procedure tcgtypeconvnode.second_int_to_int;
  62. var
  63. orgsize,
  64. newsize : tcgsize;
  65. ressize,
  66. leftsize : longint;
  67. begin
  68. newsize:=def_cgsize(resultdef);
  69. { insert range check if not explicit conversion }
  70. if not(nf_explicit in flags) then
  71. cg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
  72. { is the result size smaller? when typecasting from void
  73. we always reuse the current location, because there is
  74. nothing that we can load in a register }
  75. ressize := resultdef.size;
  76. leftsize := left.resultdef.size;
  77. if ((ressize<>leftsize) or
  78. is_bitpacked_access(left)) and
  79. not is_void(left.resultdef) then
  80. begin
  81. location_copy(location,left.location);
  82. { reuse a loc_reference when the newsize is smaller than
  83. than the original, else load it to a register }
  84. if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  85. (ressize<leftsize) then
  86. begin
  87. location.size:=newsize;
  88. if (target_info.endian = ENDIAN_BIG) then
  89. begin
  90. inc(location.reference.offset,leftsize-ressize);
  91. location.reference.alignment:=newalignment(location.reference.alignment,leftsize-ressize);
  92. end;
  93. end
  94. else
  95. location_force_reg(current_asmdata.CurrAsmList,location,newsize,false);
  96. end
  97. else
  98. begin
  99. { no special loading is required, reuse current location }
  100. { that's not true, if you go from signed to unsiged or }
  101. { vice versa, you need sign extension/removal if the }
  102. { value is already in a register (at least for archs }
  103. { which don't have 8bit register components etc) (JM) }
  104. location_copy(location,left.location);
  105. location.size:=newsize;
  106. orgsize := def_cgsize(left.resultdef);
  107. if (ressize < sizeof(aint)) and
  108. (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
  109. (orgsize <> newsize) then
  110. begin
  111. location.register := cg.getintregister(current_asmdata.CurrAsmList,newsize);
  112. location.loc := LOC_REGISTER;
  113. cg.a_load_reg_reg(current_asmdata.CurrAsmList,orgsize,newsize,left.location.register,location.register);
  114. end;
  115. end;
  116. end;
  117. procedure tcgtypeconvnode.second_int_to_bool;
  118. var
  119. hregister : tregister;
  120. href : treference;
  121. resflags : tresflags;
  122. hlabel,oldTrueLabel,oldFalseLabel : tasmlabel;
  123. newsize : tcgsize;
  124. begin
  125. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  126. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  127. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  128. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  129. secondpass(left);
  130. if codegenerror then
  131. exit;
  132. { Explicit typecasts from any ordinal type to a boolean type }
  133. { must not change the ordinal value }
  134. if (nf_explicit in flags) and
  135. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
  136. begin
  137. location_copy(location,left.location);
  138. newsize:=def_cgsize(resultdef);
  139. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  140. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  141. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  142. location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
  143. else
  144. location.size:=newsize;
  145. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  146. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  147. exit;
  148. end;
  149. { Load left node into flag F_NE/F_E }
  150. resflags:=F_NE;
  151. case left.location.loc of
  152. LOC_CREFERENCE,
  153. LOC_REFERENCE :
  154. begin
  155. if left.location.size in [OS_64,OS_S64] then
  156. begin
  157. hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  158. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hregister);
  159. href:=left.location.reference;
  160. inc(href.offset,4);
  161. cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hregister);
  162. end
  163. else
  164. begin
  165. location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
  166. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
  167. end;
  168. end;
  169. LOC_FLAGS :
  170. begin
  171. resflags:=left.location.resflags;
  172. end;
  173. LOC_REGISTER,LOC_CREGISTER :
  174. begin
  175. if left.location.size in [OS_64,OS_S64] then
  176. begin
  177. hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  178. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reglo,hregister);
  179. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister);
  180. end
  181. else
  182. begin
  183. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
  184. end;
  185. end;
  186. LOC_JUMP :
  187. begin
  188. hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  189. current_asmdata.getjumplabel(hlabel);
  190. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  191. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hregister);
  192. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  193. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  194. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hregister);
  195. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  196. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,hregister,hregister);
  197. end;
  198. else
  199. internalerror(200311301);
  200. end;
  201. { load flags to register }
  202. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  203. location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  204. cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,location.register);
  205. if (is_cbool(resultdef)) then
  206. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,location.register,location.register);
  207. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  208. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  209. end;
  210. procedure tcgtypeconvnode.second_cstring_to_pchar;
  211. var
  212. hr : treference;
  213. begin
  214. if left.nodetype<>stringconstn then
  215. internalerror(200601131);
  216. location_reset(location,LOC_REGISTER,OS_ADDR);
  217. case tstringconstnode(left).cst_type of
  218. cst_conststring :
  219. begin
  220. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  221. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
  222. end;
  223. cst_shortstring :
  224. begin
  225. inc(left.location.reference.offset);
  226. location.reference.alignment:=1;
  227. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  228. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
  229. end;
  230. cst_widestring,
  231. cst_unicodestring,
  232. cst_ansistring :
  233. begin
  234. if tstringconstnode(left).len=0 then
  235. begin
  236. { FPC_EMPTYCHAR is a widechar -> 2 bytes }
  237. reference_reset(hr,2);
  238. hr.symbol:=current_asmdata.RefAsmSymbol('FPC_EMPTYCHAR');
  239. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  240. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hr,location.register);
  241. end
  242. else
  243. begin
  244. location_copy(location,left.location);
  245. end;
  246. end;
  247. cst_longstring:
  248. begin
  249. {!!!!!!!}
  250. internalerror(8888);
  251. end;
  252. else
  253. internalerror(200808241);
  254. end;
  255. end;
  256. procedure tcgtypeconvnode.second_cstring_to_int;
  257. begin
  258. { this can't happen because constants are already processed in
  259. pass 1 }
  260. internalerror(200510013);
  261. end;
  262. procedure tcgtypeconvnode.second_string_to_chararray;
  263. begin
  264. if is_chararray(left.resultdef) then
  265. begin
  266. location_copy(location,left.location);
  267. exit;
  268. end;
  269. { should be handled already in resultdef pass (JM) }
  270. internalerror(200108292);
  271. end;
  272. procedure tcgtypeconvnode.second_array_to_pointer;
  273. begin
  274. location_reset(location,LOC_REGISTER,OS_ADDR);
  275. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  276. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
  277. end;
  278. procedure tcgtypeconvnode.second_pointer_to_array;
  279. begin
  280. { assume natural alignment }
  281. location_reset_ref(location,LOC_REFERENCE,OS_NO,resultdef.alignment);
  282. case left.location.loc of
  283. LOC_CREGISTER,
  284. LOC_REGISTER :
  285. begin
  286. {$ifdef cpu_uses_separate_address_registers}
  287. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  288. begin
  289. location.reference.base:=rg.getaddressregister(current_asmdata.CurrAsmList);
  290. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
  291. left.location.register,location.reference.base);
  292. end
  293. else
  294. {$endif}
  295. location.reference.base := left.location.register;
  296. end;
  297. LOC_REFERENCE,
  298. LOC_CREFERENCE :
  299. begin
  300. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  301. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,
  302. location.reference.base);
  303. location_freetemp(current_asmdata.CurrAsmList,left.location);
  304. end;
  305. else
  306. internalerror(2002032216);
  307. end;
  308. end;
  309. procedure tcgtypeconvnode.second_char_to_string;
  310. begin
  311. location_reset_ref(location,LOC_REFERENCE,OS_NO,2);
  312. case tstringdef(resultdef).stringtype of
  313. st_shortstring :
  314. begin
  315. tg.GetTemp(current_asmdata.CurrAsmList,256,2,tt_normal,location.reference);
  316. cg.a_load_loc_ref(current_asmdata.CurrAsmList,left.location.size,left.location,
  317. location.reference);
  318. location_freetemp(current_asmdata.CurrAsmList,left.location);
  319. end;
  320. { the rest is removed in the resultdef pass and converted to compilerprocs }
  321. else
  322. internalerror(4179);
  323. end;
  324. end;
  325. procedure tcgtypeconvnode.second_real_to_real;
  326. {$ifdef x86}
  327. var
  328. tr: treference;
  329. {$endif x86}
  330. begin
  331. location_reset(location,expectloc,def_cgsize(resultdef));
  332. {$ifdef x86}
  333. { extended types in memory which should be loaded into the sse unit
  334. must be converted by the fpu first, so force them to be loaded into
  335. the fpu }
  336. if (expectloc=LOC_MMREGISTER) and
  337. (left.location.size in [OS_F80,OS_C64]) then
  338. begin
  339. if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  340. location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
  341. { round them down to the proper precision }
  342. tg.gettemp(current_asmdata.currasmlist,resultdef.size,resultdef.alignment,tt_normal,tr);
  343. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,tr);
  344. location_reset_ref(left.location,LOC_REFERENCE,location.size,tr.alignment);
  345. left.location.reference:=tr;
  346. end;
  347. {$endif x86}
  348. { ARM VFP values are in integer registers when they are function results }
  349. if (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  350. location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
  351. case left.location.loc of
  352. LOC_FPUREGISTER,
  353. LOC_CFPUREGISTER:
  354. begin
  355. case expectloc of
  356. LOC_FPUREGISTER:
  357. begin
  358. { on sparc a move from double -> single means from two to one register. }
  359. { On all other platforms it also needs rounding to avoid that }
  360. { single(double_regvar) = double_regvar is true in all cases }
  361. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  362. cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
  363. end;
  364. LOC_MMREGISTER:
  365. begin
  366. location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
  367. location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
  368. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register,mms_movescalar);
  369. end
  370. else
  371. internalerror(2003012262);
  372. end;
  373. exit
  374. end;
  375. LOC_CREFERENCE,
  376. LOC_REFERENCE:
  377. begin
  378. if expectloc=LOC_MMREGISTER then
  379. begin
  380. location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
  381. cg.a_loadmm_loc_reg(current_asmdata.CurrAsmList,location.size,left.location,location.register,mms_movescalar)
  382. end
  383. else
  384. begin
  385. location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
  386. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  387. cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
  388. end;
  389. location_freetemp(current_asmdata.CurrAsmList,left.location);
  390. end;
  391. LOC_MMREGISTER,
  392. LOC_CMMREGISTER:
  393. begin
  394. case expectloc of
  395. LOC_FPUREGISTER:
  396. begin
  397. location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
  398. location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
  399. cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
  400. end;
  401. LOC_MMREGISTER:
  402. begin
  403. location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
  404. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register,mms_movescalar);
  405. end;
  406. else
  407. internalerror(2003012261);
  408. end;
  409. end;
  410. else
  411. internalerror(2002032215);
  412. end;
  413. end;
  414. procedure tcgtypeconvnode.second_cord_to_pointer;
  415. begin
  416. { this can't happen because constants are already processed in
  417. pass 1 }
  418. internalerror(47423985);
  419. end;
  420. procedure tcgtypeconvnode.second_proc_to_procvar;
  421. var
  422. tmpreg: tregister;
  423. begin
  424. if tabstractprocdef(resultdef).is_addressonly then
  425. begin
  426. location_reset(location,LOC_REGISTER,OS_ADDR);
  427. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  428. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
  429. end
  430. else
  431. begin
  432. if not tabstractprocdef(left.resultdef).is_addressonly then
  433. location_copy(location,left.location)
  434. else
  435. begin
  436. { assigning a global function to a nested procvar -> create
  437. tmethodpointer record and set the "frame pointer" to nil }
  438. location_reset_ref(location,LOC_REFERENCE,int_cgsize(sizeof(pint)*2),sizeof(pint));
  439. tg.gettemp(current_asmdata.CurrAsmList,resultdef.size,sizeof(pint),tt_normal,location.reference);
  440. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  441. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,tmpreg);
  442. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,location.reference);
  443. { setting the frame pointer to nil is not strictly necessary
  444. since the global procedure won't use it, but it can help with
  445. debugging }
  446. inc(location.reference.offset,sizeof(pint));
  447. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_ADDR,0,location.reference);
  448. dec(location.reference.offset,sizeof(pint));
  449. end;
  450. end;
  451. end;
  452. procedure Tcgtypeconvnode.second_nil_to_methodprocvar;
  453. var r:Treference;
  454. begin
  455. tg.gettemp(current_asmdata.currasmlist,2*sizeof(puint),sizeof(puint),tt_normal,r);
  456. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),0);
  457. location.reference:=r;
  458. cg.a_load_const_ref(current_asmdata.currasmlist,OS_ADDR,0,r);
  459. inc(r.offset,sizeof(puint));
  460. cg.a_load_const_ref(current_asmdata.currasmlist,OS_ADDR,0,r);
  461. end;
  462. procedure tcgtypeconvnode.second_bool_to_int;
  463. var
  464. newsize: tcgsize;
  465. oldTrueLabel,oldFalseLabel : tasmlabel;
  466. begin
  467. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  468. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  469. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  470. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  471. secondpass(left);
  472. location_copy(location,left.location);
  473. newsize:=def_cgsize(resultdef);
  474. { byte(bytebool) or word(wordbool) or longint(longbool) must be }
  475. { accepted for var parameters and assignments, and must not }
  476. { change the ordinal value or value location. }
  477. { htypechk.valid_for_assign ensures that such locations with a }
  478. { size<sizeof(register) cannot be LOC_CREGISTER (they otherwise }
  479. { could be in case of a plain assignment), and LOC_REGISTER can }
  480. { never be an assignment target. The remaining LOC_REGISTER/ }
  481. { LOC_CREGISTER locations do have to be sign/zero-extended. }
  482. if not(nf_explicit in flags) or
  483. (location.loc in [LOC_FLAGS,LOC_JUMP]) or
  484. { change of size/signedness? Then we have to sign/ }
  485. { zero-extend in case of a loc_(c)register }
  486. ((newsize<>left.location.size) and
  487. ((left.resultdef.size<>resultdef.size) or
  488. not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]))) then
  489. location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
  490. else
  491. { may differ in sign, e.g. bytebool -> byte }
  492. location.size:=newsize;
  493. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  494. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  495. end;
  496. procedure tcgtypeconvnode.second_bool_to_bool;
  497. begin
  498. { we can reuse the conversion already available
  499. in bool_to_int to resize the value. But when the
  500. size of the new boolean is smaller we need to calculate
  501. the value as is done in int_to_bool. This is needed because
  502. the bits that define the true status can be outside the limits
  503. of the new size and truncating the register can result in a 0
  504. value }
  505. if (left.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  506. { a cbool must be converted to -1/0 }
  507. not is_cbool(resultdef) then
  508. begin
  509. secondpass(left);
  510. if (left.location.loc <> left.expectloc) then
  511. internalerror(2010081601);
  512. location_copy(location,left.location);
  513. end
  514. else if (resultdef.size=left.resultdef.size) and
  515. (is_cbool(resultdef)=is_cbool(left.resultdef)) then
  516. second_bool_to_int
  517. else
  518. begin
  519. if (resultdef.size<>left.resultdef.size) then
  520. { remove nf_explicit to perform full conversion if boolean sizes are different }
  521. exclude(flags, nf_explicit);
  522. second_int_to_bool;
  523. end;
  524. end;
  525. procedure tcgtypeconvnode.second_ansistring_to_pchar;
  526. var
  527. l1 : tasmlabel;
  528. hr : treference;
  529. begin
  530. location_reset(location,LOC_REGISTER,OS_ADDR);
  531. current_asmdata.getjumplabel(l1);
  532. case left.location.loc of
  533. LOC_CREGISTER,LOC_REGISTER:
  534. begin
  535. {$ifdef cpu_uses_separate_address_registers}
  536. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  537. begin
  538. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  539. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
  540. left.location.register,location.register);
  541. end
  542. else
  543. {$endif}
  544. location.register := left.location.register;
  545. end;
  546. LOC_CREFERENCE,LOC_REFERENCE:
  547. begin
  548. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  549. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.register);
  550. end;
  551. else
  552. internalerror(2002032214);
  553. end;
  554. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_NE,0,location.register,l1);
  555. { FPC_EMPTYCHAR is a widechar -> 2 bytes }
  556. reference_reset(hr,2);
  557. hr.symbol:=current_asmdata.RefAsmSymbol('FPC_EMPTYCHAR');
  558. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hr,location.register);
  559. cg.a_label(current_asmdata.CurrAsmList,l1);
  560. end;
  561. procedure tcgtypeconvnode.second_class_to_intf;
  562. var
  563. l1 : tasmlabel;
  564. hd : tobjectdef;
  565. ImplIntf : TImplementedInterface;
  566. begin
  567. location_reset(location,LOC_REGISTER,OS_ADDR);
  568. case left.location.loc of
  569. LOC_CREFERENCE,
  570. LOC_REFERENCE:
  571. begin
  572. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  573. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.register);
  574. location_freetemp(current_asmdata.CurrAsmList,left.location);
  575. end;
  576. LOC_CREGISTER:
  577. begin
  578. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  579. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,location.register);
  580. end;
  581. LOC_REGISTER:
  582. location.register:=left.location.register;
  583. else
  584. internalerror(121120001);
  585. end;
  586. hd:=tobjectdef(left.resultdef);
  587. while assigned(hd) do
  588. begin
  589. ImplIntf:=hd.find_implemented_interface(tobjectdef(resultdef));
  590. if assigned(ImplIntf) then
  591. begin
  592. case ImplIntf.IType of
  593. etStandard:
  594. begin
  595. current_asmdata.getjumplabel(l1);
  596. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,location.register,l1);
  597. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,ImplIntf.ioffset,location.register);
  598. break;
  599. end;
  600. else
  601. internalerror(200802163);
  602. end;
  603. end;
  604. hd:=hd.childof;
  605. end;
  606. if hd=nil then
  607. internalerror(2002081301);
  608. cg.a_label(current_asmdata.CurrAsmList,l1);
  609. end;
  610. procedure tcgtypeconvnode.second_char_to_char;
  611. begin
  612. internalerror(2007081202);
  613. end;
  614. procedure tcgtypeconvnode.second_nothing;
  615. var
  616. newsize : tcgsize;
  617. begin
  618. { we reuse the old value }
  619. location_copy(location,left.location);
  620. { Floats should never be returned as LOC_CONSTANT, do the
  621. moving to memory before the new size is set.
  622. Also when converting from a float to a non-float
  623. or the other way round, move to memory first to prevent
  624. invalid LOC_FPUREGISTER locations }
  625. if (
  626. (resultdef.typ=floatdef) and
  627. (location.loc=LOC_CONSTANT)
  628. ) or
  629. (
  630. (left.resultdef.typ=floatdef) xor
  631. (resultdef.typ=floatdef)
  632. ) then
  633. location_force_mem(current_asmdata.CurrAsmList,location);
  634. { but use the new size, but we don't know the size of all arrays }
  635. newsize:=def_cgsize(resultdef);
  636. location.size:=newsize;
  637. end;
  638. {$ifdef TESTOBJEXT2}
  639. procedure tcgtypeconvnode.checkobject;
  640. begin
  641. { no checking by default }
  642. end;
  643. {$endif TESTOBJEXT2}
  644. procedure tcgtypeconvnode.pass_generate_code;
  645. begin
  646. { the boolean routines can be called with LOC_JUMP and
  647. call secondpass themselves in the helper }
  648. if not(convtype in [tc_bool_2_int,tc_bool_2_bool,tc_int_2_bool]) then
  649. begin
  650. secondpass(left);
  651. if codegenerror then
  652. exit;
  653. end;
  654. second_call_helper(convtype);
  655. {$ifdef TESTOBJEXT2}
  656. { Check explicit conversions to objects pointers !! }
  657. if p^.explizit and
  658. (p^.resultdef.typ=pointerdef) and
  659. (tpointerdef(p^.resultdef).definition.typ=objectdef) and not
  660. (tobjectdef(tpointerdef(p^.resultdef).definition).isclass) and
  661. ((tobjectdef(tpointerdef(p^.resultdef).definition).options and oo_hasvmt)<>0) and
  662. (cs_check_range in current_settings.localswitches) then
  663. checkobject;
  664. {$endif TESTOBJEXT2}
  665. end;
  666. procedure tcgasnode.pass_generate_code;
  667. begin
  668. secondpass(call);
  669. location_copy(location,call.location);
  670. end;
  671. begin
  672. ctypeconvnode := tcgtypeconvnode;
  673. casnode := tcgasnode;
  674. end.