njvmcnv.pas 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  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. function simplify(forinline: boolean): tnode; override;
  28. procedure second_int_to_int;override;
  29. { procedure second_string_to_string;override; }
  30. { procedure second_cstring_to_pchar;override; }
  31. { procedure second_string_to_chararray;override; }
  32. { procedure second_array_to_pointer;override; }
  33. function first_int_to_real: tnode; override;
  34. { procedure second_pointer_to_array;override; }
  35. { procedure second_chararray_to_string;override; }
  36. { procedure second_char_to_string;override; }
  37. procedure second_int_to_real;override;
  38. { procedure second_real_to_real;override; }
  39. { procedure second_cord_to_pointer;override; }
  40. { procedure second_proc_to_procvar;override; }
  41. procedure second_bool_to_int;override;
  42. procedure second_int_to_bool;override;
  43. { procedure second_load_smallset;override; }
  44. { procedure second_ansistring_to_pchar;override; }
  45. { procedure second_pchar_to_string;override; }
  46. { procedure second_class_to_intf;override; }
  47. { procedure second_char_to_char;override; }
  48. procedure second_elem_to_openarray; override;
  49. function target_specific_explicit_typeconv: boolean; override;
  50. function target_specific_general_typeconv: boolean; override;
  51. protected
  52. function do_target_specific_explicit_typeconv(check_only: boolean; out resnode: tnode): boolean;
  53. end;
  54. tjvmasnode = class(tcgasnode)
  55. protected
  56. { to discern beween "obj as tclassref" and "tclassref(obj)" }
  57. classreftypecast: boolean;
  58. function target_specific_typecheck: boolean;override;
  59. public
  60. function pass_1 : tnode;override;
  61. procedure pass_generate_code; override;
  62. function dogetcopy: tnode; override;
  63. function docompare(p: tnode): boolean; override;
  64. constructor ppuload(t: tnodetype; ppufile: tcompilerppufile); override;
  65. procedure ppuwrite(ppufile: tcompilerppufile); override;
  66. end;
  67. tjvmisnode = class(tisnode)
  68. protected
  69. function target_specific_typecheck: boolean;override;
  70. public
  71. function pass_1 : tnode;override;
  72. procedure pass_generate_code; override;
  73. end;
  74. implementation
  75. uses
  76. verbose,globals,globtype,
  77. symconst,symdef,symsym,symtable,aasmbase,aasmdata,
  78. defutil,defcmp,jvmdef,
  79. cgbase,cgutils,pass_1,pass_2,
  80. nbas,ncon,ncal,nld,nmem,procinfo,
  81. nutils,
  82. cpubase,aasmcpu,
  83. tgobj,hlcgobj,hlcgcpu;
  84. {*****************************************************************************
  85. TypeCheckTypeConv
  86. *****************************************************************************}
  87. function isvalidprocvartypeconv(fromdef, todef: tdef): boolean;
  88. var
  89. tmethoddef: tdef;
  90. function docheck(def1,def2: tdef): boolean;
  91. begin
  92. result:=false;
  93. if def1.typ<>procvardef then
  94. exit;
  95. if tprocvardef(def1).is_addressonly then
  96. result:=
  97. (def2=java_jlobject) or
  98. (def2=voidpointertype)
  99. else
  100. begin
  101. if not assigned(tmethoddef) then
  102. tmethoddef:=search_system_type('TMETHOD').typedef;
  103. result:=
  104. (def2=methodpointertype) or
  105. (def2=tmethoddef);
  106. end;
  107. end;
  108. begin
  109. tmethoddef:=nil;
  110. result:=
  111. docheck(fromdef,todef) or
  112. docheck(todef,fromdef);
  113. end;
  114. function tjvmtypeconvnode.typecheck_dynarray_to_openarray: tnode;
  115. begin
  116. { all arrays are equal in Java }
  117. result:=nil;
  118. convtype:=tc_equal;
  119. end;
  120. function tjvmtypeconvnode.typecheck_string_to_chararray: tnode;
  121. var
  122. newblock: tblocknode;
  123. newstat: tstatementnode;
  124. restemp: ttempcreatenode;
  125. chartype: string;
  126. begin
  127. if (left.nodetype = stringconstn) and
  128. (tstringconstnode(left).cst_type=cst_conststring) then
  129. inserttypeconv(left,cunicodestringtype);
  130. { even constant strings have to be handled via a helper }
  131. if is_widechar(tarraydef(resultdef).elementdef) then
  132. chartype:='widechar'
  133. else
  134. chartype:='char';
  135. newblock:=internalstatements(newstat);
  136. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  137. addstatement(newstat,restemp);
  138. addstatement(newstat,ccallnode.createintern('fpc_'+tstringdef(left.resultdef).stringtypname+
  139. '_to_'+chartype+'array',ccallparanode.create(left,ccallparanode.create(
  140. ctemprefnode.create(restemp),nil))));
  141. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  142. addstatement(newstat,ctemprefnode.create(restemp));
  143. result:=newblock;
  144. left:=nil;
  145. end;
  146. {*****************************************************************************
  147. FirstTypeConv
  148. *****************************************************************************}
  149. function tjvmtypeconvnode.first_int_to_real: tnode;
  150. begin
  151. if not is_64bitint(left.resultdef) then
  152. if is_signed(left.resultdef) or
  153. (left.resultdef.size<4) then
  154. inserttypeconv(left,s32inttype)
  155. else
  156. inserttypeconv(left,u32inttype);
  157. firstpass(left);
  158. result := nil;
  159. expectloc:=LOC_FPUREGISTER;
  160. end;
  161. function tjvmtypeconvnode.pass_1: tnode;
  162. begin
  163. if (nf_explicit in flags) then
  164. begin
  165. do_target_specific_explicit_typeconv(false,result);
  166. if assigned(result) then
  167. exit;
  168. end;
  169. result:=inherited pass_1;
  170. end;
  171. function tjvmtypeconvnode.simplify(forinline: boolean): tnode;
  172. begin
  173. result:=inherited simplify(forinline);
  174. if assigned(result) then
  175. exit;
  176. { string constants passed to java.lang.String must be converted to
  177. widestring }
  178. if (left.nodetype=stringconstn) and
  179. not(tstringconstnode(left).cst_type in [cst_unicodestring,cst_widestring]) and
  180. (maybe_find_real_class_definition(resultdef,false)=java_jlstring) then
  181. inserttypeconv(left,cunicodestringtype);
  182. end;
  183. {*****************************************************************************
  184. SecondTypeConv
  185. *****************************************************************************}
  186. procedure tjvmtypeconvnode.second_int_to_int;
  187. var
  188. ressize,
  189. leftsize : longint;
  190. begin
  191. { insert range check if not explicit conversion }
  192. if not(nf_explicit in flags) then
  193. hlcg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
  194. { is the result size smaller? when typecasting from void
  195. we always reuse the current location, because there is
  196. nothing that we can load in a register }
  197. ressize:=resultdef.size;
  198. leftsize :=left.resultdef.size;
  199. if ((ressize<>leftsize) or
  200. ((location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  201. (location.reference.arrayreftype<>art_none) and
  202. (is_widechar(left.resultdef)<>is_widechar(resultdef))) or
  203. is_bitpacked_access(left)) and
  204. not is_void(left.resultdef) then
  205. begin
  206. location_copy(location,left.location);
  207. { reuse a loc_reference when the newsize is larger than
  208. than the original, because all <= 4 byte loads will result in
  209. a stack slot that occupies 4 bytes.
  210. Except
  211. a) for arrays (they use different load instructions for
  212. differently sized data types) or symbols (idem)
  213. b) when going from 4 to 8 bytes, because these are different
  214. data types
  215. }
  216. if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  217. not assigned(location.reference.symbol) and
  218. (location.reference.arrayreftype=art_none) and
  219. (ressize>leftsize) and
  220. ((ressize=4) or
  221. { this will kill any sign/zero-extension after the load, so
  222. in case the result is 2 bytes (and source is 1 bytes), the
  223. source must be unsigned (-> already zero-extended in memory),
  224. or the destination must be signed (sign-extension in memory
  225. can be loaded onto the stack without problems) }
  226. ((ressize=2) and
  227. (not is_signed(left.resultdef) or
  228. is_signed(resultdef)))) then
  229. begin
  230. location.size:=def_cgsize(resultdef);
  231. { no adjustment of the offset even though Java is big endian,
  232. because the load instruction will remain the same }
  233. end
  234. else
  235. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,false);
  236. end
  237. else
  238. begin
  239. location_copy(location,left.location);
  240. location.size:=def_cgsize(resultdef);
  241. if (ressize < sizeof(aint)) and
  242. (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
  243. (def_cgsize(left.resultdef)<>def_cgsize(resultdef)) then
  244. begin
  245. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  246. location.loc:=LOC_REGISTER;
  247. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register);
  248. end;
  249. end;
  250. end;
  251. procedure tjvmtypeconvnode.second_int_to_real;
  252. var
  253. srcsize, ressize: longint;
  254. procedure convertsignedstackloc;
  255. begin
  256. case srcsize of
  257. 4:
  258. case ressize of
  259. 4:
  260. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2f));
  261. 8:
  262. begin
  263. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2d));
  264. thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
  265. end;
  266. else
  267. internalerror(2011010601);
  268. end;
  269. 8:
  270. case ressize of
  271. 4:
  272. begin
  273. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2f));
  274. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  275. end;
  276. 8:
  277. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2d));
  278. else
  279. internalerror(2011010602);
  280. end;
  281. else
  282. internalerror(2011010603);
  283. end;
  284. end;
  285. var
  286. signeddef : tdef;
  287. l1 : tasmlabel;
  288. begin
  289. srcsize:=left.resultdef.size;
  290. ressize:=resultdef.size;
  291. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  292. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  293. { first always convert as if it's a signed number }
  294. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  295. convertsignedstackloc;
  296. if not is_signed(left.resultdef) then
  297. begin
  298. { if it was unsigned, add high(cardinal)+1/high(qword)+1 in case
  299. the signed interpretation is < 0 }
  300. current_asmdata.getjumplabel(l1);
  301. if srcsize=4 then
  302. signeddef:=s32inttype
  303. else
  304. signeddef:=s64inttype;
  305. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,signeddef,OC_GTE,0,left.location,l1);
  306. if srcsize=4 then
  307. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,4294967296.0)
  308. else
  309. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,18446744073709551616.0);
  310. if ressize=4 then
  311. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_fadd))
  312. else
  313. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dadd));
  314. hlcg.a_label(current_asmdata.CurrAsmList,l1);
  315. end;
  316. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  317. end;
  318. procedure tjvmtypeconvnode.second_bool_to_int;
  319. var
  320. newsize: tcgsize;
  321. oldTrueLabel,oldFalseLabel : tasmlabel;
  322. begin
  323. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  324. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  325. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  326. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  327. secondpass(left);
  328. location_copy(location,left.location);
  329. newsize:=def_cgsize(resultdef);
  330. { byte(bytebool) or word(wordbool) or longint(longbool) must be }
  331. { accepted for var parameters and assignments, and must not }
  332. { change the ordinal value or value location. }
  333. { htypechk.valid_for_assign ensures that such locations with a }
  334. { size<sizeof(register) cannot be LOC_CREGISTER (they otherwise }
  335. { could be in case of a plain assignment), and LOC_REGISTER can }
  336. { never be an assignment target. The remaining LOC_REGISTER/ }
  337. { LOC_CREGISTER locations do have to be sign/zero-extended. }
  338. { -- Note: this does not work for Java and 2/4 byte sized
  339. values, because bytebool/wordbool are signed and
  340. are stored in 4 byte locations -> will result in
  341. "byte" with the value high(cardinal); see remark
  342. in second_int_to_int above regarding consequences }
  343. if not(nf_explicit in flags) or
  344. (location.loc in [LOC_FLAGS,LOC_JUMP]) or
  345. ((newsize<>left.location.size) and
  346. ((left.resultdef.size<>resultdef.size) or
  347. not(left.resultdef.size in [4,8]))
  348. ) then
  349. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  350. else
  351. { may differ in sign, e.g. bytebool -> byte }
  352. location.size:=newsize;
  353. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  354. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  355. end;
  356. procedure tjvmtypeconvnode.second_int_to_bool;
  357. var
  358. hlabel1,hlabel2,oldTrueLabel,oldFalseLabel : tasmlabel;
  359. newsize : tcgsize;
  360. begin
  361. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  362. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  363. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  364. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  365. secondpass(left);
  366. if codegenerror then
  367. exit;
  368. { Explicit typecasts from any ordinal type to a boolean type }
  369. { must not change the ordinal value }
  370. if (nf_explicit in flags) and
  371. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
  372. begin
  373. location_copy(location,left.location);
  374. newsize:=def_cgsize(resultdef);
  375. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  376. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  377. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  378. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  379. else
  380. location.size:=newsize;
  381. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  382. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  383. exit;
  384. end;
  385. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  386. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  387. current_asmdata.getjumplabel(hlabel2);
  388. case left.location.loc of
  389. LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
  390. begin
  391. current_asmdata.getjumplabel(hlabel1);
  392. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location,hlabel1);
  393. end;
  394. LOC_JUMP :
  395. begin
  396. hlabel1:=current_procinfo.CurrFalseLabel;
  397. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  398. end;
  399. else
  400. internalerror(10062);
  401. end;
  402. if not(is_cbool(resultdef)) then
  403. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,1,R_INTREGISTER)
  404. else
  405. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,-1,R_INTREGISTER);
  406. { we jump over the next constant load -> they don't appear on the
  407. stack simulataneously }
  408. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  409. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel2);
  410. hlcg.a_label(current_asmdata.CurrAsmList,hlabel1);
  411. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,0,R_INTREGISTER);
  412. hlcg.a_label(current_asmdata.CurrAsmList,hlabel2);
  413. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  414. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  415. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  416. end;
  417. procedure tjvmtypeconvnode.second_elem_to_openarray;
  418. var
  419. primitivetype: boolean;
  420. opc: tasmop;
  421. mangledname: string;
  422. basereg: tregister;
  423. arrayref: treference;
  424. begin
  425. { create an array with one element of the required type }
  426. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s32inttype,1,R_INTREGISTER);
  427. mangledname:=jvmarrtype(left.resultdef,primitivetype);
  428. if primitivetype then
  429. opc:=a_newarray
  430. else
  431. opc:=a_anewarray;
  432. { doesn't change stack height: one int replaced by one reference }
  433. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opc,current_asmdata.RefAsmSymbol(mangledname)));
  434. { store the data in the newly created array }
  435. basereg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
  436. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,java_jlobject,basereg);
  437. reference_reset_base(arrayref,basereg,0,4);
  438. arrayref.arrayreftype:=art_indexconst;
  439. arrayref.indexoffset:=0;
  440. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location,arrayref);
  441. location_reset_ref(location,LOC_REFERENCE,OS_ADDR,4);
  442. tg.gethltemp(current_asmdata.CurrAsmList,java_jlobject,4,tt_normal,location.reference);
  443. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,java_jlobject,java_jlobject,basereg,location.reference);
  444. end;
  445. procedure get_most_nested_types(var fromdef, todef: tdef);
  446. begin
  447. while is_dynamic_array(fromdef) and
  448. is_dynamic_array(todef) do
  449. begin
  450. fromdef:=tarraydef(fromdef).elementdef;
  451. todef:=tarraydef(todef).elementdef;
  452. end;
  453. fromdef:=maybe_find_real_class_definition(fromdef,false);
  454. todef:=maybe_find_real_class_definition(todef,false);
  455. end;
  456. function tjvmtypeconvnode.do_target_specific_explicit_typeconv(check_only: boolean; out resnode: tnode): boolean;
  457. { handle explicit typecast from int to to real or vice versa }
  458. function int_real_explicit_typecast(fdef: tfloatdef; const singlemethod, doublemethod: string): tnode;
  459. var
  460. csym: ttypesym;
  461. psym: tsym;
  462. begin
  463. { use the float/double to raw bits methods to get the bit pattern }
  464. if fdef.floattype=s32real then
  465. begin
  466. csym:=search_system_type('JLFLOAT');
  467. psym:=search_struct_member(tobjectdef(csym.typedef),singlemethod);
  468. end
  469. else
  470. begin
  471. csym:=search_system_type('JLDOUBLE');
  472. psym:=search_struct_member(tobjectdef(csym.typedef),doublemethod);
  473. end;
  474. if not assigned(psym) or
  475. (psym.typ<>procsym) then
  476. internalerror(2011012901);
  477. { call the (static class) method to get the raw bits }
  478. result:=ccallnode.create(ccallparanode.create(left,nil),
  479. tprocsym(psym),psym.owner,
  480. cloadvmtaddrnode.create(ctypenode.create(csym.typedef)),[]);
  481. { convert the result to the result type of this type conversion node }
  482. inserttypeconv_explicit(result,resultdef);
  483. { left is reused }
  484. left:=nil;
  485. end;
  486. function ord_enum_explicit_typecast(fdef: torddef; todef: tenumdef): tnode;
  487. var
  488. psym: tsym;
  489. begin
  490. { we only create a class for the basedefs }
  491. todef:=todef.getbasedef;
  492. psym:=search_struct_member(todef.classdef,'FPCVALUEOF');
  493. if not assigned(psym) or
  494. (psym.typ<>procsym) then
  495. internalerror(2011062601);
  496. result:=ccallnode.create(ccallparanode.create(left,nil),
  497. tprocsym(psym),psym.owner,
  498. cloadvmtaddrnode.create(ctypenode.create(todef.classdef)),[]);
  499. { convert the result to the result type of this type conversion node }
  500. inserttypeconv_explicit(result,resultdef);
  501. { left is reused }
  502. left:=nil;
  503. end;
  504. function enum_ord_explicit_typecast(fdef: tenumdef; todef: torddef): tnode;
  505. var
  506. psym: tsym;
  507. begin
  508. { we only create a class for the basedef }
  509. fdef:=fdef.getbasedef;
  510. psym:=search_struct_member(fdef.classdef,'FPCORDINAL');
  511. if not assigned(psym) or
  512. (psym.typ<>procsym) then
  513. internalerror(2011062602);
  514. result:=ccallnode.create(nil,tprocsym(psym),psym.owner,left,[]);
  515. { convert the result to the result type of this type conversion node }
  516. inserttypeconv_explicit(result,resultdef);
  517. { left is reused }
  518. left:=nil;
  519. end;
  520. function ptr_no_typecheck_required(fromdef, todef: tdef): boolean;
  521. function check_type_equality(def1,def2: tdef): boolean;
  522. begin
  523. result:=true;
  524. if is_ansistring(def1) and
  525. (def2=java_ansistring) then
  526. exit;
  527. if is_wide_or_unicode_string(def1) and
  528. (def2=java_jlstring) then
  529. exit;
  530. if def1.typ=pointerdef then
  531. begin
  532. if is_shortstring(tpointerdef(def1).pointeddef) and
  533. (def2=java_shortstring) then
  534. exit;
  535. end;
  536. result:=false;
  537. end;
  538. function check_array_type_equality(def1,def2: tdef): boolean;
  539. begin
  540. result:=true;
  541. if is_shortstring(def1) and
  542. (def2=java_shortstring) then
  543. exit;
  544. result:=false;
  545. end;
  546. begin
  547. result:=true;
  548. if (todef=java_jlobject) or
  549. (todef=voidpointertype) then
  550. exit;
  551. if compare_defs(fromdef,todef,nothingn)>=te_equal then
  552. exit;
  553. { trecorddef.is_related() must work for inheritance/method checking,
  554. but do not allow records to be directly typecasted into class/
  555. pointer types (you have to use FpcBaseRecordType(@rec) instead) }
  556. if not is_record(fromdef) and
  557. fromdef.is_related(todef) then
  558. exit;
  559. if check_type_equality(fromdef,todef) then
  560. exit;
  561. if check_type_equality(todef,fromdef) then
  562. exit;
  563. if (fromdef.typ=pointerdef) and
  564. (tpointerdef(fromdef).pointeddef.typ=recorddef) and
  565. (todef=java_fpcbaserecordtype) then
  566. exit;
  567. { all classrefs are currently java.lang.Class at the bytecode level }
  568. if (fromdef.typ=classrefdef) and
  569. (todef.typ=objectdef) and
  570. (todef=search_system_type('JLCLASS').typedef) then
  571. exit;
  572. if (fromdef.typ=classrefdef) and
  573. (todef.typ=classrefdef) and
  574. tclassrefdef(fromdef).pointeddef.is_related(tclassrefdef(todef).pointeddef) then
  575. exit;
  576. { special case: "array of shortstring" to "array of ShortstringClass"
  577. and "array of <record>" to "array of FpcRecordBaseType" (normally
  578. you have to use ShortstringClass(@shortstrvar) etc, but that's not
  579. possible in case of passing arrays to e.g. setlength) }
  580. if is_dynamic_array(left.resultdef) and
  581. is_dynamic_array(resultdef) then
  582. begin
  583. if check_array_type_equality(fromdef,todef) or
  584. check_array_type_equality(todef,fromdef) then
  585. exit;
  586. if is_record(fromdef) and
  587. (todef=java_fpcbaserecordtype) then
  588. exit;
  589. end;
  590. result:=false;
  591. end;
  592. var
  593. fromclasscompatible,
  594. toclasscompatible,
  595. procvarconv: boolean;
  596. fromdef,
  597. todef: tdef;
  598. fromarrtype,
  599. toarrtype: char;
  600. begin
  601. resnode:=nil;
  602. if not(convtype in [tc_equal,tc_int_2_int,tc_int_2_bool,tc_bool_2_int]) then
  603. begin
  604. result:=false;
  605. exit
  606. end;
  607. { This routine is only called for explicit typeconversions of same-sized
  608. entities that aren't handled by normal type conversions -> bit pattern
  609. reinterpretations. In the JVM, many of these also need special
  610. handling because of the type safety. }
  611. { don't allow conversions between object-based and non-object-based
  612. types }
  613. procvarconv:=isvalidprocvartypeconv(left.resultdef,resultdef);
  614. fromclasscompatible:=
  615. (left.resultdef.typ=formaldef) or
  616. (left.resultdef.typ=pointerdef) or
  617. (left.resultdef.typ=objectdef) or
  618. is_dynamic_array(left.resultdef) or
  619. ((left.resultdef.typ in [stringdef,classrefdef]) and
  620. not is_shortstring(left.resultdef)) or
  621. (left.resultdef.typ=enumdef) or
  622. procvarconv;
  623. toclasscompatible:=
  624. (resultdef.typ=pointerdef) or
  625. (resultdef.typ=objectdef) or
  626. is_dynamic_array(resultdef) or
  627. ((resultdef.typ in [stringdef,classrefdef]) and
  628. not is_shortstring(resultdef)) or
  629. (resultdef.typ=enumdef) or
  630. procvarconv;
  631. { typescasts from void (the result of untyped_ptr^) to an implicit
  632. pointertype (record, array, ...) also needs a typecheck }
  633. if is_void(left.resultdef) and
  634. jvmimplicitpointertype(resultdef) then
  635. begin
  636. fromclasscompatible:=true;
  637. toclasscompatible:=true;
  638. end;
  639. if fromclasscompatible and toclasscompatible then
  640. begin
  641. { we need an as-node to check the validity of the conversion (since
  642. it wasn't handled by another type conversion, we know it can't
  643. have been valid normally)
  644. Exceptions: (most nested) destination is
  645. * java.lang.Object, since everything is compatible with that type
  646. * related to source
  647. * a primitive that are represented by the same type in Java
  648. (e.g., byte and shortint) }
  649. { in case of arrays, check the compatibility of the innermost types }
  650. fromdef:=left.resultdef;
  651. todef:=resultdef;
  652. get_most_nested_types(fromdef,todef);
  653. { in case of enums, get the equivalent class definitions }
  654. if (fromdef.typ=enumdef) then
  655. fromdef:=tenumdef(fromdef).getbasedef;
  656. if (todef.typ=enumdef) then
  657. todef:=tenumdef(todef).getbasedef;
  658. fromarrtype:=jvmarrtype_setlength(fromdef);
  659. toarrtype:=jvmarrtype_setlength(todef);
  660. if not ptr_no_typecheck_required(fromdef,todef) then
  661. begin
  662. if (fromarrtype in ['A','R','T']) or
  663. (fromarrtype<>toarrtype) then
  664. begin
  665. if not check_only and
  666. not assignment_side then
  667. begin
  668. resnode:=ctypenode.create(resultdef);
  669. if resultdef.typ=objectdef then
  670. resnode:=cloadvmtaddrnode.create(resnode);
  671. resnode:=casnode.create_internal(left,resnode);
  672. if resultdef.typ=classrefdef then
  673. tjvmasnode(resnode).classreftypecast:=true;
  674. left:=nil;
  675. end
  676. end
  677. { typecasting from a child to a parent type on the assignment side
  678. will (rightly) mess up the type safety verification of the JVM }
  679. else if assignment_side then
  680. CGMessage(type_e_no_managed_assign_generic_typecast);
  681. end;
  682. result:=true;
  683. exit;
  684. end;
  685. { a formaldef can be converted to anything, but not on the assignment
  686. side }
  687. if (left.resultdef.typ=formaldef) and
  688. not assignment_side then
  689. exit;
  690. { don't allow conversions between different classes of primitive types,
  691. except for a few special cases }
  692. { float to int/enum explicit type conversion: get the bits }
  693. if (left.resultdef.typ=floatdef) and
  694. (is_integer(resultdef) or
  695. (resultdef.typ=enumdef)) then
  696. begin
  697. if not check_only then
  698. resnode:=int_real_explicit_typecast(tfloatdef(left.resultdef),'FLOATTORAWINTBITS','DOUBLETORAWLONGBITS');
  699. result:=true;
  700. exit;
  701. end;
  702. { int to float explicit type conversion: also use the bits }
  703. if (is_integer(left.resultdef) or
  704. (left.resultdef.typ=enumdef)) and
  705. (resultdef.typ=floatdef) then
  706. begin
  707. if not check_only then
  708. begin
  709. if (left.resultdef.typ=enumdef) then
  710. inserttypeconv_explicit(left,s32inttype);
  711. resnode:=int_real_explicit_typecast(tfloatdef(resultdef),'INTBITSTOFLOAT','LONGBITSTODOUBLE');
  712. end;
  713. result:=true;
  714. exit;
  715. end;
  716. { enums }
  717. if (left.resultdef.typ=enumdef) or
  718. (resultdef.typ=enumdef) then
  719. begin
  720. { both enum? }
  721. if (resultdef.typ=left.resultdef.typ) then
  722. begin
  723. { same base type -> nothing special }
  724. fromdef:=tenumdef(left.resultdef).getbasedef;
  725. todef:=tenumdef(resultdef).getbasedef;
  726. if fromdef=todef then
  727. begin
  728. result:=false;
  729. exit;
  730. end;
  731. { convert via ordinal intermediate }
  732. if not check_only then
  733. begin;
  734. inserttypeconv_explicit(left,s32inttype);
  735. inserttypeconv_explicit(left,resultdef);
  736. resnode:=left;
  737. left:=nil
  738. end;
  739. result:=true;
  740. exit;
  741. end;
  742. { enum to orddef & vice versa }
  743. if left.resultdef.typ=orddef then
  744. begin
  745. if not check_only then
  746. resnode:=ord_enum_explicit_typecast(torddef(left.resultdef),tenumdef(resultdef));
  747. result:=true;
  748. exit;
  749. end
  750. else if resultdef.typ=orddef then
  751. begin
  752. if not check_only then
  753. resnode:=enum_ord_explicit_typecast(tenumdef(left.resultdef),torddef(resultdef));
  754. result:=true;
  755. exit;
  756. end
  757. end;
  758. {$ifndef nounsupported}
  759. if (left.resultdef.typ in [orddef,enumdef,setdef]) and
  760. (resultdef.typ in [orddef,enumdef,setdef]) then
  761. begin
  762. result:=false;
  763. exit;
  764. end;
  765. { non-literal type conversions }
  766. if convtype in
  767. [tc_char_2_string,
  768. tc_char_2_chararray,
  769. tc_string_2_string,
  770. tc_string_2_chararray,
  771. tc_real_2_real,
  772. tc_proc_2_procvar,
  773. tc_arrayconstructor_2_set,
  774. tc_set_to_set,
  775. tc_class_2_intf,
  776. tc_array_2_dynarray] then
  777. begin
  778. result:=false;
  779. exit;
  780. end;
  781. {$endif}
  782. { Todo:
  783. * int to set and vice versa
  784. * set to float and vice versa (via int) (maybe)
  785. * regular array of primitive to primitive and vice versa (maybe)
  786. * packed record to primitive and vice versa (maybe)
  787. Definitely not:
  788. * unpacked record to anything and vice versa (no alignment rules
  789. for Java)
  790. }
  791. { anything not explicitly handled is a problem }
  792. result:=true;
  793. CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
  794. end;
  795. function tjvmtypeconvnode.target_specific_explicit_typeconv: boolean;
  796. var
  797. dummyres: tnode;
  798. begin
  799. result:=do_target_specific_explicit_typeconv(true,dummyres);
  800. end;
  801. function tjvmtypeconvnode.target_specific_general_typeconv: boolean;
  802. begin
  803. result:=false;
  804. { on the JVM platform, enums can always be converted to class instances,
  805. because enums /are/ class instances there. To prevent the
  806. typechecking/conversion code from assuming it can treat it like any
  807. ordinal constant, firstpass() it so that the ordinal constant gets
  808. replaced with a load of a staticvarsym. This is not done in
  809. pass_typecheck, because that would prevent many optimizations }
  810. if (left.nodetype=ordconstn) and
  811. (left.resultdef.typ=enumdef) and
  812. (resultdef.typ=objectdef) then
  813. firstpass(left);
  814. {$ifndef nounsupported}
  815. { generated in nmem; replace voidpointertype with java_jlobject }
  816. if nf_load_procvar in flags then
  817. begin
  818. self.totypedef:=java_jlobject;
  819. resultdef:=java_jlobject;
  820. end;
  821. if isvalidprocvartypeconv(left.resultdef,resultdef) then
  822. begin
  823. convtype:=tc_equal;
  824. result:=true;
  825. exit;
  826. end;
  827. {$endif}
  828. end;
  829. {*****************************************************************************
  830. AsNode and IsNode common helpers
  831. *****************************************************************************}
  832. function asis_target_specific_typecheck(node: tasisnode): boolean;
  833. var
  834. realtodef: tdef;
  835. begin
  836. if not(nf_internal in node.flags) then
  837. begin
  838. { handle using normal code }
  839. result:=false;
  840. exit;
  841. end;
  842. result:=true;
  843. { these are converted type conversion nodes, to insert the checkcast
  844. operations }
  845. realtodef:=node.right.resultdef;
  846. if (realtodef.typ=classrefdef) and
  847. ((node.nodetype<>asn) or
  848. not tjvmasnode(node).classreftypecast) then
  849. realtodef:=tclassrefdef(realtodef).pointeddef;
  850. realtodef:=maybe_find_real_class_definition(realtodef,false);
  851. if result then
  852. if node.nodetype=asn then
  853. node.resultdef:=realtodef
  854. else
  855. node.resultdef:=pasbool8type;
  856. end;
  857. function asis_pass_1(node: tasisnode; const methodname: string): tnode;
  858. var
  859. ps: tsym;
  860. call: tnode;
  861. jlclass: tobjectdef;
  862. begin
  863. result:=nil;
  864. firstpass(node.left);
  865. if not(node.right.nodetype in [typen,loadvmtaddrn]) then
  866. begin
  867. if (node.nodetype=isn) or
  868. not assigned(tasnode(node).call) then
  869. begin
  870. if not is_javaclassref(node.right.resultdef) then
  871. internalerror(2011041920);
  872. firstpass(node.right);
  873. jlclass:=tobjectdef(search_system_type('JLCLASS').typedef);
  874. ps:=search_struct_member(jlclass,methodname);
  875. if not assigned(ps) or
  876. (ps.typ<>procsym) then
  877. internalerror(2011041910);
  878. call:=ccallnode.create(ccallparanode.create(node.left,nil),tprocsym(ps),ps.owner,ctypeconvnode.create_explicit(node.right,jlclass),[]);
  879. node.left:=nil;
  880. node.right:=nil;
  881. firstpass(call);
  882. if codegenerror then
  883. exit;
  884. if node.nodetype=isn then
  885. result:=call
  886. else
  887. begin
  888. tasnode(node).call:=call;
  889. node.expectloc:=call.expectloc;
  890. end;
  891. end;
  892. end
  893. else
  894. begin
  895. node.expectloc:=LOC_REGISTER;
  896. result:=nil;
  897. end;
  898. end;
  899. function asis_generate_code(node: tasisnode; opcode: tasmop): boolean;
  900. var
  901. checkdef: tdef;
  902. begin
  903. if (node.nodetype=asn) and
  904. assigned(tasnode(node).call) then
  905. begin
  906. result:=false;
  907. exit;
  908. end;
  909. result:=true;
  910. secondpass(node.left);
  911. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,node.left.resultdef,node.left.location);
  912. location_freetemp(current_asmdata.CurrAsmList,node.left.location);
  913. { Perform a checkcast instruction, which will raise an exception in case
  914. the actual type does not match/inherit from the expected type.
  915. Object types need the full type name (package+class name), arrays only
  916. the array definition }
  917. if node.nodetype=asn then
  918. checkdef:=node.resultdef
  919. else if node.right.resultdef.typ=classrefdef then
  920. checkdef:=tclassrefdef(node.right.resultdef).pointeddef
  921. else
  922. checkdef:=node.right.resultdef;
  923. { replace special types with their equivalent class type }
  924. if checkdef=voidpointertype then
  925. checkdef:=java_jlobject
  926. else if checkdef.typ=pointerdef then
  927. checkdef:=tpointerdef(checkdef).pointeddef
  928. else if checkdef.typ=enumdef then
  929. checkdef:=tenumdef(checkdef).classdef;
  930. {$ifndef nounsupported}
  931. if checkdef.typ=procvardef then
  932. checkdef:=java_jlobject
  933. else
  934. {$endif}
  935. if is_wide_or_unicode_string(checkdef) then
  936. checkdef:=java_jlstring
  937. else if is_ansistring(checkdef) then
  938. checkdef:=java_ansistring
  939. else if is_shortstring(checkdef) then
  940. checkdef:=java_shortstring;
  941. if checkdef.typ in [objectdef,recorddef] then
  942. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
  943. else if checkdef.typ=classrefdef then
  944. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol('java/lang/Class')))
  945. else
  946. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef,false))));
  947. location_reset(node.location,LOC_REGISTER,OS_ADDR);
  948. node.location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,node.resultdef);
  949. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,node.resultdef,node.location.register);
  950. end;
  951. {*****************************************************************************
  952. TJVMAsNode
  953. *****************************************************************************}
  954. function tjvmasnode.target_specific_typecheck: boolean;
  955. begin
  956. result:=asis_target_specific_typecheck(self);
  957. end;
  958. function tjvmasnode.pass_1: tnode;
  959. begin
  960. result:=asis_pass_1(self,'CAST');
  961. end;
  962. procedure tjvmasnode.pass_generate_code;
  963. begin
  964. if not asis_generate_code(self,a_checkcast) then
  965. inherited;
  966. end;
  967. function tjvmasnode.dogetcopy: tnode;
  968. begin
  969. result:=inherited dogetcopy;
  970. tjvmasnode(result).classreftypecast:=classreftypecast;
  971. end;
  972. function tjvmasnode.docompare(p: tnode): boolean;
  973. begin
  974. result:=
  975. inherited docompare(p) and
  976. (tjvmasnode(p).classreftypecast=classreftypecast);
  977. end;
  978. constructor tjvmasnode.ppuload(t: tnodetype; ppufile: tcompilerppufile);
  979. begin
  980. inherited;
  981. classreftypecast:=boolean(ppufile.getbyte);
  982. end;
  983. procedure tjvmasnode.ppuwrite(ppufile: tcompilerppufile);
  984. begin
  985. inherited ppuwrite(ppufile);
  986. ppufile.putbyte(byte(classreftypecast));
  987. end;
  988. {*****************************************************************************
  989. TJVMIsNode
  990. *****************************************************************************}
  991. function tjvmisnode.target_specific_typecheck: boolean;
  992. begin
  993. result:=asis_target_specific_typecheck(self);
  994. end;
  995. function tjvmisnode.pass_1: tnode;
  996. begin
  997. result:=asis_pass_1(self,'ISINSTANCE');
  998. end;
  999. procedure tjvmisnode.pass_generate_code;
  1000. begin
  1001. if not asis_generate_code(self,a_instanceof) then
  1002. inherited;
  1003. end;
  1004. begin
  1005. ctypeconvnode:=tjvmtypeconvnode;
  1006. casnode:=tjvmasnode;
  1007. cisnode:=tjvmisnode;
  1008. end.