njvmcnv.pas 43 KB

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