njvmcnv.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. {
  2. Copyright (c) 1998-2011 by Florian Klaempfl and Jonas Maebe
  3. Generate JVM code for type converting nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************}
  16. unit njvmcnv;
  17. {$i fpcdefs.inc}
  18. interface
  19. uses
  20. node,ncnv,ncgcnv,
  21. symtype;
  22. type
  23. tjvmtypeconvnode = class(tcgtypeconvnode)
  24. function typecheck_dynarray_to_openarray: tnode; override;
  25. function typecheck_string_to_chararray: tnode; override;
  26. function pass_1: tnode; override;
  27. procedure second_int_to_int;override;
  28. { procedure second_string_to_string;override; }
  29. { procedure second_cstring_to_pchar;override; }
  30. { procedure second_string_to_chararray;override; }
  31. { procedure second_array_to_pointer;override; }
  32. function first_int_to_real: tnode; override;
  33. { procedure second_pointer_to_array;override; }
  34. { procedure second_chararray_to_string;override; }
  35. { procedure second_char_to_string;override; }
  36. procedure second_int_to_real;override;
  37. { procedure second_real_to_real;override; }
  38. { procedure second_cord_to_pointer;override; }
  39. { procedure second_proc_to_procvar;override; }
  40. procedure second_bool_to_int;override;
  41. procedure second_int_to_bool;override;
  42. { procedure second_load_smallset;override; }
  43. { procedure second_ansistring_to_pchar;override; }
  44. { procedure second_pchar_to_string;override; }
  45. { procedure second_class_to_intf;override; }
  46. { procedure second_char_to_char;override; }
  47. function target_specific_explicit_typeconv: boolean; override;
  48. function target_specific_general_typeconv: boolean; override;
  49. protected
  50. function do_target_specific_explicit_typeconv(check_only: boolean; out resnode: tnode): boolean;
  51. end;
  52. tjvmasnode = class(tcgasnode)
  53. protected
  54. function target_specific_typecheck: boolean;override;
  55. public
  56. function pass_1 : tnode;override;
  57. procedure pass_generate_code; override;
  58. end;
  59. tjvmisnode = class(tisnode)
  60. protected
  61. function target_specific_typecheck: boolean;override;
  62. public
  63. function pass_1 : tnode;override;
  64. procedure pass_generate_code; override;
  65. end;
  66. implementation
  67. uses
  68. verbose,globals,globtype,
  69. symconst,symdef,symsym,symtable,aasmbase,aasmdata,
  70. defutil,defcmp,jvmdef,
  71. cgbase,cgutils,pass_1,pass_2,
  72. nbas,ncon,ncal,nld,nmem,procinfo,
  73. nutils,
  74. cpubase,aasmcpu,
  75. tgobj,hlcgobj,hlcgcpu;
  76. {*****************************************************************************
  77. TypeCheckTypeConv
  78. *****************************************************************************}
  79. function tjvmtypeconvnode.typecheck_dynarray_to_openarray: tnode;
  80. begin
  81. { all arrays are equal in Java }
  82. left.resultdef:=resultdef;
  83. result:=left;
  84. left:=nil;
  85. end;
  86. function tjvmtypeconvnode.typecheck_string_to_chararray: tnode;
  87. var
  88. newblock: tblocknode;
  89. newstat: tstatementnode;
  90. restemp: ttempcreatenode;
  91. chartype: string;
  92. begin
  93. if (left.nodetype = stringconstn) and
  94. (tstringconstnode(left).cst_type=cst_conststring) then
  95. inserttypeconv(left,cunicodestringtype);
  96. { even constant strings have to be handled via a helper }
  97. if is_widechar(tarraydef(resultdef).elementdef) then
  98. chartype:='widechar'
  99. else
  100. chartype:='char';
  101. newblock:=internalstatements(newstat);
  102. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  103. addstatement(newstat,restemp);
  104. addstatement(newstat,ccallnode.createintern('fpc_'+tstringdef(left.resultdef).stringtypname+
  105. '_to_'+chartype+'array',ccallparanode.create(left,ccallparanode.create(
  106. ctemprefnode.create(restemp),nil))));
  107. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  108. addstatement(newstat,ctemprefnode.create(restemp));
  109. result:=newblock;
  110. left:=nil;
  111. end;
  112. {*****************************************************************************
  113. FirstTypeConv
  114. *****************************************************************************}
  115. function tjvmtypeconvnode.first_int_to_real: tnode;
  116. begin
  117. if not is_64bitint(left.resultdef) then
  118. if is_signed(left.resultdef) or
  119. (left.resultdef.size<4) then
  120. inserttypeconv(left,s32inttype)
  121. else
  122. inserttypeconv(left,u32inttype);
  123. firstpass(left);
  124. result := nil;
  125. expectloc:=LOC_FPUREGISTER;
  126. end;
  127. function tjvmtypeconvnode.pass_1: tnode;
  128. begin
  129. if (nf_explicit in flags) then
  130. begin
  131. do_target_specific_explicit_typeconv(false,result);
  132. if assigned(result) then
  133. exit;
  134. end;
  135. result:=inherited pass_1;
  136. end;
  137. {*****************************************************************************
  138. SecondTypeConv
  139. *****************************************************************************}
  140. procedure tjvmtypeconvnode.second_int_to_int;
  141. var
  142. ressize,
  143. leftsize : longint;
  144. begin
  145. { insert range check if not explicit conversion }
  146. if not(nf_explicit in flags) then
  147. hlcg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
  148. { is the result size smaller? when typecasting from void
  149. we always reuse the current location, because there is
  150. nothing that we can load in a register }
  151. ressize:=resultdef.size;
  152. leftsize :=left.resultdef.size;
  153. if ((ressize<>leftsize) or
  154. ((location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  155. (location.reference.arrayreftype<>art_none) and
  156. (is_widechar(left.resultdef)<>is_widechar(resultdef))) or
  157. is_bitpacked_access(left)) and
  158. not is_void(left.resultdef) then
  159. begin
  160. location_copy(location,left.location);
  161. { reuse a loc_reference when the newsize is smaller than
  162. than the original, except
  163. a) for arrays (they use different load instructions for
  164. differently sized data types)
  165. b) when going from 8 to 4 bytes, because these are different
  166. data types
  167. -- note that this is different from other targets, and will
  168. break stuff like passing byte(shortintvar) to a var-parameter;
  169. although that may be "fixed" again because we have to use
  170. copy-in/copy-out to emulate var-parameters anyway... }
  171. if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  172. (location.reference.arrayreftype=art_none) and
  173. (ressize<leftsize) and
  174. (leftsize<=4) then
  175. begin
  176. location.size:=def_cgsize(resultdef);
  177. { no adjustment of the ffset even though Java is big endian,
  178. because the load instruction will remain the same }
  179. end
  180. else
  181. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,false);
  182. end
  183. else
  184. begin
  185. location_copy(location,left.location);
  186. location.size:=def_cgsize(resultdef);
  187. if (ressize < sizeof(aint)) and
  188. (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
  189. (def_cgsize(left.resultdef)<>def_cgsize(resultdef)) then
  190. begin
  191. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  192. location.loc:=LOC_REGISTER;
  193. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register);
  194. end;
  195. end;
  196. end;
  197. procedure tjvmtypeconvnode.second_int_to_real;
  198. var
  199. srcsize, ressize: longint;
  200. procedure convertsignedstackloc;
  201. begin
  202. case srcsize of
  203. 4:
  204. case ressize of
  205. 4:
  206. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2f));
  207. 8:
  208. begin
  209. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2d));
  210. thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
  211. end;
  212. else
  213. internalerror(2011010601);
  214. end;
  215. 8:
  216. case ressize of
  217. 4:
  218. begin
  219. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2f));
  220. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  221. end;
  222. 8:
  223. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2d));
  224. else
  225. internalerror(2011010602);
  226. end;
  227. else
  228. internalerror(2011010603);
  229. end;
  230. end;
  231. var
  232. signeddef : tdef;
  233. l1 : tasmlabel;
  234. begin
  235. srcsize:=left.resultdef.size;
  236. ressize:=resultdef.size;
  237. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  238. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  239. { first always convert as if it's a signed number }
  240. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  241. convertsignedstackloc;
  242. if not is_signed(left.resultdef) then
  243. begin
  244. { if it was unsigned, add high(cardinal)+1/high(qword)+1 in case
  245. the signed interpretation is < 0 }
  246. current_asmdata.getjumplabel(l1);
  247. if srcsize=4 then
  248. signeddef:=s32inttype
  249. else
  250. signeddef:=s64inttype;
  251. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,signeddef,OC_GTE,0,left.location,l1);
  252. if srcsize=4 then
  253. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,4294967296.0)
  254. else
  255. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,18446744073709551616.0);
  256. if ressize=4 then
  257. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_fadd))
  258. else
  259. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dadd));
  260. hlcg.a_label(current_asmdata.CurrAsmList,l1);
  261. end;
  262. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  263. end;
  264. procedure tjvmtypeconvnode.second_bool_to_int;
  265. var
  266. newsize: tcgsize;
  267. oldTrueLabel,oldFalseLabel : tasmlabel;
  268. begin
  269. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  270. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  271. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  272. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  273. secondpass(left);
  274. location_copy(location,left.location);
  275. newsize:=def_cgsize(resultdef);
  276. { byte(bytebool) or word(wordbool) or longint(longbool) must be }
  277. { accepted for var parameters and assignments, and must not }
  278. { change the ordinal value or value location. }
  279. { htypechk.valid_for_assign ensures that such locations with a }
  280. { size<sizeof(register) cannot be LOC_CREGISTER (they otherwise }
  281. { could be in case of a plain assignment), and LOC_REGISTER can }
  282. { never be an assignment target. The remaining LOC_REGISTER/ }
  283. { LOC_CREGISTER locations do have to be sign/zero-extended. }
  284. { -- Note: this does not work for Java and 2/4 byte sized
  285. values, because bytebool/wordbool are signed and
  286. are stored in 4 byte locations -> will result in
  287. "byte" with the value high(cardinal); see remark
  288. in second_int_to_int above regarding consequences }
  289. if not(nf_explicit in flags) or
  290. (location.loc in [LOC_FLAGS,LOC_JUMP]) or
  291. ((newsize<>left.location.size) and
  292. ((left.resultdef.size<>resultdef.size) or
  293. not(left.resultdef.size in [4,8]))
  294. ) then
  295. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  296. else
  297. { may differ in sign, e.g. bytebool -> byte }
  298. location.size:=newsize;
  299. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  300. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  301. end;
  302. procedure tjvmtypeconvnode.second_int_to_bool;
  303. var
  304. hlabel1,hlabel2,oldTrueLabel,oldFalseLabel : tasmlabel;
  305. newsize : tcgsize;
  306. begin
  307. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  308. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  309. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  310. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  311. secondpass(left);
  312. if codegenerror then
  313. exit;
  314. { Explicit typecasts from any ordinal type to a boolean type }
  315. { must not change the ordinal value }
  316. if (nf_explicit in flags) and
  317. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
  318. begin
  319. location_copy(location,left.location);
  320. newsize:=def_cgsize(resultdef);
  321. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  322. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  323. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  324. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  325. else
  326. location.size:=newsize;
  327. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  328. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  329. exit;
  330. end;
  331. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  332. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  333. current_asmdata.getjumplabel(hlabel2);
  334. case left.location.loc of
  335. LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
  336. begin
  337. current_asmdata.getjumplabel(hlabel1);
  338. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location,hlabel1);
  339. end;
  340. LOC_JUMP :
  341. begin
  342. hlabel1:=current_procinfo.CurrFalseLabel;
  343. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  344. end;
  345. else
  346. internalerror(10062);
  347. end;
  348. if not(is_cbool(resultdef)) then
  349. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,1,R_INTREGISTER)
  350. else
  351. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,-1,R_INTREGISTER);
  352. { we jump over the next constant load -> they don't appear on the
  353. stack simulataneously }
  354. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  355. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel2);
  356. hlcg.a_label(current_asmdata.CurrAsmList,hlabel1);
  357. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,0,R_INTREGISTER);
  358. hlcg.a_label(current_asmdata.CurrAsmList,hlabel2);
  359. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  360. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  361. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  362. end;
  363. procedure get_most_nested_types(var fromdef, todef: tdef);
  364. begin
  365. while is_dynamic_array(fromdef) and
  366. is_dynamic_array(todef) do
  367. begin
  368. fromdef:=tarraydef(fromdef).elementdef;
  369. todef:=tarraydef(todef).elementdef;
  370. end;
  371. end;
  372. function tjvmtypeconvnode.do_target_specific_explicit_typeconv(check_only: boolean; out resnode: tnode): boolean;
  373. { handle explicit typecast from int to to real or vice versa }
  374. function int_real_explicit_typecast(fdef: tfloatdef; const singlemethod, doublemethod: string): tnode;
  375. var
  376. csym: ttypesym;
  377. psym: tsym;
  378. begin
  379. { use the float/double to raw bits methods to get the bit pattern }
  380. if fdef.floattype=s32real then
  381. begin
  382. csym:=search_system_type('JLFLOAT');
  383. psym:=search_struct_member(tobjectdef(csym.typedef),singlemethod);
  384. end
  385. else
  386. begin
  387. csym:=search_system_type('JLDOUBLE');
  388. psym:=search_struct_member(tobjectdef(csym.typedef),doublemethod);
  389. end;
  390. if not assigned(psym) or
  391. (psym.typ<>procsym) then
  392. internalerror(2011012901);
  393. { call the (static class) method to get the raw bits }
  394. result:=ccallnode.create(ccallparanode.create(left,nil),
  395. tprocsym(psym),psym.owner,
  396. cloadvmtaddrnode.create(ctypenode.create(csym.typedef)),[]);
  397. { convert the result to the result type of this type conversion node }
  398. inserttypeconv_explicit(result,resultdef);
  399. { left is reused }
  400. left:=nil;
  401. end;
  402. var
  403. fromclasscompatible,
  404. toclasscompatible: boolean;
  405. fromdef,
  406. todef,
  407. jlclass: tdef;
  408. fromarrtype,
  409. toarrtype: char;
  410. begin
  411. resnode:=nil;
  412. { This routine is only called for explicit typeconversions of same-sized
  413. entities that aren't handled by normal type conversions -> bit pattern
  414. reinterpretations. In the JVM, many of these also need special
  415. handling because of the type safety. }
  416. { don't allow conversions between object-based and non-object-based
  417. types }
  418. fromclasscompatible:=
  419. (left.resultdef.typ=objectdef) or
  420. is_dynamic_array(left.resultdef) or
  421. ((left.resultdef.typ in [recorddef,stringdef]) and
  422. (resultdef.typ=objectdef));
  423. toclasscompatible:=
  424. (resultdef.typ=objectdef) or
  425. is_dynamic_array(resultdef) or
  426. ((resultdef.typ in [recorddef,stringdef]) and
  427. (left.resultdef.typ=objectdef));
  428. if fromclasscompatible and toclasscompatible then
  429. begin
  430. { we need an as-node to check the validity of the conversion (since
  431. it wasn't handled by another type conversion, we know it can't
  432. have been valid normally)
  433. Exceptions: (most nested) destination is
  434. * java.lang.Object, since everything is compatible with that type
  435. * related to source
  436. * a primitive that are represented by the same type in Java
  437. (e.g., byte and shortint) }
  438. fromdef:=left.resultdef;
  439. todef:=resultdef;
  440. get_most_nested_types(fromdef,todef);
  441. fromarrtype:=jvmarrtype_setlength(fromdef);
  442. toarrtype:=jvmarrtype_setlength(todef);
  443. if (compare_defs(fromdef,todef,nothingn)<te_equal) and
  444. not fromdef.is_related(todef) and
  445. (((fromdef.typ in [objectdef,recorddef,stringdef]) and
  446. not is_dynamic_array(fromdef)) or
  447. (todef<>java_jlobject)) and
  448. ((fromarrtype in ['A','R']) or
  449. (fromarrtype<>toarrtype)) then
  450. begin
  451. if not check_only and
  452. not assignment_side then
  453. begin
  454. resnode:=ctypenode.create(resultdef);
  455. if resultdef.typ=objectdef then
  456. resnode:=cloadvmtaddrnode.create(resnode);
  457. resnode:=casnode.create(left,resnode);
  458. left:=nil;
  459. end
  460. end
  461. { typecasting from a child to a parent type on the assignment side
  462. will (rightly) mess up the type safety verification of the JVM }
  463. else if assignment_side and
  464. (compare_defs(fromdef,todef,nothingn)<te_equal) then
  465. CGMessage(type_e_no_managed_assign_generic_typecast);
  466. result:=true;
  467. exit;
  468. end;
  469. { from classrefdef to JLClass and JLObject and back }
  470. if (left.resultdef.typ=classrefdef) or
  471. (resultdef.typ=classrefdef) then
  472. begin
  473. if (left.resultdef.typ=classrefdef) and
  474. (resultdef.typ=classrefdef) then
  475. begin
  476. if not tclassrefdef(left.resultdef).pointeddef.is_related(resultdef) and
  477. not tclassrefdef(resultdef).pointeddef.is_related(left.resultdef) then
  478. CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
  479. end
  480. else
  481. begin
  482. jlclass:=search_system_type('JLCLASS').typedef;
  483. if (left.resultdef<>jlclass) and
  484. (left.resultdef<>java_jlobject) and
  485. (resultdef<>jlclass) and
  486. (resultdef<>java_jlobject) then
  487. CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
  488. end;
  489. result:=true;
  490. exit;
  491. end;
  492. { don't allow conversions between different classes of primitive types,
  493. except for a few special cases }
  494. { float to int/enum explicit type conversion: get the bits }
  495. if (convtype<>tc_int_2_real) and
  496. (left.resultdef.typ=floatdef) and
  497. (is_integer(resultdef) or
  498. (resultdef.typ=enumdef)) then
  499. begin
  500. if not check_only then
  501. resnode:=int_real_explicit_typecast(tfloatdef(left.resultdef),'FLOATTORAWINTBITS','DOUBLETORAWLONGBITS');
  502. result:=true;
  503. exit;
  504. end;
  505. { int to float explicit type conversion: also use the bits }
  506. if (is_integer(left.resultdef) or
  507. (left.resultdef.typ=enumdef)) and
  508. (resultdef.typ=floatdef) then
  509. begin
  510. if (convtype<>tc_int_2_real) then
  511. begin
  512. if not check_only then
  513. resnode:=int_real_explicit_typecast(tfloatdef(resultdef),'INTBITSTOFLOAT','LONGBITSTODOUBLE');
  514. result:=true;
  515. end
  516. else
  517. result:=false;
  518. exit;
  519. end;
  520. { nothing special required when going between ordinals and enums }
  521. if (left.resultdef.typ in [orddef,enumdef]) and
  522. (resultdef.typ in [orddef,enumdef]) then
  523. begin
  524. result:=false;
  525. exit;
  526. end;
  527. {$ifndef nounsupported}
  528. if (left.resultdef.typ in [orddef,enumdef,setdef]) and
  529. (resultdef.typ in [orddef,enumdef,setdef]) then
  530. begin
  531. result:=false;
  532. exit;
  533. end;
  534. { non-literal type conversions }
  535. if convtype in
  536. [tc_char_2_string,
  537. tc_char_2_chararray,
  538. tc_string_2_string,
  539. tc_string_2_chararray,
  540. tc_real_2_real,
  541. tc_proc_2_procvar,
  542. tc_arrayconstructor_2_set,
  543. tc_set_to_set,
  544. tc_class_2_intf,
  545. tc_array_2_dynarray] then
  546. begin
  547. result:=false;
  548. exit;
  549. end;
  550. {$endif}
  551. { Todo:
  552. * int to set and vice versa
  553. * set to float and vice versa (via int) (maybe)
  554. * regular array of primitive to primitive and vice versa (maybe)
  555. * packed record to primitive and vice versa (maybe)
  556. Definitely not:
  557. * unpacked record to anything and vice versa (no alignment rules
  558. for Java)
  559. }
  560. { anything not explicitly handled is a problem }
  561. result:=true;
  562. CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
  563. end;
  564. function tjvmtypeconvnode.target_specific_explicit_typeconv: boolean;
  565. var
  566. dummyres: tnode;
  567. begin
  568. result:=do_target_specific_explicit_typeconv(true,dummyres);
  569. end;
  570. function tjvmtypeconvnode.target_specific_general_typeconv: boolean;
  571. begin
  572. result:=false;
  573. { deal with explicit typecasts between records and classes (for
  574. FpcBaseRecordType) }
  575. if ((left.resultdef.typ=recorddef) and
  576. (resultdef.typ=objectdef) and
  577. left.resultdef.is_related(resultdef)) or
  578. ((left.resultdef.typ=objectdef) and
  579. (resultdef.typ=recorddef) and
  580. resultdef.is_related(left.resultdef)) and
  581. (nf_explicit in flags) then
  582. begin
  583. convtype:=tc_equal;
  584. result:=true;
  585. exit;
  586. end;
  587. {$ifndef nounsupported}
  588. if ((left.resultdef.typ=procvardef) and
  589. ((resultdef=methodpointertype) or
  590. (resultdef=search_system_type('TMETHOD').typedef))) or
  591. ((resultdef.typ=procvardef) and
  592. ((left.resultdef=methodpointertype) or
  593. (left.resultdef=search_system_type('TMETHOD').typedef))) then
  594. begin
  595. convtype:=tc_equal;
  596. result:=true;
  597. exit;
  598. end;
  599. {$endif}
  600. end;
  601. {*****************************************************************************
  602. AsNode and IsNode common helpers
  603. *****************************************************************************}
  604. function asis_target_specific_typecheck(node: tasisnode): boolean;
  605. function isrecordconv(fromdef, todef: tdef): boolean;
  606. begin
  607. if is_record(todef) then
  608. begin
  609. result:=
  610. (fromdef=java_jlobject) or
  611. (fromdef=java_fpcbaserecordtype);
  612. end
  613. else if is_record(fromdef) then
  614. begin
  615. result:=
  616. (todef=java_jlobject) or
  617. (todef=java_fpcbaserecordtype)
  618. end
  619. else
  620. result:=false;
  621. end;
  622. function isstringconv(fromdef, todef: tdef): boolean;
  623. begin
  624. if is_wide_or_unicode_string(todef) then
  625. begin
  626. result:=
  627. (fromdef=java_jlobject) or
  628. (fromdef=java_jlstring)
  629. end
  630. else if is_wide_or_unicode_string(fromdef) then
  631. begin
  632. result:=
  633. (todef=java_jlobject) or
  634. (todef=java_jlstring)
  635. end
  636. else
  637. result:=false;
  638. end;
  639. var
  640. fromelt, toelt: tdef;
  641. realfromdef,
  642. realtodef: tdef;
  643. begin
  644. realfromdef:=maybe_find_real_class_definition(node.left.resultdef,false);
  645. realtodef:=node.right.resultdef;
  646. if realtodef.typ=classrefdef then
  647. realtodef:=tclassrefdef(realtodef).pointeddef;
  648. realtodef:=maybe_find_real_class_definition(realtodef,false);
  649. result:=isrecordconv(realfromdef,realtodef);
  650. if not result then
  651. result:=isstringconv(realfromdef,realtodef);
  652. if not result then
  653. { dynamic arrays can be converted to java.lang.Object and vice versa }
  654. if realtodef=java_jlobject then
  655. { dynamic array to java.lang.Object }
  656. result:=is_dynamic_array(realfromdef)
  657. else if is_dynamic_array(realtodef) then
  658. begin
  659. { <x> to dynamic array: only if possibly valid }
  660. fromelt:=node.left.resultdef;
  661. toelt:=realtodef;
  662. get_most_nested_types(fromelt,toelt);
  663. { final levels must be convertable:
  664. a) from array (dynamic or not) to java.lang.Object or vice versa,
  665. or
  666. b) the same primitive/class type
  667. }
  668. result:=
  669. isrecordconv(fromelt,toelt) or
  670. isstringconv(fromelt,toelt) or
  671. (compare_defs(fromelt,toelt,node.left.nodetype) in [te_exact,te_equal]) or
  672. (((fromelt.typ=objectdef) or
  673. (fromelt.typ=arraydef)) and
  674. ((toelt.typ=objectdef) or
  675. (toelt.typ=arraydef)));
  676. end
  677. else
  678. begin
  679. if (node.right.resultdef.typ<>classrefdef) then
  680. result:=false
  681. else
  682. result:=true;
  683. end;
  684. if result then
  685. if node.nodetype=asn then
  686. begin
  687. if realtodef.typ<>classrefdef then
  688. node.resultdef:=realtodef
  689. else
  690. node.resultdef:=tclassrefdef(realtodef).pointeddef
  691. end
  692. else
  693. node.resultdef:=pasbool8type;
  694. end;
  695. function asis_pass_1(node: tasisnode; const methodname: string): tnode;
  696. var
  697. ps: tsym;
  698. call: tnode;
  699. jlclass: tobjectdef;
  700. begin
  701. result:=nil;
  702. firstpass(node.left);
  703. if not(node.right.nodetype in [typen,loadvmtaddrn]) then
  704. begin
  705. if (node.nodetype=isn) or
  706. not assigned(tasnode(node).call) then
  707. begin
  708. if not is_javaclassref(node.right.resultdef) then
  709. internalerror(2011041920);
  710. firstpass(node.right);
  711. jlclass:=tobjectdef(search_system_type('JLCLASS').typedef);
  712. ps:=search_struct_member(jlclass,methodname);
  713. if not assigned(ps) or
  714. (ps.typ<>procsym) then
  715. internalerror(2011041910);
  716. call:=ccallnode.create(ccallparanode.create(node.left,nil),tprocsym(ps),ps.owner,ctypeconvnode.create_explicit(node.right,jlclass),[]);
  717. node.left:=nil;
  718. node.right:=nil;
  719. firstpass(call);
  720. if codegenerror then
  721. exit;
  722. if node.nodetype=isn then
  723. result:=call
  724. else
  725. begin
  726. tasnode(node).call:=call;
  727. node.expectloc:=call.expectloc;
  728. end;
  729. end;
  730. end
  731. else
  732. begin
  733. node.expectloc:=LOC_REGISTER;
  734. result:=nil;
  735. end;
  736. end;
  737. function asis_generate_code(node: tasisnode; opcode: tasmop): boolean;
  738. var
  739. checkdef: tdef;
  740. begin
  741. if (node.nodetype=asn) and
  742. assigned(tasnode(node).call) then
  743. begin
  744. result:=false;
  745. exit;
  746. end;
  747. result:=true;
  748. secondpass(node.left);
  749. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,node.left.resultdef,node.left.location);
  750. location_freetemp(current_asmdata.CurrAsmList,node.left.location);
  751. { Perform a checkcast instruction, which will raise an exception in case
  752. the actual type does not match/inherit from the expected type.
  753. Object types need the full type name (package+class name), arrays only
  754. the array definition }
  755. if node.nodetype=asn then
  756. checkdef:=node.resultdef
  757. else if node.right.resultdef.typ=classrefdef then
  758. checkdef:=tclassrefdef(node.right.resultdef).pointeddef
  759. else
  760. checkdef:=node.right.resultdef;
  761. { replace special types with their equivalent class type }
  762. if is_wide_or_unicode_string(checkdef) then
  763. checkdef:=java_jlstring;
  764. if checkdef.typ in [objectdef,recorddef] then
  765. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
  766. else
  767. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef,false))));
  768. location_reset(node.location,LOC_REGISTER,OS_ADDR);
  769. node.location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,node.resultdef);
  770. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,node.resultdef,node.location.register);
  771. end;
  772. {*****************************************************************************
  773. TJVMAsNode
  774. *****************************************************************************}
  775. function tjvmasnode.target_specific_typecheck: boolean;
  776. begin
  777. result:=asis_target_specific_typecheck(self);
  778. end;
  779. function tjvmasnode.pass_1: tnode;
  780. begin
  781. result:=asis_pass_1(self,'CAST');
  782. end;
  783. procedure tjvmasnode.pass_generate_code;
  784. begin
  785. if not asis_generate_code(self,a_checkcast) then
  786. inherited;
  787. end;
  788. {*****************************************************************************
  789. TJVMIsNode
  790. *****************************************************************************}
  791. function tjvmisnode.target_specific_typecheck: boolean;
  792. begin
  793. result:=asis_target_specific_typecheck(self);
  794. end;
  795. function tjvmisnode.pass_1: tnode;
  796. begin
  797. result:=asis_pass_1(self,'ISINSTANCE');
  798. end;
  799. procedure tjvmisnode.pass_generate_code;
  800. begin
  801. if not asis_generate_code(self,a_instanceof) then
  802. inherited;
  803. end;
  804. begin
  805. ctypeconvnode:=tjvmtypeconvnode;
  806. casnode:=tjvmasnode;
  807. cisnode:=tjvmisnode;
  808. end.