njvmcnv.pas 24 KB

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