njvmcnv.pas 40 KB

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