njvmcnv.pas 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  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. { This routine is only called for explicit typeconversions of same-sized
  603. entities that aren't handled by normal type conversions -> bit pattern
  604. reinterpretations. In the JVM, many of these also need special
  605. handling because of the type safety. }
  606. { don't allow conversions between object-based and non-object-based
  607. types }
  608. procvarconv:=isvalidprocvartypeconv(left.resultdef,resultdef);
  609. fromclasscompatible:=
  610. (left.resultdef.typ=formaldef) or
  611. (left.resultdef.typ=pointerdef) or
  612. (left.resultdef.typ=objectdef) or
  613. is_dynamic_array(left.resultdef) or
  614. ((left.resultdef.typ in [stringdef,classrefdef]) and
  615. not is_shortstring(left.resultdef)) or
  616. (left.resultdef.typ=enumdef) or
  617. procvarconv;
  618. toclasscompatible:=
  619. (resultdef.typ=pointerdef) or
  620. (resultdef.typ=objectdef) or
  621. is_dynamic_array(resultdef) or
  622. ((resultdef.typ in [stringdef,classrefdef]) and
  623. not is_shortstring(resultdef)) or
  624. (resultdef.typ=enumdef) or
  625. procvarconv;
  626. { typescasts from void (the result of untyped_ptr^) to an implicit
  627. pointertype (record, array, ...) also needs a typecheck }
  628. if is_void(left.resultdef) and
  629. jvmimplicitpointertype(resultdef) then
  630. begin
  631. fromclasscompatible:=true;
  632. toclasscompatible:=true;
  633. end;
  634. if fromclasscompatible and toclasscompatible then
  635. begin
  636. { we need an as-node to check the validity of the conversion (since
  637. it wasn't handled by another type conversion, we know it can't
  638. have been valid normally)
  639. Exceptions: (most nested) destination is
  640. * java.lang.Object, since everything is compatible with that type
  641. * related to source
  642. * a primitive that are represented by the same type in Java
  643. (e.g., byte and shortint) }
  644. { in case of arrays, check the compatibility of the innermost types }
  645. fromdef:=left.resultdef;
  646. todef:=resultdef;
  647. get_most_nested_types(fromdef,todef);
  648. { in case of enums, get the equivalent class definitions }
  649. if (fromdef.typ=enumdef) then
  650. fromdef:=tenumdef(fromdef).getbasedef;
  651. if (todef.typ=enumdef) then
  652. todef:=tenumdef(todef).getbasedef;
  653. fromarrtype:=jvmarrtype_setlength(fromdef);
  654. toarrtype:=jvmarrtype_setlength(todef);
  655. if not ptr_no_typecheck_required(fromdef,todef) then
  656. begin
  657. if (fromarrtype in ['A','R','T']) or
  658. (fromarrtype<>toarrtype) then
  659. begin
  660. if not check_only and
  661. not assignment_side then
  662. begin
  663. resnode:=ctypenode.create(resultdef);
  664. if resultdef.typ=objectdef then
  665. resnode:=cloadvmtaddrnode.create(resnode);
  666. resnode:=casnode.create_internal(left,resnode);
  667. if resultdef.typ=classrefdef then
  668. tjvmasnode(resnode).classreftypecast:=true;
  669. left:=nil;
  670. end
  671. end
  672. { typecasting from a child to a parent type on the assignment side
  673. will (rightly) mess up the type safety verification of the JVM }
  674. else if assignment_side then
  675. CGMessage(type_e_no_managed_assign_generic_typecast);
  676. end;
  677. result:=true;
  678. exit;
  679. end;
  680. { a formaldef can be converted to anything, but not on the assignment
  681. side }
  682. if (left.resultdef.typ=formaldef) and
  683. not assignment_side then
  684. exit;
  685. { don't allow conversions between different classes of primitive types,
  686. except for a few special cases }
  687. { float to int/enum explicit type conversion: get the bits }
  688. if (convtype<>tc_int_2_real) and
  689. (left.resultdef.typ=floatdef) and
  690. (is_integer(resultdef) or
  691. (resultdef.typ=enumdef)) then
  692. begin
  693. if not check_only then
  694. resnode:=int_real_explicit_typecast(tfloatdef(left.resultdef),'FLOATTORAWINTBITS','DOUBLETORAWLONGBITS');
  695. result:=true;
  696. exit;
  697. end;
  698. { int to float explicit type conversion: also use the bits }
  699. if (is_integer(left.resultdef) or
  700. (left.resultdef.typ=enumdef)) and
  701. (resultdef.typ=floatdef) then
  702. begin
  703. if (convtype<>tc_int_2_real) then
  704. begin
  705. if (left.resultdef.typ=enumdef) then
  706. inserttypeconv_explicit(left,s32inttype);
  707. if not check_only then
  708. resnode:=int_real_explicit_typecast(tfloatdef(resultdef),'INTBITSTOFLOAT','LONGBITSTODOUBLE');
  709. result:=true;
  710. end
  711. else
  712. result:=false;
  713. exit;
  714. end;
  715. { enums }
  716. if (left.resultdef.typ=enumdef) or
  717. (resultdef.typ=enumdef) then
  718. begin
  719. { both enum? }
  720. if (resultdef.typ=left.resultdef.typ) then
  721. begin
  722. { same base type -> nothing special }
  723. fromdef:=tenumdef(left.resultdef).getbasedef;
  724. todef:=tenumdef(resultdef).getbasedef;
  725. if fromdef=todef then
  726. begin
  727. result:=false;
  728. exit;
  729. end;
  730. { convert via ordinal intermediate }
  731. if not check_only then
  732. begin;
  733. inserttypeconv_explicit(left,s32inttype);
  734. inserttypeconv_explicit(left,resultdef);
  735. resnode:=left;
  736. left:=nil
  737. end;
  738. result:=true;
  739. exit;
  740. end;
  741. { enum to orddef & vice versa }
  742. if left.resultdef.typ=orddef then
  743. begin
  744. if not check_only then
  745. resnode:=ord_enum_explicit_typecast(torddef(left.resultdef),tenumdef(resultdef));
  746. result:=true;
  747. exit;
  748. end
  749. else if resultdef.typ=orddef then
  750. begin
  751. if not check_only then
  752. resnode:=enum_ord_explicit_typecast(tenumdef(left.resultdef),torddef(resultdef));
  753. result:=true;
  754. exit;
  755. end
  756. end;
  757. {$ifndef nounsupported}
  758. if (left.resultdef.typ in [orddef,enumdef,setdef]) and
  759. (resultdef.typ in [orddef,enumdef,setdef]) then
  760. begin
  761. result:=false;
  762. exit;
  763. end;
  764. { non-literal type conversions }
  765. if convtype in
  766. [tc_char_2_string,
  767. tc_char_2_chararray,
  768. tc_string_2_string,
  769. tc_string_2_chararray,
  770. tc_real_2_real,
  771. tc_proc_2_procvar,
  772. tc_arrayconstructor_2_set,
  773. tc_set_to_set,
  774. tc_class_2_intf,
  775. tc_array_2_dynarray] then
  776. begin
  777. result:=false;
  778. exit;
  779. end;
  780. {$endif}
  781. { Todo:
  782. * int to set and vice versa
  783. * set to float and vice versa (via int) (maybe)
  784. * regular array of primitive to primitive and vice versa (maybe)
  785. * packed record to primitive and vice versa (maybe)
  786. Definitely not:
  787. * unpacked record to anything and vice versa (no alignment rules
  788. for Java)
  789. }
  790. { anything not explicitly handled is a problem }
  791. result:=true;
  792. CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
  793. end;
  794. function tjvmtypeconvnode.target_specific_explicit_typeconv: boolean;
  795. var
  796. dummyres: tnode;
  797. begin
  798. result:=do_target_specific_explicit_typeconv(true,dummyres);
  799. end;
  800. function tjvmtypeconvnode.target_specific_general_typeconv: boolean;
  801. begin
  802. result:=false;
  803. { on the JVM platform, enums can always be converted to class instances,
  804. because enums /are/ class instances there. To prevent the
  805. typechecking/conversion code from assuming it can treat it like any
  806. ordinal constant, firstpass() it so that the ordinal constant gets
  807. replaced with a load of a staticvarsym. This is not done in
  808. pass_typecheck, because that would prevent many optimizations }
  809. if (left.nodetype=ordconstn) and
  810. (left.resultdef.typ=enumdef) and
  811. (resultdef.typ=objectdef) then
  812. firstpass(left);
  813. {$ifndef nounsupported}
  814. { generated in nmem; replace voidpointertype with java_jlobject }
  815. if nf_load_procvar in flags then
  816. begin
  817. self.totypedef:=java_jlobject;
  818. resultdef:=java_jlobject;
  819. end;
  820. if isvalidprocvartypeconv(left.resultdef,resultdef) then
  821. begin
  822. convtype:=tc_equal;
  823. result:=true;
  824. exit;
  825. end;
  826. {$endif}
  827. end;
  828. {*****************************************************************************
  829. AsNode and IsNode common helpers
  830. *****************************************************************************}
  831. function asis_target_specific_typecheck(node: tasisnode): boolean;
  832. var
  833. realtodef: tdef;
  834. begin
  835. if not(nf_internal in node.flags) then
  836. begin
  837. { handle using normal code }
  838. result:=false;
  839. exit;
  840. end;
  841. result:=true;
  842. { these are converted type conversion nodes, to insert the checkcast
  843. operations }
  844. realtodef:=node.right.resultdef;
  845. if (realtodef.typ=classrefdef) and
  846. ((node.nodetype<>asn) or
  847. not tjvmasnode(node).classreftypecast) then
  848. realtodef:=tclassrefdef(realtodef).pointeddef;
  849. realtodef:=maybe_find_real_class_definition(realtodef,false);
  850. if result then
  851. if node.nodetype=asn then
  852. node.resultdef:=realtodef
  853. else
  854. node.resultdef:=pasbool8type;
  855. end;
  856. function asis_pass_1(node: tasisnode; const methodname: string): tnode;
  857. var
  858. ps: tsym;
  859. call: tnode;
  860. jlclass: tobjectdef;
  861. begin
  862. result:=nil;
  863. firstpass(node.left);
  864. if not(node.right.nodetype in [typen,loadvmtaddrn]) then
  865. begin
  866. if (node.nodetype=isn) or
  867. not assigned(tasnode(node).call) then
  868. begin
  869. if not is_javaclassref(node.right.resultdef) then
  870. internalerror(2011041920);
  871. firstpass(node.right);
  872. jlclass:=tobjectdef(search_system_type('JLCLASS').typedef);
  873. ps:=search_struct_member(jlclass,methodname);
  874. if not assigned(ps) or
  875. (ps.typ<>procsym) then
  876. internalerror(2011041910);
  877. call:=ccallnode.create(ccallparanode.create(node.left,nil),tprocsym(ps),ps.owner,ctypeconvnode.create_explicit(node.right,jlclass),[]);
  878. node.left:=nil;
  879. node.right:=nil;
  880. firstpass(call);
  881. if codegenerror then
  882. exit;
  883. if node.nodetype=isn then
  884. result:=call
  885. else
  886. begin
  887. tasnode(node).call:=call;
  888. node.expectloc:=call.expectloc;
  889. end;
  890. end;
  891. end
  892. else
  893. begin
  894. node.expectloc:=LOC_REGISTER;
  895. result:=nil;
  896. end;
  897. end;
  898. function asis_generate_code(node: tasisnode; opcode: tasmop): boolean;
  899. var
  900. checkdef: tdef;
  901. begin
  902. if (node.nodetype=asn) and
  903. assigned(tasnode(node).call) then
  904. begin
  905. result:=false;
  906. exit;
  907. end;
  908. result:=true;
  909. secondpass(node.left);
  910. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,node.left.resultdef,node.left.location);
  911. location_freetemp(current_asmdata.CurrAsmList,node.left.location);
  912. { Perform a checkcast instruction, which will raise an exception in case
  913. the actual type does not match/inherit from the expected type.
  914. Object types need the full type name (package+class name), arrays only
  915. the array definition }
  916. if node.nodetype=asn then
  917. checkdef:=node.resultdef
  918. else if node.right.resultdef.typ=classrefdef then
  919. checkdef:=tclassrefdef(node.right.resultdef).pointeddef
  920. else
  921. checkdef:=node.right.resultdef;
  922. { replace special types with their equivalent class type }
  923. if checkdef=voidpointertype then
  924. checkdef:=java_jlobject
  925. else if checkdef.typ=pointerdef then
  926. checkdef:=tpointerdef(checkdef).pointeddef
  927. else if checkdef.typ=enumdef then
  928. checkdef:=tenumdef(checkdef).classdef;
  929. {$ifndef nounsupported}
  930. if checkdef.typ=procvardef then
  931. checkdef:=java_jlobject
  932. else
  933. {$endif}
  934. if is_wide_or_unicode_string(checkdef) then
  935. checkdef:=java_jlstring
  936. else if is_ansistring(checkdef) then
  937. checkdef:=java_ansistring
  938. else if is_shortstring(checkdef) then
  939. checkdef:=java_shortstring;
  940. if checkdef.typ in [objectdef,recorddef] then
  941. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
  942. else if checkdef.typ=classrefdef then
  943. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol('java/lang/Class')))
  944. else
  945. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef,false))));
  946. location_reset(node.location,LOC_REGISTER,OS_ADDR);
  947. node.location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,node.resultdef);
  948. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,node.resultdef,node.location.register);
  949. end;
  950. {*****************************************************************************
  951. TJVMAsNode
  952. *****************************************************************************}
  953. function tjvmasnode.target_specific_typecheck: boolean;
  954. begin
  955. result:=asis_target_specific_typecheck(self);
  956. end;
  957. function tjvmasnode.pass_1: tnode;
  958. begin
  959. result:=asis_pass_1(self,'CAST');
  960. end;
  961. procedure tjvmasnode.pass_generate_code;
  962. begin
  963. if not asis_generate_code(self,a_checkcast) then
  964. inherited;
  965. end;
  966. function tjvmasnode.dogetcopy: tnode;
  967. begin
  968. result:=inherited dogetcopy;
  969. tjvmasnode(result).classreftypecast:=classreftypecast;
  970. end;
  971. function tjvmasnode.docompare(p: tnode): boolean;
  972. begin
  973. result:=
  974. inherited docompare(p) and
  975. (tjvmasnode(p).classreftypecast=classreftypecast);
  976. end;
  977. constructor tjvmasnode.ppuload(t: tnodetype; ppufile: tcompilerppufile);
  978. begin
  979. inherited;
  980. classreftypecast:=boolean(ppufile.getbyte);
  981. end;
  982. procedure tjvmasnode.ppuwrite(ppufile: tcompilerppufile);
  983. begin
  984. inherited ppuwrite(ppufile);
  985. ppufile.putbyte(byte(classreftypecast));
  986. end;
  987. {*****************************************************************************
  988. TJVMIsNode
  989. *****************************************************************************}
  990. function tjvmisnode.target_specific_typecheck: boolean;
  991. begin
  992. result:=asis_target_specific_typecheck(self);
  993. end;
  994. function tjvmisnode.pass_1: tnode;
  995. begin
  996. result:=asis_pass_1(self,'ISINSTANCE');
  997. end;
  998. procedure tjvmisnode.pass_generate_code;
  999. begin
  1000. if not asis_generate_code(self,a_instanceof) then
  1001. inherited;
  1002. end;
  1003. begin
  1004. ctypeconvnode:=tjvmtypeconvnode;
  1005. casnode:=tjvmasnode;
  1006. cisnode:=tjvmisnode;
  1007. end.