njvmcnv.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  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. procedure second_int_to_int;override;
  26. { procedure second_string_to_string;override; }
  27. { procedure second_cstring_to_pchar;override; }
  28. { procedure second_string_to_chararray;override; }
  29. { procedure second_array_to_pointer;override; }
  30. function first_int_to_real: tnode; override;
  31. { procedure second_pointer_to_array;override; }
  32. { procedure second_chararray_to_string;override; }
  33. { procedure second_char_to_string;override; }
  34. procedure second_int_to_real;override;
  35. { procedure second_real_to_real;override; }
  36. { procedure second_cord_to_pointer;override; }
  37. { procedure second_proc_to_procvar;override; }
  38. procedure second_bool_to_int;override;
  39. procedure second_int_to_bool;override;
  40. { procedure second_load_smallset;override; }
  41. { procedure second_ansistring_to_pchar;override; }
  42. { procedure second_pchar_to_string;override; }
  43. { procedure second_class_to_intf;override; }
  44. { procedure second_char_to_char;override; }
  45. protected
  46. function target_specific_explicit_typeconv: tnode; override;
  47. function target_specific_general_typeconv(var res: tnode): boolean; override;
  48. end;
  49. tjvmasnode = class(tcgasnode)
  50. protected
  51. function target_specific_typecheck: boolean;override;
  52. public
  53. function pass_1 : tnode;override;
  54. procedure pass_generate_code; override;
  55. end;
  56. tjvmisnode = class(tisnode)
  57. protected
  58. function target_specific_typecheck: boolean;override;
  59. public
  60. function pass_1 : tnode;override;
  61. procedure pass_generate_code; override;
  62. end;
  63. implementation
  64. uses
  65. verbose,globals,globtype,
  66. symconst,symdef,symsym,symtable,aasmbase,aasmdata,
  67. defutil,defcmp,jvmdef,
  68. cgbase,cgutils,pass_1,pass_2,
  69. nbas,ncon,ncal,nld,nmem,procinfo,
  70. nutils,
  71. cpubase,aasmcpu,
  72. tgobj,hlcgobj,hlcgcpu;
  73. {*****************************************************************************
  74. TypeCheckTypeConv
  75. *****************************************************************************}
  76. function tjvmtypeconvnode.typecheck_dynarray_to_openarray: tnode;
  77. begin
  78. { all arrays are equal in Java }
  79. left.resultdef:=resultdef;
  80. result:=left;
  81. left:=nil;
  82. end;
  83. {*****************************************************************************
  84. FirstTypeConv
  85. *****************************************************************************}
  86. function tjvmtypeconvnode.first_int_to_real: tnode;
  87. begin
  88. if not is_64bitint(left.resultdef) then
  89. if is_signed(left.resultdef) or
  90. (left.resultdef.size<4) then
  91. inserttypeconv(left,s32inttype)
  92. else
  93. inserttypeconv(left,u32inttype);
  94. firstpass(left);
  95. result := nil;
  96. expectloc:=LOC_FPUREGISTER;
  97. end;
  98. {*****************************************************************************
  99. SecondTypeConv
  100. *****************************************************************************}
  101. procedure tjvmtypeconvnode.second_int_to_int;
  102. var
  103. ressize,
  104. leftsize : longint;
  105. begin
  106. { insert range check if not explicit conversion }
  107. if not(nf_explicit in flags) then
  108. hlcg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
  109. { is the result size smaller? when typecasting from void
  110. we always reuse the current location, because there is
  111. nothing that we can load in a register }
  112. ressize:=resultdef.size;
  113. leftsize :=left.resultdef.size;
  114. if ((ressize<>leftsize) or
  115. ((location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  116. (location.reference.arrayreftype<>art_none) and
  117. (is_widechar(left.resultdef)<>is_widechar(resultdef))) or
  118. is_bitpacked_access(left)) and
  119. not is_void(left.resultdef) then
  120. begin
  121. location_copy(location,left.location);
  122. { reuse a loc_reference when the newsize is smaller than
  123. than the original, except
  124. a) for arrays (they use different load instructions for
  125. differently sized data types)
  126. b) when going from 8 to 4 bytes, because these are different
  127. data types
  128. -- note that this is different from other targets, and will
  129. break stuff like passing byte(shortintvar) to a var-parameter;
  130. although that may be "fixed" again because we have to use
  131. copy-in/copy-out to emulate var-parameters anyway... }
  132. if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  133. (location.reference.arrayreftype=art_none) and
  134. (ressize<leftsize) and
  135. (leftsize<=4) then
  136. begin
  137. location.size:=def_cgsize(resultdef);
  138. { no adjustment of the ffset even though Java is big endian,
  139. because the load instruction will remain the same }
  140. end
  141. else
  142. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,false);
  143. end
  144. else
  145. begin
  146. location_copy(location,left.location);
  147. location.size:=def_cgsize(resultdef);
  148. if (ressize < sizeof(aint)) and
  149. (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
  150. (def_cgsize(left.resultdef)<>def_cgsize(resultdef)) then
  151. begin
  152. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  153. location.loc:=LOC_REGISTER;
  154. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register);
  155. end;
  156. end;
  157. end;
  158. procedure tjvmtypeconvnode.second_int_to_real;
  159. var
  160. srcsize, ressize: longint;
  161. procedure convertsignedstackloc;
  162. begin
  163. case srcsize of
  164. 4:
  165. case ressize of
  166. 4:
  167. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2f));
  168. 8:
  169. begin
  170. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2d));
  171. thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
  172. end;
  173. else
  174. internalerror(2011010601);
  175. end;
  176. 8:
  177. case ressize of
  178. 4:
  179. begin
  180. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2f));
  181. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  182. end;
  183. 8:
  184. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2d));
  185. else
  186. internalerror(2011010602);
  187. end;
  188. else
  189. internalerror(2011010603);
  190. end;
  191. end;
  192. var
  193. signeddef : tdef;
  194. l1 : tasmlabel;
  195. begin
  196. srcsize:=left.resultdef.size;
  197. ressize:=resultdef.size;
  198. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  199. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  200. { first always convert as if it's a signed number }
  201. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  202. convertsignedstackloc;
  203. if not is_signed(left.resultdef) then
  204. begin
  205. { if it was unsigned, add high(cardinal)+1/high(qword)+1 in case
  206. the signed interpretation is < 0 }
  207. current_asmdata.getjumplabel(l1);
  208. if srcsize=4 then
  209. signeddef:=s32inttype
  210. else
  211. signeddef:=s64inttype;
  212. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,signeddef,OC_GTE,0,left.location,l1);
  213. if srcsize=4 then
  214. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,4294967296.0)
  215. else
  216. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,18446744073709551616.0);
  217. if ressize=4 then
  218. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_fadd))
  219. else
  220. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dadd));
  221. hlcg.a_label(current_asmdata.CurrAsmList,l1);
  222. end;
  223. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  224. end;
  225. procedure tjvmtypeconvnode.second_bool_to_int;
  226. var
  227. newsize: tcgsize;
  228. oldTrueLabel,oldFalseLabel : tasmlabel;
  229. begin
  230. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  231. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  232. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  233. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  234. secondpass(left);
  235. location_copy(location,left.location);
  236. newsize:=def_cgsize(resultdef);
  237. { byte(bytebool) or word(wordbool) or longint(longbool) must be }
  238. { accepted for var parameters and assignments, and must not }
  239. { change the ordinal value or value location. }
  240. { htypechk.valid_for_assign ensures that such locations with a }
  241. { size<sizeof(register) cannot be LOC_CREGISTER (they otherwise }
  242. { could be in case of a plain assignment), and LOC_REGISTER can }
  243. { never be an assignment target. The remaining LOC_REGISTER/ }
  244. { LOC_CREGISTER locations do have to be sign/zero-extended. }
  245. { -- Note: this does not work for Java and 2/4 byte sized
  246. values, because bytebool/wordbool are signed and
  247. are stored in 4 byte locations -> will result in
  248. "byte" with the value high(cardinal); see remark
  249. in second_int_to_int above regarding consequences }
  250. if not(nf_explicit in flags) or
  251. (location.loc in [LOC_FLAGS,LOC_JUMP]) or
  252. ((newsize<>left.location.size) and
  253. ((left.resultdef.size<>resultdef.size) or
  254. not(left.resultdef.size in [4,8]))
  255. ) then
  256. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  257. else
  258. { may differ in sign, e.g. bytebool -> byte }
  259. location.size:=newsize;
  260. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  261. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  262. end;
  263. procedure tjvmtypeconvnode.second_int_to_bool;
  264. var
  265. hlabel1,hlabel2,oldTrueLabel,oldFalseLabel : tasmlabel;
  266. newsize : tcgsize;
  267. begin
  268. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  269. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  270. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  271. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  272. secondpass(left);
  273. if codegenerror then
  274. exit;
  275. { Explicit typecasts from any ordinal type to a boolean type }
  276. { must not change the ordinal value }
  277. if (nf_explicit in flags) and
  278. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
  279. begin
  280. location_copy(location,left.location);
  281. newsize:=def_cgsize(resultdef);
  282. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  283. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  284. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  285. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  286. else
  287. location.size:=newsize;
  288. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  289. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  290. exit;
  291. end;
  292. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  293. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  294. current_asmdata.getjumplabel(hlabel2);
  295. case left.location.loc of
  296. LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
  297. begin
  298. current_asmdata.getjumplabel(hlabel1);
  299. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location,hlabel1);
  300. end;
  301. LOC_JUMP :
  302. begin
  303. hlabel1:=current_procinfo.CurrFalseLabel;
  304. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  305. end;
  306. else
  307. internalerror(10062);
  308. end;
  309. if not(is_cbool(resultdef)) then
  310. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,1,R_INTREGISTER)
  311. else
  312. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,-1,R_INTREGISTER);
  313. { we jump over the next constant load -> they don't appear on the
  314. stack simulataneously }
  315. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  316. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel2);
  317. hlcg.a_label(current_asmdata.CurrAsmList,hlabel1);
  318. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,0,R_INTREGISTER);
  319. hlcg.a_label(current_asmdata.CurrAsmList,hlabel2);
  320. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  321. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  322. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  323. end;
  324. procedure get_most_nested_types(var fromdef, todef: tdef);
  325. begin
  326. while is_dynamic_array(fromdef) and
  327. is_dynamic_array(todef) do
  328. begin
  329. fromdef:=tarraydef(fromdef).elementdef;
  330. todef:=tarraydef(todef).elementdef;
  331. end;
  332. end;
  333. function tjvmtypeconvnode.target_specific_explicit_typeconv: tnode;
  334. { handle explicit typecast from int to to real or vice versa }
  335. function int_real_explicit_typecast(fdef: tfloatdef; const singlemethod, doublemethod: string): tnode;
  336. var
  337. csym: ttypesym;
  338. psym: tsym;
  339. begin
  340. { use the float/double to raw bits methods to get the bit pattern }
  341. if fdef.floattype=s32real then
  342. begin
  343. csym:=search_system_type('JLFLOAT');
  344. psym:=search_struct_member(tobjectdef(csym.typedef),singlemethod);
  345. end
  346. else
  347. begin
  348. csym:=search_system_type('JLDOUBLE');
  349. psym:=search_struct_member(tobjectdef(csym.typedef),doublemethod);
  350. end;
  351. if not assigned(psym) or
  352. (psym.typ<>procsym) then
  353. internalerror(2011012901);
  354. { call the (static class) method to get the raw bits }
  355. result:=ccallnode.create(ccallparanode.create(left,nil),
  356. tprocsym(psym),psym.owner,
  357. cloadvmtaddrnode.create(ctypenode.create(csym.typedef)),[]);
  358. { convert the result to the result type of this type conversion node }
  359. inserttypeconv_explicit(result,resultdef);
  360. { left is reused }
  361. left:=nil;
  362. end;
  363. var
  364. fromclasscompatible,
  365. toclasscompatible: boolean;
  366. fromdef,
  367. todef: tdef;
  368. begin
  369. result:=nil;
  370. { This routine is only called for explicit typeconversions of same-sized
  371. entities that aren't handled by normal type conversions -> bit pattern
  372. reinterpretations. In the JVM, many of these also need special
  373. handling because of the type safety. }
  374. { don't allow conversions between object-based and non-object-based
  375. types }
  376. fromclasscompatible:=
  377. (left.resultdef.typ=objectdef) or
  378. is_dynamic_array(left.resultdef) or
  379. ((left.resultdef.typ=recorddef) and
  380. (resultdef.typ=objectdef));
  381. toclasscompatible:=
  382. (resultdef.typ=objectdef) or
  383. is_dynamic_array(resultdef) or
  384. ((resultdef.typ=recorddef) and
  385. (left.resultdef.typ=objectdef));
  386. if fromclasscompatible and toclasscompatible then
  387. begin
  388. { we need an as-node to check the validity of the conversion (since
  389. it wasn't handled by another type conversion, we know it can't
  390. have been valid normally)
  391. Exception: (most nested) destination is java.lang.Object, since
  392. everything is compatible with that type }
  393. fromdef:=left.resultdef;
  394. todef:=resultdef;
  395. get_most_nested_types(fromdef,todef);
  396. if not left.resultdef.is_related(resultdef) and
  397. (((fromdef.typ<>objectdef) and
  398. not is_dynamic_array(fromdef)) or
  399. (todef<>java_jlobject)) then
  400. begin
  401. result:=ctypenode.create(resultdef);
  402. if resultdef.typ=objectdef then
  403. result:=cloadvmtaddrnode.create(result);
  404. result:=casnode.create(left,result);
  405. left:=nil;
  406. end;
  407. exit;
  408. end;
  409. { don't allow conversions between different classes of primitive types,
  410. except for a few special cases }
  411. { float to int/enum explicit type conversion: get the bits }
  412. if (left.resultdef.typ=floatdef) and
  413. (is_integer(resultdef) or
  414. (resultdef.typ=enumdef)) then
  415. begin
  416. result:=int_real_explicit_typecast(tfloatdef(left.resultdef),'FLOATTORAWINTBITS','DOUBLETORAWLONGBITS');
  417. exit;
  418. end;
  419. { int to float explicit type conversion: also use the bits }
  420. if (is_integer(left.resultdef) or
  421. (left.resultdef.typ=enumdef)) and
  422. (resultdef.typ=floatdef) then
  423. begin
  424. result:=int_real_explicit_typecast(tfloatdef(resultdef),'INTBITSTOFLOAT','LONGBITSTODOUBLE');
  425. exit;
  426. end;
  427. { nothing special required when going between ordinals and enums }
  428. if (left.resultdef.typ in [orddef,enumdef])=(resultdef.typ in [orddef,enumdef]) then
  429. exit;
  430. { Todo:
  431. * int to set and vice versa
  432. * set to float and vice versa (via int) (maybe)
  433. * regular array of primitive to primitive and vice versa (maybe)
  434. * packed record to primitive and vice versa (maybe)
  435. Definitely not:
  436. * unpacked record to anything and vice versa (no alignment rules
  437. for Java)
  438. }
  439. { anything not explicitly handled is a problem }
  440. CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
  441. end;
  442. function tjvmtypeconvnode.target_specific_general_typeconv(var res: tnode): boolean;
  443. begin
  444. result:=false;
  445. { deal with explicit typecasts between records and classes (for
  446. FpcBaseRecordType) }
  447. if ((left.resultdef.typ=recorddef) and
  448. (resultdef.typ=objectdef) and
  449. left.resultdef.is_related(resultdef)) or
  450. ((left.resultdef.typ=objectdef) and
  451. (resultdef.typ=recorddef) and
  452. resultdef.is_related(left.resultdef)) and
  453. (nf_explicit in flags) then
  454. begin
  455. convtype:=tc_equal;
  456. res:=target_specific_explicit_typeconv;
  457. result:=true;
  458. end;
  459. end;
  460. {*****************************************************************************
  461. AsNode and IsNode common helpers
  462. *****************************************************************************}
  463. function asis_target_specific_typecheck(node: tasisnode): boolean;
  464. var
  465. fromelt, toelt: tdef;
  466. realfromdef,
  467. realtodef: tdef;
  468. begin
  469. realfromdef:=maybe_find_real_class_definition(node.left.resultdef,false);
  470. realtodef:=maybe_find_real_class_definition(node.right.resultdef,false);
  471. if is_record(realtodef) then
  472. result:=
  473. (realfromdef=java_jlobject) or
  474. (realfromdef=java_fpcbaserecordtype)
  475. else if is_record(realfromdef) then
  476. result:=
  477. (realtodef=java_jlobject) or
  478. (realtodef=java_fpcbaserecordtype)
  479. { dynamic arrays can be converted to java.lang.Object and vice versa }
  480. else if realtodef=java_jlobject then
  481. { dynamic array to java.lang.Object }
  482. result:=is_dynamic_array(realfromdef)
  483. else if is_dynamic_array(realtodef) then
  484. begin
  485. { <x> to dynamic array: only if possibly valid }
  486. fromelt:=node.left.resultdef;
  487. toelt:=realtodef;
  488. get_most_nested_types(fromelt,toelt);
  489. { final levels must be convertable:
  490. a) from array (dynamic or not) to java.lang.Object or vice versa,
  491. or
  492. b) the same primitive/class type
  493. }
  494. result:=
  495. (compare_defs(fromelt,toelt,node.left.nodetype) in [te_exact,te_equal]) or
  496. (((fromelt.typ=objectdef) or
  497. (fromelt.typ=arraydef)) and
  498. ((toelt.typ=objectdef) or
  499. (toelt.typ=arraydef)));
  500. end
  501. else
  502. begin
  503. { full class reference support requires using the Java reflection API,
  504. not yet implemented }
  505. if (node.right.nodetype<>loadvmtaddrn) or
  506. (tloadvmtaddrnode(node.right).left.nodetype<>typen) then
  507. internalerror(2011012601);
  508. result:=false;
  509. end;
  510. if result then
  511. if node.nodetype=asn then
  512. begin
  513. if realtodef.typ<>classrefdef then
  514. node.resultdef:=realtodef
  515. else
  516. node.resultdef:=tclassrefdef(realtodef).pointeddef
  517. end
  518. else
  519. node.resultdef:=pasbool8type;
  520. end;
  521. procedure asis_generate_code(node: tasisnode; opcode: tasmop);
  522. var
  523. checkdef: tdef;
  524. begin
  525. secondpass(node.left);
  526. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,node.left.resultdef,node.left.location);
  527. location_freetemp(current_asmdata.CurrAsmList,node.left.location);
  528. { Perform a checkcast instruction, which will raise an exception in case
  529. the actual type does not match/inherit from the expected type.
  530. Object types need the full type name (package+class name), arrays only
  531. the array definition }
  532. if node.nodetype=asn then
  533. checkdef:=node.resultdef
  534. else if node.right.resultdef.typ=classrefdef then
  535. checkdef:=tclassrefdef(node.right.resultdef).pointeddef
  536. else
  537. checkdef:=node.right.resultdef;
  538. if checkdef.typ in [objectdef,recorddef] then
  539. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
  540. else
  541. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef))));
  542. location_reset(node.location,LOC_REGISTER,OS_ADDR);
  543. node.location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,node.resultdef);
  544. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,node.resultdef,node.location.register);
  545. end;
  546. {*****************************************************************************
  547. TJVMAsNode
  548. *****************************************************************************}
  549. function tjvmasnode.target_specific_typecheck: boolean;
  550. begin
  551. result:=asis_target_specific_typecheck(self);
  552. end;
  553. function tjvmasnode.pass_1: tnode;
  554. begin
  555. { call-by-reference does not exist in Java, so it's no problem to
  556. change a memory location to a register }
  557. firstpass(left);
  558. if right.nodetype<>typen then
  559. firstpass(right);
  560. expectloc:=LOC_REGISTER;
  561. result:=nil;
  562. end;
  563. procedure tjvmasnode.pass_generate_code;
  564. begin
  565. asis_generate_code(self,a_checkcast);
  566. end;
  567. {*****************************************************************************
  568. TJVMIsNode
  569. *****************************************************************************}
  570. function tjvmisnode.target_specific_typecheck: boolean;
  571. begin
  572. result:=asis_target_specific_typecheck(self);
  573. end;
  574. function tjvmisnode.pass_1: tnode;
  575. begin
  576. firstpass(left);
  577. if right.nodetype<>typen then
  578. firstpass(right);
  579. expectloc:=LOC_REGISTER;
  580. result:=nil;
  581. end;
  582. procedure tjvmisnode.pass_generate_code;
  583. begin
  584. asis_generate_code(self,a_instanceof);
  585. end;
  586. begin
  587. ctypeconvnode:=tjvmtypeconvnode;
  588. casnode:=tjvmasnode;
  589. cisnode:=tjvmisnode;
  590. end.