njvmcnv.pas 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534
  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 typecheck_proc_to_procvar: tnode; override;
  28. function pass_1: tnode; override;
  29. function simplify(forinline: boolean): tnode; override;
  30. function first_set_to_set : tnode;override;
  31. function first_nil_to_methodprocvar: tnode; override;
  32. function first_proc_to_procvar: tnode; override;
  33. procedure second_int_to_int;override;
  34. { procedure second_string_to_string;override; }
  35. { procedure second_cstring_to_pchar;override; }
  36. { procedure second_string_to_chararray;override; }
  37. { procedure second_array_to_pointer;override; }
  38. function first_int_to_real: tnode; override;
  39. { procedure second_pointer_to_array;override; }
  40. { procedure second_chararray_to_string;override; }
  41. { procedure second_char_to_string;override; }
  42. procedure second_int_to_real;override;
  43. { procedure second_real_to_real;override; }
  44. { procedure second_cord_to_pointer;override; }
  45. procedure second_proc_to_procvar;override;
  46. procedure second_bool_to_int;override;
  47. procedure second_int_to_bool;override;
  48. { procedure second_load_smallset;override; }
  49. { procedure second_ansistring_to_pchar;override; }
  50. { procedure second_pchar_to_string;override; }
  51. { procedure second_class_to_intf;override; }
  52. { procedure second_char_to_char;override; }
  53. procedure second_elem_to_openarray; override;
  54. function target_specific_explicit_typeconv: boolean; override;
  55. function target_specific_general_typeconv: boolean; override;
  56. protected
  57. function do_target_specific_explicit_typeconv(check_only: boolean; out resnode: tnode): boolean;
  58. end;
  59. tjvmasnode = class(tcgasnode)
  60. protected
  61. { to discern beween "obj as tclassref" and "tclassref(obj)" }
  62. classreftypecast: boolean;
  63. function target_specific_typecheck: boolean;override;
  64. public
  65. function pass_1 : tnode;override;
  66. procedure pass_generate_code; override;
  67. function dogetcopy: tnode; override;
  68. function docompare(p: tnode): boolean; override;
  69. constructor ppuload(t: tnodetype; ppufile: tcompilerppufile); override;
  70. procedure ppuwrite(ppufile: tcompilerppufile); override;
  71. end;
  72. tjvmisnode = class(tisnode)
  73. protected
  74. function target_specific_typecheck: boolean;override;
  75. public
  76. function pass_1 : tnode;override;
  77. procedure pass_generate_code; override;
  78. end;
  79. implementation
  80. uses
  81. verbose,globals,globtype,constexp,
  82. symbase,symconst,symdef,symsym,symtable,aasmbase,aasmdata,
  83. defutil,defcmp,jvmdef,
  84. cgbase,cgutils,pass_1,pass_2,
  85. nbas,ncon,ncal,ninl,nld,nmem,procinfo,
  86. nutils,paramgr,
  87. cpubase,aasmcpu,
  88. tgobj,hlcgobj,hlcgcpu;
  89. {*****************************************************************************
  90. TypeCheckTypeConv
  91. *****************************************************************************}
  92. function isvalidprocvartypeconv(fromdef, todef: tdef): boolean;
  93. var
  94. tmethoddef: tdef;
  95. function docheck(def1,def2: tdef): boolean;
  96. begin
  97. result:=false;
  98. if def1.typ<>procvardef then
  99. exit;
  100. { is_addressonly procvars are treated like regular pointer-sized data,
  101. po_methodpointer procvars like implicit pointers to a struct }
  102. if tprocvardef(def1).is_addressonly then
  103. result:=
  104. ((def2.typ=procvardef) and
  105. tprocvardef(def2).is_addressonly) or
  106. (def2=java_jlobject) or
  107. (def2=voidpointertype)
  108. else if po_methodpointer in tprocvardef(def1).procoptions then
  109. begin
  110. if not assigned(tmethoddef) then
  111. tmethoddef:=search_system_type('TMETHOD').typedef;
  112. result:=
  113. (def2=methodpointertype) or
  114. (def2=tmethoddef) or
  115. ((def2.typ=procvardef) and
  116. (po_methodpointer in tprocvardef(def2).procoptions));
  117. end;
  118. { can't typecast nested procvars, they need 3 data pointers }
  119. end;
  120. begin
  121. tmethoddef:=nil;
  122. result:=
  123. docheck(fromdef,todef) or
  124. docheck(todef,fromdef);
  125. end;
  126. function tjvmtypeconvnode.typecheck_dynarray_to_openarray: tnode;
  127. begin
  128. { all arrays are equal in Java }
  129. result:=nil;
  130. convtype:=tc_equal;
  131. end;
  132. function tjvmtypeconvnode.typecheck_string_to_chararray: tnode;
  133. var
  134. newblock: tblocknode;
  135. newstat: tstatementnode;
  136. restemp: ttempcreatenode;
  137. chartype: string;
  138. begin
  139. if (left.nodetype = stringconstn) and
  140. (tstringconstnode(left).cst_type=cst_conststring) then
  141. inserttypeconv(left,cunicodestringtype);
  142. { even constant strings have to be handled via a helper }
  143. if is_widechar(tarraydef(resultdef).elementdef) then
  144. chartype:='widechar'
  145. else
  146. chartype:='char';
  147. newblock:=internalstatements(newstat);
  148. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  149. addstatement(newstat,restemp);
  150. addstatement(newstat,ccallnode.createintern('fpc_'+tstringdef(left.resultdef).stringtypname+
  151. '_to_'+chartype+'array',ccallparanode.create(left,ccallparanode.create(
  152. ctemprefnode.create(restemp),nil))));
  153. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  154. addstatement(newstat,ctemprefnode.create(restemp));
  155. result:=newblock;
  156. left:=nil;
  157. end;
  158. function tjvmtypeconvnode.typecheck_char_to_string: tnode;
  159. begin
  160. { make sure the generic code gets a stringdef }
  161. if self.totypedef=java_jlstring then
  162. begin
  163. inserttypeconv(left,cunicodestringtype);
  164. inserttypeconv(left,totypedef);
  165. result:=left;
  166. left:=nil;
  167. exit;
  168. end;
  169. result:=inherited;
  170. end;
  171. function tjvmtypeconvnode.typecheck_proc_to_procvar: tnode;
  172. begin
  173. result:=inherited typecheck_proc_to_procvar;
  174. if not assigned(totypedef) then
  175. begin
  176. if assigned(tprocvardef(resultdef).classdef) then
  177. internalerror(2011072405);
  178. { associate generic classdef; this is the result of an @proc
  179. expression, and such expressions can never result in a direct call
  180. -> no invoke() method required (which only exists in custom
  181. constructed descendents created for defined procvar types) }
  182. if is_nested_pd(tabstractprocdef(resultdef)) then
  183. { todo }
  184. internalerror(2011072406)
  185. else
  186. tprocvardef(resultdef).classdef:=java_procvarbase;
  187. end;
  188. end;
  189. {*****************************************************************************
  190. FirstTypeConv
  191. *****************************************************************************}
  192. function tjvmtypeconvnode.first_int_to_real: tnode;
  193. begin
  194. if not is_64bitint(left.resultdef) then
  195. if is_signed(left.resultdef) or
  196. (left.resultdef.size<4) then
  197. inserttypeconv(left,s32inttype)
  198. else
  199. inserttypeconv(left,u32inttype);
  200. firstpass(left);
  201. result := nil;
  202. expectloc:=LOC_FPUREGISTER;
  203. end;
  204. function tjvmtypeconvnode.pass_1: tnode;
  205. begin
  206. if (nf_explicit in flags) then
  207. begin
  208. do_target_specific_explicit_typeconv(false,result);
  209. if assigned(result) then
  210. exit;
  211. end;
  212. result:=inherited pass_1;
  213. end;
  214. function tjvmtypeconvnode.simplify(forinline: boolean): tnode;
  215. begin
  216. result:=inherited simplify(forinline);
  217. if assigned(result) then
  218. exit;
  219. { string constants passed to java.lang.String must be converted to
  220. widestring }
  221. if ((is_conststringnode(left) and
  222. not(tstringconstnode(left).cst_type in [cst_unicodestring,cst_widestring])) or
  223. is_constcharnode(left)) and
  224. (maybe_find_real_class_definition(resultdef,false)=java_jlstring) then
  225. inserttypeconv(left,cunicodestringtype);
  226. end;
  227. function tjvmtypeconvnode.first_set_to_set: tnode;
  228. var
  229. setclassdef: tdef;
  230. helpername: string;
  231. begin
  232. result:=nil;
  233. if (left.nodetype=setconstn) then
  234. result:=inherited
  235. { on native targets, only the binary layout has to match. Here, both
  236. sets also have to be either of enums or ordinals, and in case of
  237. enums they have to be of the same base type }
  238. else if (tsetdef(left.resultdef).elementdef.typ=enumdef)=(tsetdef(resultdef).elementdef.typ=enumdef) and
  239. ((tsetdef(left.resultdef).elementdef.typ<>enumdef) or
  240. (tenumdef(tsetdef(left.resultdef).elementdef).getbasedef=tenumdef(tsetdef(resultdef).elementdef).getbasedef)) and
  241. (tsetdef(left.resultdef).setbase=tsetdef(resultdef).setbase) and
  242. (left.resultdef.size=resultdef.size) then
  243. begin
  244. result:=left;
  245. left:=nil;
  246. end
  247. else
  248. begin
  249. { 'deep' conversion }
  250. if tsetdef(resultdef).elementdef.typ<>enumdef then
  251. begin
  252. if tsetdef(left.resultdef).elementdef.typ<>enumdef then
  253. helpername:='fpc_bitset_to_bitset'
  254. else
  255. helpername:='fpc_enumset_to_bitset';
  256. result:=ccallnode.createintern(helpername,ccallparanode.create(
  257. genintconstnode(tsetdef(resultdef).setbase), ccallparanode.create(
  258. genintconstnode(tsetdef(left.resultdef).setbase),
  259. ccallparanode.create(left,nil))));
  260. end
  261. else
  262. begin
  263. if tsetdef(left.resultdef).elementdef.typ<>enumdef then
  264. begin
  265. helpername:='fpcBitSetToEnumSet';
  266. setclassdef:=java_jubitset;
  267. end
  268. else
  269. begin
  270. helpername:='fpcEnumSetToEnumSet';
  271. setclassdef:=java_juenumset;
  272. end;
  273. left:=caddrnode.create_internal(left);
  274. include(left.flags,nf_typedaddr);
  275. inserttypeconv_explicit(left,setclassdef);
  276. result:=ccallnode.createinternmethod(
  277. cloadvmtaddrnode.create(ctypenode.create(setclassdef)),
  278. helpername,ccallparanode.create(
  279. genintconstnode(tsetdef(resultdef).setbase), ccallparanode.create(
  280. genintconstnode(tsetdef(left.resultdef).setbase),
  281. ccallparanode.create(left,nil))));
  282. end;
  283. inserttypeconv_explicit(result,getpointerdef(resultdef));
  284. result:=cderefnode.create(result);
  285. { reused }
  286. left:=nil;
  287. end;
  288. end;
  289. function tjvmtypeconvnode.first_nil_to_methodprocvar: tnode;
  290. begin
  291. result:=inherited first_nil_to_methodprocvar;
  292. if assigned(result) then
  293. exit;
  294. if not assigned(tprocvardef(resultdef).classdef) then
  295. tprocvardef(resultdef).classdef:=java_procvarbase;
  296. result:=ccallnode.createinternmethod(
  297. cloadvmtaddrnode.create(ctypenode.create(tprocvardef(resultdef).classdef)),'CREATE',nil);
  298. { method pointer is an implicit pointer type }
  299. result:=ctypeconvnode.create_explicit(result,getpointerdef(resultdef));
  300. result:=cderefnode.create(result);
  301. end;
  302. function tjvmtypeconvnode.first_proc_to_procvar: tnode;
  303. var
  304. constrparas: tcallparanode;
  305. newpara: tnode;
  306. procdefparas: tarrayconstructornode;
  307. pvs: tparavarsym;
  308. fvs: tsym;
  309. i: longint;
  310. corrclass: tdef;
  311. jlclass: tobjectdef;
  312. encodedtype: tsymstr;
  313. procload: tnode;
  314. procdef: tprocdef;
  315. st: tsymtable;
  316. pushaddr: boolean;
  317. begin
  318. result:=inherited first_proc_to_procvar;
  319. if assigned(result) then
  320. exit;
  321. procdef:=tloadnode(left).procdef;
  322. procload:=tloadnode(left).left;
  323. if not assigned(procload) then
  324. begin
  325. { nested or regular routine -> figure out whether unit-level or
  326. nested, and if nested whether it's nested in a method or in a
  327. regular routine }
  328. st:=procdef.owner;
  329. while st.symtabletype=localsymtable do
  330. st:=st.defowner.owner;
  331. if st.symtabletype in [objectsymtable,recordsymtable] then
  332. { nested routine in method -> part of encloding class }
  333. procload:=cloadvmtaddrnode.create(ctypenode.create(tdef(st.defowner)))
  334. else
  335. begin
  336. { regular procedure/function -> get type representing unit
  337. class }
  338. while not(st.symtabletype in [staticsymtable,globalsymtable]) do
  339. st:=st.defowner.owner;
  340. corrclass:=search_named_unit_globaltype(st.realname^,'__FPC_JVM_MODULE_CLASS_ALIAS$',true).typedef;
  341. procload:=cloadvmtaddrnode.create(ctypenode.create(tdef(corrclass)));
  342. end;
  343. end;
  344. { todo: support nested procvars }
  345. if is_nested_pd(procdef) then
  346. internalerror(2011072607);
  347. { constructor FpcBaseProcVarType.create(inst: jlobject; const method: unicodestring; const argTypes: array of JLClass); }
  348. constrparas:=ccallparanode.create(ctypeconvnode.create_explicit(procload,java_jlobject),nil);
  349. constrparas:=ccallparanode.create(cstringconstnode.createstr(procdef.procsym.realname),constrparas);
  350. procdefparas:=nil;
  351. jlclass:=tobjectdef(search_system_type('JLCLASS').typedef);
  352. { in reverse to make it easier to build the arrayconstructorn }
  353. for i:=procdef.paras.count-1 downto 0 do
  354. begin
  355. pvs:=tparavarsym(procdef.paras[i]);
  356. { self is deal with via the "inst" parameter }
  357. if vo_is_self in pvs.varoptions then
  358. continue;
  359. { in case of an arraydef, pass by jlclass.forName() to get the classdef
  360. (could be optimized by adding support to loadvmtaddrnode to also deal
  361. with arrays, although we'd have to create specific arraydefs for var/
  362. out/constref parameters }
  363. pushaddr:=paramanager.push_copyout_param(pvs.varspez,pvs.vardef,procdef.proccalloption);
  364. if pushaddr or
  365. (pvs.vardef.typ=arraydef) then
  366. begin
  367. encodedtype:=jvmencodetype(pvs.vardef,false);
  368. if pushaddr then
  369. encodedtype:='['+encodedtype;
  370. newpara:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(jlclass)),'FORNAME',
  371. ccallparanode.create(cstringconstnode.createstr(encodedtype),nil));
  372. end
  373. else
  374. begin
  375. corrclass:=jvmgetcorrespondingclassdef(pvs.vardef);
  376. if pvs.vardef.typ in [orddef,floatdef] then
  377. begin
  378. { get the class representing the primitive type }
  379. fvs:=search_struct_member(tobjectdef(corrclass),'FTYPE');
  380. if not assigned(fvs) or
  381. (fvs.typ<>staticvarsym) then
  382. internalerror(2011072417);
  383. newpara:=cloadnode.create(fvs,fvs.owner);
  384. end
  385. else
  386. newpara:=cloadvmtaddrnode.create(ctypenode.create(corrclass));
  387. newpara:=ctypeconvnode.create_explicit(newpara,jlclass);
  388. end;
  389. procdefparas:=carrayconstructornode.create(newpara,procdefparas);
  390. end;
  391. if not assigned(procdefparas) then
  392. procdefparas:=carrayconstructornode.create(nil,nil);
  393. constrparas:=ccallparanode.create(procdefparas,constrparas);
  394. result:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(tprocvardef(resultdef).classdef)),'CREATE',constrparas);
  395. { typecast to the procvar type }
  396. if tprocvardef(resultdef).is_addressonly then
  397. result:=ctypeconvnode.create_explicit(result,resultdef)
  398. else
  399. begin
  400. result:=ctypeconvnode.create_explicit(result,getpointerdef(resultdef));
  401. result:=cderefnode.create(result)
  402. end;
  403. { reused }
  404. tloadnode(left).left:=nil;
  405. end;
  406. {*****************************************************************************
  407. SecondTypeConv
  408. *****************************************************************************}
  409. procedure tjvmtypeconvnode.second_int_to_int;
  410. var
  411. ressize,
  412. leftsize : longint;
  413. begin
  414. { insert range check if not explicit conversion }
  415. if not(nf_explicit in flags) then
  416. hlcg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
  417. { is the result size smaller? when typecasting from void
  418. we always reuse the current location, because there is
  419. nothing that we can load in a register }
  420. ressize:=resultdef.size;
  421. leftsize :=left.resultdef.size;
  422. if ((ressize<>leftsize) or
  423. ((location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  424. (location.reference.arrayreftype<>art_none) and
  425. (is_widechar(left.resultdef)<>is_widechar(resultdef))) or
  426. is_bitpacked_access(left)) and
  427. not is_void(left.resultdef) then
  428. begin
  429. location_copy(location,left.location);
  430. { reuse a loc_reference when the newsize is larger than
  431. than the original and 4 bytes, because all <= 4 byte loads will
  432. result in a stack slot that occupies 4 bytes.
  433. Except
  434. a) for arrays (they use different load instructions for
  435. differently sized data types) or symbols (idem)
  436. b) when going from 4 to 8 bytes, because these are different
  437. data types
  438. }
  439. if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  440. not assigned(location.reference.symbol) and
  441. (location.reference.arrayreftype=art_none) and
  442. (ressize>leftsize) and
  443. (ressize=4) then
  444. begin
  445. location.size:=def_cgsize(resultdef);
  446. { no adjustment of the offset even though Java is big endian,
  447. because the load instruction will remain the same }
  448. end
  449. else
  450. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,false);
  451. end
  452. else
  453. begin
  454. if (ressize < sizeof(aint)) and
  455. (def_cgsize(left.resultdef)<>def_cgsize(resultdef)) then
  456. begin
  457. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  458. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  459. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location,location.register);
  460. end
  461. else
  462. location_copy(location,left.location);
  463. end;
  464. end;
  465. procedure tjvmtypeconvnode.second_int_to_real;
  466. var
  467. srcsize, ressize: longint;
  468. procedure convertsignedstackloc;
  469. begin
  470. case srcsize of
  471. 4:
  472. case ressize of
  473. 4:
  474. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2f));
  475. 8:
  476. begin
  477. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2d));
  478. thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
  479. end;
  480. else
  481. internalerror(2011010601);
  482. end;
  483. 8:
  484. case ressize of
  485. 4:
  486. begin
  487. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2f));
  488. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  489. end;
  490. 8:
  491. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2d));
  492. else
  493. internalerror(2011010602);
  494. end;
  495. else
  496. internalerror(2011010603);
  497. end;
  498. end;
  499. var
  500. signeddef : tdef;
  501. l1 : tasmlabel;
  502. begin
  503. srcsize:=left.resultdef.size;
  504. ressize:=resultdef.size;
  505. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  506. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  507. { first always convert as if it's a signed number }
  508. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  509. convertsignedstackloc;
  510. if not is_signed(left.resultdef) then
  511. begin
  512. { if it was unsigned, add high(cardinal)+1/high(qword)+1 in case
  513. the signed interpretation is < 0 }
  514. current_asmdata.getjumplabel(l1);
  515. if srcsize=4 then
  516. signeddef:=s32inttype
  517. else
  518. signeddef:=s64inttype;
  519. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,signeddef,OC_GTE,0,left.location,l1);
  520. if srcsize=4 then
  521. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,4294967296.0)
  522. else
  523. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,18446744073709551616.0);
  524. if ressize=4 then
  525. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_fadd))
  526. else
  527. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dadd));
  528. hlcg.a_label(current_asmdata.CurrAsmList,l1);
  529. end;
  530. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  531. end;
  532. procedure tjvmtypeconvnode.second_proc_to_procvar;
  533. begin
  534. internalerror(2011072506);
  535. end;
  536. procedure tjvmtypeconvnode.second_bool_to_int;
  537. var
  538. newsize: tcgsize;
  539. oldTrueLabel,oldFalseLabel : tasmlabel;
  540. begin
  541. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  542. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  543. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  544. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  545. secondpass(left);
  546. location_copy(location,left.location);
  547. newsize:=def_cgsize(resultdef);
  548. { byte(bytebool) or word(wordbool) or longint(longbool) must be }
  549. { accepted for var parameters and assignments, and must not }
  550. { change the ordinal value or value location. }
  551. { htypechk.valid_for_assign ensures that such locations with a }
  552. { size<sizeof(register) cannot be LOC_CREGISTER (they otherwise }
  553. { could be in case of a plain assignment), and LOC_REGISTER can }
  554. { never be an assignment target. The remaining LOC_REGISTER/ }
  555. { LOC_CREGISTER locations do have to be sign/zero-extended. }
  556. { -- Note: this does not work for Java and 2/4 byte sized
  557. values, because bytebool/wordbool are signed and
  558. are stored in 4 byte locations -> will result in
  559. "byte" with the value high(cardinal); see remark
  560. in second_int_to_int above regarding consequences }
  561. if not(nf_explicit in flags) or
  562. (location.loc in [LOC_FLAGS,LOC_JUMP]) or
  563. ((newsize<>left.location.size) and
  564. ((left.resultdef.size<>resultdef.size) or
  565. not(left.resultdef.size in [4,8]))
  566. ) then
  567. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  568. else
  569. { may differ in sign, e.g. bytebool -> byte }
  570. location.size:=newsize;
  571. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  572. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  573. end;
  574. procedure tjvmtypeconvnode.second_int_to_bool;
  575. var
  576. hlabel1,hlabel2,oldTrueLabel,oldFalseLabel : tasmlabel;
  577. newsize : tcgsize;
  578. begin
  579. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  580. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  581. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  582. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  583. secondpass(left);
  584. if codegenerror then
  585. exit;
  586. { Explicit typecasts from any ordinal type to a boolean type }
  587. { must not change the ordinal value }
  588. if (nf_explicit in flags) and
  589. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
  590. begin
  591. location_copy(location,left.location);
  592. newsize:=def_cgsize(resultdef);
  593. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  594. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  595. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  596. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  597. else
  598. location.size:=newsize;
  599. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  600. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  601. exit;
  602. end;
  603. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  604. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  605. current_asmdata.getjumplabel(hlabel2);
  606. case left.location.loc of
  607. LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
  608. begin
  609. current_asmdata.getjumplabel(hlabel1);
  610. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location,hlabel1);
  611. end;
  612. LOC_JUMP :
  613. begin
  614. hlabel1:=current_procinfo.CurrFalseLabel;
  615. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  616. end;
  617. else
  618. internalerror(10062);
  619. end;
  620. if not(is_cbool(resultdef)) then
  621. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,1,R_INTREGISTER)
  622. else
  623. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,-1,R_INTREGISTER);
  624. { we jump over the next constant load -> they don't appear on the
  625. stack simulataneously }
  626. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  627. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel2);
  628. hlcg.a_label(current_asmdata.CurrAsmList,hlabel1);
  629. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,0,R_INTREGISTER);
  630. hlcg.a_label(current_asmdata.CurrAsmList,hlabel2);
  631. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  632. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  633. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  634. end;
  635. procedure tjvmtypeconvnode.second_elem_to_openarray;
  636. var
  637. primitivetype: boolean;
  638. opc: tasmop;
  639. mangledname: string;
  640. basereg: tregister;
  641. arrayref: treference;
  642. begin
  643. { create an array with one element of the required type }
  644. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s32inttype,1,R_INTREGISTER);
  645. mangledname:=jvmarrtype(left.resultdef,primitivetype);
  646. if primitivetype then
  647. opc:=a_newarray
  648. else
  649. opc:=a_anewarray;
  650. { doesn't change stack height: one int replaced by one reference }
  651. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opc,current_asmdata.RefAsmSymbol(mangledname)));
  652. { store the data in the newly created array }
  653. basereg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
  654. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,java_jlobject,basereg);
  655. reference_reset_base(arrayref,basereg,0,4);
  656. arrayref.arrayreftype:=art_indexconst;
  657. arrayref.indexoffset:=0;
  658. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location,arrayref);
  659. location_reset_ref(location,LOC_REFERENCE,OS_ADDR,4);
  660. tg.gethltemp(current_asmdata.CurrAsmList,java_jlobject,4,tt_normal,location.reference);
  661. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,java_jlobject,java_jlobject,basereg,location.reference);
  662. end;
  663. procedure get_most_nested_types(var fromdef, todef: tdef);
  664. begin
  665. while is_dynamic_array(fromdef) and
  666. is_dynamic_array(todef) do
  667. begin
  668. fromdef:=tarraydef(fromdef).elementdef;
  669. todef:=tarraydef(todef).elementdef;
  670. end;
  671. fromdef:=maybe_find_real_class_definition(fromdef,false);
  672. todef:=maybe_find_real_class_definition(todef,false);
  673. end;
  674. function tjvmtypeconvnode.do_target_specific_explicit_typeconv(check_only: boolean; out resnode: tnode): boolean;
  675. { handle explicit typecast from int to to real or vice versa }
  676. function int_real_explicit_typecast(fdef: tfloatdef; const singlemethod, doublemethod: string): tnode;
  677. var
  678. csym: ttypesym;
  679. psym: tsym;
  680. begin
  681. { use the float/double to raw bits methods to get the bit pattern }
  682. if fdef.floattype=s32real then
  683. begin
  684. csym:=search_system_type('JLFLOAT');
  685. psym:=search_struct_member(tobjectdef(csym.typedef),singlemethod);
  686. end
  687. else
  688. begin
  689. csym:=search_system_type('JLDOUBLE');
  690. psym:=search_struct_member(tobjectdef(csym.typedef),doublemethod);
  691. end;
  692. if not assigned(psym) or
  693. (psym.typ<>procsym) then
  694. internalerror(2011012901);
  695. { call the (static class) method to get the raw bits }
  696. result:=ccallnode.create(ccallparanode.create(left,nil),
  697. tprocsym(psym),psym.owner,
  698. cloadvmtaddrnode.create(ctypenode.create(csym.typedef)),[]);
  699. { convert the result to the result type of this type conversion node }
  700. inserttypeconv_explicit(result,resultdef);
  701. { left is reused }
  702. left:=nil;
  703. end;
  704. function ord_enum_explicit_typecast(fdef: torddef; todef: tenumdef): tnode;
  705. var
  706. psym: tsym;
  707. begin
  708. { we only create a class for the basedefs }
  709. todef:=todef.getbasedef;
  710. psym:=search_struct_member(todef.classdef,'FPCVALUEOF');
  711. if not assigned(psym) or
  712. (psym.typ<>procsym) then
  713. internalerror(2011062601);
  714. result:=ccallnode.create(ccallparanode.create(left,nil),
  715. tprocsym(psym),psym.owner,
  716. cloadvmtaddrnode.create(ctypenode.create(todef.classdef)),[]);
  717. { convert the result to the result type of this type conversion node }
  718. inserttypeconv_explicit(result,resultdef);
  719. { left is reused }
  720. left:=nil;
  721. end;
  722. function enum_ord_explicit_typecast(fdef: tenumdef; todef: torddef): tnode;
  723. var
  724. psym: tsym;
  725. begin
  726. { we only create a class for the basedef }
  727. fdef:=fdef.getbasedef;
  728. psym:=search_struct_member(fdef.classdef,'FPCORDINAL');
  729. if not assigned(psym) or
  730. (psym.typ<>procsym) then
  731. internalerror(2011062602);
  732. result:=ccallnode.create(nil,tprocsym(psym),psym.owner,left,[]);
  733. { convert the result to the result type of this type conversion node }
  734. inserttypeconv_explicit(result,resultdef);
  735. { left is reused }
  736. left:=nil;
  737. end;
  738. function from_set_explicit_typecast: tnode;
  739. var
  740. helpername: string;
  741. setconvdef: tdef;
  742. begin
  743. if tsetdef(left.resultdef).elementdef.typ=enumdef then
  744. begin
  745. setconvdef:=java_juenumset;
  746. helpername:='fpc_enumset_to_'
  747. end
  748. else
  749. begin
  750. setconvdef:=java_jubitset;
  751. helpername:='fpc_bitset_to_'
  752. end;
  753. if left.resultdef.size<=4 then
  754. helpername:=helpername+'int'
  755. else
  756. helpername:=helpername+'long';
  757. result:=ccallnode.createintern(helpername,ccallparanode.create(
  758. genintconstnode(left.resultdef.size),ccallparanode.create(genintconstnode(tsetdef(left.resultdef).setbase),
  759. ccallparanode.create(ctypeconvnode.create_explicit(left,setconvdef),nil))));
  760. left:=nil;
  761. end;
  762. function to_set_explicit_typecast: tnode;
  763. var
  764. enumclassdef: tobjectdef;
  765. mp: tnode;
  766. helpername: string;
  767. begin
  768. if tsetdef(resultdef).elementdef.typ=enumdef then
  769. begin
  770. inserttypeconv_explicit(left,s64inttype);
  771. enumclassdef:=tenumdef(tsetdef(resultdef).elementdef).getbasedef.classdef;
  772. mp:=cloadvmtaddrnode.create(ctypenode.create(enumclassdef));
  773. helpername:='fpcLongToEnumSet';
  774. { enumclass.fpcLongToEnumSet(left,setbase,setsize) }
  775. result:=ccallnode.createinternmethod(mp,helpername,
  776. ccallparanode.create(genintconstnode(resultdef.size),
  777. ccallparanode.create(genintconstnode(tsetdef(resultdef).setbase),
  778. ccallparanode.create(left,nil))));
  779. end
  780. else
  781. begin
  782. if left.resultdef.size<=4 then
  783. begin
  784. helpername:='fpc_int_to_bitset';
  785. inserttypeconv_explicit(left,s32inttype);
  786. end
  787. else
  788. begin
  789. helpername:='fpc_long_to_bitset';
  790. inserttypeconv_explicit(left,s64inttype);
  791. end;
  792. result:=ccallnode.createintern(helpername,
  793. ccallparanode.create(genintconstnode(resultdef.size),
  794. ccallparanode.create(genintconstnode(tsetdef(resultdef).setbase),
  795. ccallparanode.create(left,nil))));
  796. end;
  797. end;
  798. function procvar_to_procvar(fromdef, todef: tdef): tnode;
  799. var
  800. fsym: tsym;
  801. begin
  802. result:=nil;
  803. if fromdef=todef then
  804. exit;
  805. fsym:=tfieldvarsym(search_struct_member(tprocvardef(fromdef).classdef,'METHOD'));
  806. if not assigned(fsym) or
  807. (fsym.typ<>fieldvarsym) then
  808. internalerror(2011072414);
  809. { can either be a procvar or a procvarclass }
  810. if fromdef.typ=procvardef then
  811. begin
  812. left:=ctypeconvnode.create_explicit(left,tprocvardef(fromdef).classdef);
  813. include(left.flags,nf_load_procvar);
  814. typecheckpass(left);
  815. end;
  816. result:=csubscriptnode.create(fsym,left);
  817. { create destination procvartype with info from source }
  818. result:=ccallnode.createinternmethod(
  819. cloadvmtaddrnode.create(ctypenode.create(tprocvardef(todef).classdef)),
  820. 'CREATE',ccallparanode.create(result,nil));
  821. left:=nil;
  822. end;
  823. function procvar_to_tmethod(fromdef, todef: tdef): tnode;
  824. var
  825. fsym: tsym;
  826. begin
  827. { must be procedure-of-object -> implicit pointer type -> get address
  828. before typecasting to corresponding classdef }
  829. left:=caddrnode.create_internal(left);
  830. inserttypeconv_explicit(left,tprocvardef(fromdef).classdef);
  831. fsym:=tfieldvarsym(search_struct_member(tprocvardef(fromdef).classdef,'METHOD'));
  832. if not assigned(fsym) or
  833. (fsym.typ<>fieldvarsym) then
  834. internalerror(2011072414);
  835. result:=csubscriptnode.create(fsym,left);
  836. left:=nil;
  837. end;
  838. function tmethod_to_procvar(fromdef, todef: tdef): tnode;
  839. var
  840. fsym: tsym;
  841. begin
  842. fsym:=tfieldvarsym(search_struct_member(tprocvardef(todef).classdef,'METHOD'));
  843. if not assigned(fsym) or
  844. (fsym.typ<>fieldvarsym) then
  845. internalerror(2011072415);
  846. result:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(tprocvardef(todef).classdef)),
  847. 'CREATE',ccallparanode.create(left,nil));
  848. left:=nil;
  849. end;
  850. function ptr_no_typecheck_required(fromdef, todef: tdef): boolean;
  851. function check_type_equality(def1,def2: tdef): boolean;
  852. begin
  853. result:=true;
  854. if is_ansistring(def1) and
  855. (def2=java_ansistring) then
  856. exit;
  857. if is_wide_or_unicode_string(def1) and
  858. (def2=java_jlstring) then
  859. exit;
  860. if def1.typ=pointerdef then
  861. begin
  862. if is_shortstring(tpointerdef(def1).pointeddef) and
  863. (def2=java_shortstring) then
  864. exit;
  865. { pointer-to-set to JUEnumSet/JUBitSet }
  866. if (tpointerdef(def1).pointeddef.typ=setdef) then
  867. begin
  868. if not assigned(tsetdef(tpointerdef(def1).pointeddef).elementdef) then
  869. begin
  870. if (def2=java_jubitset) or
  871. (def2=java_juenumset) then
  872. exit;
  873. end
  874. else if tsetdef(tpointerdef(def1).pointeddef).elementdef.typ=enumdef then
  875. begin
  876. if def2=java_juenumset then
  877. exit;
  878. end
  879. else if def2=java_jubitset then
  880. exit;
  881. end;
  882. end;
  883. result:=false;
  884. end;
  885. function check_array_type_equality(def1,def2: tdef): boolean;
  886. begin
  887. result:=true;
  888. if is_shortstring(def1) and
  889. (def2=java_shortstring) then
  890. exit;
  891. result:=false;
  892. end;
  893. begin
  894. result:=true;
  895. { check procvar conversion compatibility via their classes }
  896. if fromdef.typ=procvardef then
  897. fromdef:=tprocvardef(fromdef).classdef;
  898. if todef.typ=procvardef then
  899. todef:=tprocvardef(todef).classdef;
  900. if (todef=java_jlobject) or
  901. (todef=voidpointertype) then
  902. exit;
  903. if compare_defs(fromdef,todef,nothingn)>=te_equal then
  904. exit;
  905. { trecorddef.is_related() must work for inheritance/method checking,
  906. but do not allow records to be directly typecasted into class/
  907. pointer types (you have to use FpcBaseRecordType(@rec) instead) }
  908. if not is_record(fromdef) and
  909. fromdef.is_related(todef) then
  910. exit;
  911. if check_type_equality(fromdef,todef) then
  912. exit;
  913. if check_type_equality(todef,fromdef) then
  914. exit;
  915. if (fromdef.typ=pointerdef) and
  916. (tpointerdef(fromdef).pointeddef.typ=recorddef) and
  917. (todef=java_fpcbaserecordtype) then
  918. exit;
  919. { all classrefs are currently java.lang.Class at the bytecode level }
  920. if (fromdef.typ=classrefdef) and
  921. (todef.typ=objectdef) and
  922. (todef=search_system_type('JLCLASS').typedef) then
  923. exit;
  924. if (fromdef.typ=classrefdef) and
  925. (todef.typ=classrefdef) and
  926. tclassrefdef(fromdef).pointeddef.is_related(tclassrefdef(todef).pointeddef) then
  927. exit;
  928. { special case: "array of shortstring" to "array of ShortstringClass"
  929. and "array of <record>" to "array of FpcRecordBaseType" (normally
  930. you have to use ShortstringClass(@shortstrvar) etc, but that's not
  931. possible in case of passing arrays to e.g. setlength) }
  932. if is_dynamic_array(left.resultdef) and
  933. is_dynamic_array(resultdef) then
  934. begin
  935. if check_array_type_equality(fromdef,todef) or
  936. check_array_type_equality(todef,fromdef) then
  937. exit;
  938. if is_record(fromdef) and
  939. (todef=java_fpcbaserecordtype) then
  940. exit;
  941. end;
  942. result:=false;
  943. end;
  944. var
  945. fromclasscompatible,
  946. toclasscompatible: boolean;
  947. fromdef,
  948. todef: tdef;
  949. fromarrtype,
  950. toarrtype: char;
  951. begin
  952. resnode:=nil;
  953. if not(convtype in [tc_equal,tc_int_2_int,tc_int_2_bool,tc_bool_2_int,tc_class_2_intf]) or
  954. ((convtype in [tc_equal,tc_int_2_int,tc_bool_2_int,tc_int_2_bool]) and
  955. ((left.resultdef.typ=orddef) and
  956. (resultdef.typ=orddef))) then
  957. begin
  958. result:=false;
  959. exit
  960. end;
  961. { This routine is only called for explicit typeconversions of same-sized
  962. entities that aren't handled by normal type conversions -> bit pattern
  963. reinterpretations. In the JVM, many of these also need special
  964. handling because of the type safety. }
  965. { don't allow conversions between object-based and non-object-based
  966. types }
  967. fromclasscompatible:=
  968. (left.resultdef.typ=formaldef) or
  969. (left.resultdef.typ=pointerdef) or
  970. is_java_class_or_interface(left.resultdef) or
  971. is_dynamic_array(left.resultdef) or
  972. ((left.resultdef.typ in [stringdef,classrefdef]) and
  973. not is_shortstring(left.resultdef)) or
  974. (left.resultdef.typ=enumdef) or
  975. { procvar2procvar needs special handling }
  976. ((left.resultdef.typ=procvardef) and
  977. tprocvardef(left.resultdef).is_addressonly and
  978. (resultdef.typ<>procvardef));
  979. toclasscompatible:=
  980. (resultdef.typ=pointerdef) or
  981. is_java_class_or_interface(resultdef) or
  982. is_dynamic_array(resultdef) or
  983. ((resultdef.typ in [stringdef,classrefdef]) and
  984. not is_shortstring(resultdef)) or
  985. (resultdef.typ=enumdef) or
  986. ((resultdef.typ=procvardef) and
  987. tprocvardef(resultdef).is_addressonly);
  988. { typescasts from void (the result of untyped_ptr^) to an implicit
  989. pointertype (record, array, ...) also needs a typecheck }
  990. if is_void(left.resultdef) and
  991. jvmimplicitpointertype(resultdef) then
  992. begin
  993. fromclasscompatible:=true;
  994. toclasscompatible:=true;
  995. end;
  996. if fromclasscompatible and toclasscompatible then
  997. begin
  998. { we need an as-node to check the validity of the conversion (since
  999. it wasn't handled by another type conversion, we know it can't
  1000. have been valid normally)
  1001. Exceptions: (most nested) destination is
  1002. * java.lang.Object, since everything is compatible with that type
  1003. * related to source
  1004. * a primitive that are represented by the same type in Java
  1005. (e.g., byte and shortint) }
  1006. { in case of arrays, check the compatibility of the innermost types }
  1007. fromdef:=left.resultdef;
  1008. todef:=resultdef;
  1009. get_most_nested_types(fromdef,todef);
  1010. { in case of enums, get the equivalent class definitions }
  1011. if (fromdef.typ=enumdef) then
  1012. fromdef:=tenumdef(fromdef).getbasedef;
  1013. if (todef.typ=enumdef) then
  1014. todef:=tenumdef(todef).getbasedef;
  1015. fromarrtype:=jvmarrtype_setlength(fromdef);
  1016. toarrtype:=jvmarrtype_setlength(todef);
  1017. if not ptr_no_typecheck_required(fromdef,todef) then
  1018. begin
  1019. if (fromarrtype in ['A','R','T','E','L','P']) or
  1020. (fromarrtype<>toarrtype) then
  1021. begin
  1022. if not check_only and
  1023. not assignment_side then
  1024. begin
  1025. resnode:=ctypenode.create(resultdef);
  1026. if resultdef.typ=objectdef then
  1027. resnode:=cloadvmtaddrnode.create(resnode);
  1028. resnode:=casnode.create_internal(left,resnode);
  1029. if resultdef.typ=classrefdef then
  1030. tjvmasnode(resnode).classreftypecast:=true;
  1031. left:=nil;
  1032. end
  1033. end
  1034. { typecasting from a child to a parent type on the assignment side
  1035. will (rightly) mess up the type safety verification of the JVM }
  1036. else if assignment_side then
  1037. CGMessage(type_e_no_managed_assign_generic_typecast);
  1038. end;
  1039. result:=true;
  1040. exit;
  1041. end;
  1042. { a formaldef can be converted to anything, but not on the assignment
  1043. side }
  1044. if (left.resultdef.typ=formaldef) and
  1045. not assignment_side then
  1046. begin
  1047. if resultdef.typ in [orddef,floatdef] then
  1048. begin
  1049. if not check_only then
  1050. begin
  1051. resnode:=cinlinenode.create(in_unbox_x_y,false,
  1052. ccallparanode.create(ctypenode.create(resultdef),
  1053. ccallparanode.create(left,nil)));
  1054. left:=nil;
  1055. end;
  1056. result:=true;
  1057. exit;
  1058. end
  1059. else if jvmimplicitpointertype(resultdef) then
  1060. begin
  1061. { typecast formaldef to pointer to the type, then deref, so that
  1062. a proper checkcast is inserted }
  1063. if not check_only then
  1064. begin
  1065. resnode:=ctypeconvnode.create_explicit(left,getpointerdef(resultdef));
  1066. resnode:=cderefnode.create(resnode);
  1067. left:=nil;
  1068. end;
  1069. result:=true;
  1070. exit;
  1071. end;
  1072. result:=false;
  1073. exit;
  1074. end;
  1075. { procvar to tmethod and vice versa, and procvar to procvar }
  1076. if isvalidprocvartypeconv(left.resultdef,resultdef) then
  1077. begin
  1078. if not check_only then
  1079. begin
  1080. if (left.resultdef.typ=procvardef) and
  1081. (resultdef.typ=procvardef) then
  1082. resnode:=procvar_to_procvar(left.resultdef,resultdef)
  1083. else if left.resultdef.typ=procvardef then
  1084. resnode:=procvar_to_tmethod(left.resultdef,resultdef)
  1085. else
  1086. resnode:=tmethod_to_procvar(left.resultdef,resultdef);
  1087. end;
  1088. result:=true;
  1089. exit;
  1090. end;
  1091. { don't allow conversions between different classes of primitive types,
  1092. except for a few special cases }
  1093. { float to int/enum explicit type conversion: get the bits }
  1094. if (left.resultdef.typ=floatdef) and
  1095. (is_integer(resultdef) or
  1096. (resultdef.typ=enumdef)) then
  1097. begin
  1098. if not check_only then
  1099. resnode:=int_real_explicit_typecast(tfloatdef(left.resultdef),'FLOATTORAWINTBITS','DOUBLETORAWLONGBITS');
  1100. result:=true;
  1101. exit;
  1102. end;
  1103. { int to float explicit type conversion: also use the bits }
  1104. if (is_integer(left.resultdef) or
  1105. (left.resultdef.typ=enumdef)) and
  1106. (resultdef.typ=floatdef) then
  1107. begin
  1108. if not check_only then
  1109. begin
  1110. if (left.resultdef.typ=enumdef) then
  1111. inserttypeconv_explicit(left,s32inttype);
  1112. resnode:=int_real_explicit_typecast(tfloatdef(resultdef),'INTBITSTOFLOAT','LONGBITSTODOUBLE');
  1113. end;
  1114. result:=true;
  1115. exit;
  1116. end;
  1117. { enums }
  1118. if (left.resultdef.typ=enumdef) or
  1119. (resultdef.typ=enumdef) then
  1120. begin
  1121. { both enum? }
  1122. if (resultdef.typ=left.resultdef.typ) then
  1123. begin
  1124. { same base type -> nothing special }
  1125. fromdef:=tenumdef(left.resultdef).getbasedef;
  1126. todef:=tenumdef(resultdef).getbasedef;
  1127. if fromdef=todef then
  1128. begin
  1129. result:=false;
  1130. exit;
  1131. end;
  1132. { convert via ordinal intermediate }
  1133. if not check_only then
  1134. begin;
  1135. inserttypeconv_explicit(left,s32inttype);
  1136. inserttypeconv_explicit(left,resultdef);
  1137. resnode:=left;
  1138. left:=nil
  1139. end;
  1140. result:=true;
  1141. exit;
  1142. end;
  1143. { enum to orddef & vice versa }
  1144. if left.resultdef.typ=orddef then
  1145. begin
  1146. if not check_only then
  1147. resnode:=ord_enum_explicit_typecast(torddef(left.resultdef),tenumdef(resultdef));
  1148. result:=true;
  1149. exit;
  1150. end
  1151. else if resultdef.typ=orddef then
  1152. begin
  1153. if not check_only then
  1154. resnode:=enum_ord_explicit_typecast(tenumdef(left.resultdef),torddef(resultdef));
  1155. result:=true;
  1156. exit;
  1157. end
  1158. end;
  1159. { sets }
  1160. if (left.resultdef.typ=setdef) or
  1161. (resultdef.typ=setdef) then
  1162. begin
  1163. { set -> ord/enum/other-set-type }
  1164. if (resultdef.typ in [orddef,enumdef]) then
  1165. begin
  1166. if not check_only then
  1167. begin
  1168. resnode:=from_set_explicit_typecast;
  1169. { convert to desired result }
  1170. inserttypeconv_explicit(resnode,resultdef);
  1171. end;
  1172. result:=true;
  1173. exit;
  1174. end
  1175. { ord/enum -> set }
  1176. else if (left.resultdef.typ in [orddef,enumdef]) then
  1177. begin
  1178. if not check_only then
  1179. begin
  1180. resnode:=to_set_explicit_typecast;
  1181. { convert to desired result }
  1182. inserttypeconv_explicit(resnode,getpointerdef(resultdef));
  1183. resnode:=cderefnode.create(resnode);
  1184. end;
  1185. result:=true;
  1186. exit;
  1187. end;
  1188. { if someone needs it, float->set and set->float explicit typecasts
  1189. could also be added (cannot be handled by the above, because
  1190. float(intvalue) will convert rather than re-interpret the value) }
  1191. end;
  1192. { anything not explicitly handled is a problem }
  1193. result:=true;
  1194. CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
  1195. end;
  1196. function tjvmtypeconvnode.target_specific_explicit_typeconv: boolean;
  1197. var
  1198. dummyres: tnode;
  1199. begin
  1200. result:=do_target_specific_explicit_typeconv(true,dummyres);
  1201. end;
  1202. function tjvmtypeconvnode.target_specific_general_typeconv: boolean;
  1203. begin
  1204. result:=false;
  1205. { on the JVM platform, enums can always be converted to class instances,
  1206. because enums /are/ class instances there. To prevent the
  1207. typechecking/conversion code from assuming it can treat it like any
  1208. ordinal constant, firstpass() it so that the ordinal constant gets
  1209. replaced with a load of a staticvarsym. This is not done in
  1210. pass_typecheck, because that would prevent many optimizations }
  1211. if (left.nodetype=ordconstn) and
  1212. (left.resultdef.typ=enumdef) and
  1213. (resultdef.typ=objectdef) then
  1214. firstpass(left);
  1215. end;
  1216. {*****************************************************************************
  1217. AsNode and IsNode common helpers
  1218. *****************************************************************************}
  1219. function asis_target_specific_typecheck(node: tasisnode): boolean;
  1220. var
  1221. realtodef: tdef;
  1222. begin
  1223. if not(nf_internal in node.flags) then
  1224. begin
  1225. { handle using normal code }
  1226. result:=false;
  1227. exit;
  1228. end;
  1229. result:=true;
  1230. { these are converted type conversion nodes, to insert the checkcast
  1231. operations }
  1232. realtodef:=node.right.resultdef;
  1233. if (realtodef.typ=classrefdef) and
  1234. ((node.nodetype<>asn) or
  1235. not tjvmasnode(node).classreftypecast) then
  1236. realtodef:=tclassrefdef(realtodef).pointeddef;
  1237. realtodef:=maybe_find_real_class_definition(realtodef,false);
  1238. if result then
  1239. if node.nodetype=asn then
  1240. node.resultdef:=realtodef
  1241. else
  1242. node.resultdef:=pasbool8type;
  1243. end;
  1244. function asis_pass_1(node: tasisnode; const methodname: string): tnode;
  1245. var
  1246. ps: tsym;
  1247. call: tnode;
  1248. jlclass: tobjectdef;
  1249. begin
  1250. result:=nil;
  1251. firstpass(node.left);
  1252. if not(node.right.nodetype in [typen,loadvmtaddrn]) then
  1253. begin
  1254. if (node.nodetype=isn) or
  1255. not assigned(tasnode(node).call) then
  1256. begin
  1257. if not is_javaclassref(node.right.resultdef) then
  1258. internalerror(2011041920);
  1259. firstpass(node.right);
  1260. jlclass:=tobjectdef(search_system_type('JLCLASS').typedef);
  1261. ps:=search_struct_member(jlclass,methodname);
  1262. if not assigned(ps) or
  1263. (ps.typ<>procsym) then
  1264. internalerror(2011041910);
  1265. call:=ccallnode.create(ccallparanode.create(node.left,nil),tprocsym(ps),ps.owner,ctypeconvnode.create_explicit(node.right,jlclass),[]);
  1266. node.left:=nil;
  1267. node.right:=nil;
  1268. firstpass(call);
  1269. if codegenerror then
  1270. exit;
  1271. if node.nodetype=isn then
  1272. result:=call
  1273. else
  1274. begin
  1275. tasnode(node).call:=call;
  1276. node.expectloc:=call.expectloc;
  1277. end;
  1278. end;
  1279. end
  1280. else
  1281. begin
  1282. node.expectloc:=LOC_REGISTER;
  1283. result:=nil;
  1284. end;
  1285. end;
  1286. function asis_generate_code(node: tasisnode; opcode: tasmop): boolean;
  1287. var
  1288. checkdef: tdef;
  1289. begin
  1290. if (node.nodetype=asn) and
  1291. assigned(tasnode(node).call) then
  1292. begin
  1293. result:=false;
  1294. exit;
  1295. end;
  1296. result:=true;
  1297. secondpass(node.left);
  1298. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,node.left.resultdef,node.left.location);
  1299. location_freetemp(current_asmdata.CurrAsmList,node.left.location);
  1300. { Perform a checkcast instruction, which will raise an exception in case
  1301. the actual type does not match/inherit from the expected type.
  1302. Object types need the full type name (package+class name), arrays only
  1303. the array definition }
  1304. if node.nodetype=asn then
  1305. checkdef:=node.resultdef
  1306. else if node.right.resultdef.typ=classrefdef then
  1307. checkdef:=tclassrefdef(node.right.resultdef).pointeddef
  1308. else
  1309. checkdef:=node.right.resultdef;
  1310. { replace special types with their equivalent class type }
  1311. if (checkdef.typ=pointerdef) and
  1312. jvmimplicitpointertype(tpointerdef(checkdef).pointeddef) then
  1313. checkdef:=tpointerdef(checkdef).pointeddef;
  1314. if (checkdef=voidpointertype) or
  1315. (checkdef.typ=formaldef) then
  1316. checkdef:=java_jlobject
  1317. else if checkdef.typ=enumdef then
  1318. checkdef:=tenumdef(checkdef).classdef
  1319. else if checkdef.typ=setdef then
  1320. begin
  1321. if tsetdef(checkdef).elementdef.typ=enumdef then
  1322. checkdef:=java_juenumset
  1323. else
  1324. checkdef:=java_jubitset;
  1325. end
  1326. else if checkdef.typ=procvardef then
  1327. checkdef:=tprocvardef(checkdef).classdef
  1328. else if is_wide_or_unicode_string(checkdef) then
  1329. checkdef:=java_jlstring
  1330. else if is_ansistring(checkdef) then
  1331. checkdef:=java_ansistring
  1332. else if is_shortstring(checkdef) then
  1333. checkdef:=java_shortstring;
  1334. if checkdef.typ in [objectdef,recorddef] then
  1335. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
  1336. else if checkdef.typ=classrefdef then
  1337. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol('java/lang/Class')))
  1338. else
  1339. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef,false))));
  1340. location_reset(node.location,LOC_REGISTER,OS_ADDR);
  1341. node.location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,node.resultdef);
  1342. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,node.resultdef,node.location.register);
  1343. end;
  1344. {*****************************************************************************
  1345. TJVMAsNode
  1346. *****************************************************************************}
  1347. function tjvmasnode.target_specific_typecheck: boolean;
  1348. begin
  1349. result:=asis_target_specific_typecheck(self);
  1350. end;
  1351. function tjvmasnode.pass_1: tnode;
  1352. begin
  1353. result:=asis_pass_1(self,'CAST');
  1354. end;
  1355. procedure tjvmasnode.pass_generate_code;
  1356. begin
  1357. if not asis_generate_code(self,a_checkcast) then
  1358. inherited;
  1359. end;
  1360. function tjvmasnode.dogetcopy: tnode;
  1361. begin
  1362. result:=inherited dogetcopy;
  1363. tjvmasnode(result).classreftypecast:=classreftypecast;
  1364. end;
  1365. function tjvmasnode.docompare(p: tnode): boolean;
  1366. begin
  1367. result:=
  1368. inherited docompare(p) and
  1369. (tjvmasnode(p).classreftypecast=classreftypecast);
  1370. end;
  1371. constructor tjvmasnode.ppuload(t: tnodetype; ppufile: tcompilerppufile);
  1372. begin
  1373. inherited;
  1374. classreftypecast:=boolean(ppufile.getbyte);
  1375. end;
  1376. procedure tjvmasnode.ppuwrite(ppufile: tcompilerppufile);
  1377. begin
  1378. inherited ppuwrite(ppufile);
  1379. ppufile.putbyte(byte(classreftypecast));
  1380. end;
  1381. {*****************************************************************************
  1382. TJVMIsNode
  1383. *****************************************************************************}
  1384. function tjvmisnode.target_specific_typecheck: boolean;
  1385. begin
  1386. result:=asis_target_specific_typecheck(self);
  1387. end;
  1388. function tjvmisnode.pass_1: tnode;
  1389. begin
  1390. result:=asis_pass_1(self,'ISINSTANCE');
  1391. end;
  1392. procedure tjvmisnode.pass_generate_code;
  1393. begin
  1394. if not asis_generate_code(self,a_instanceof) then
  1395. inherited;
  1396. end;
  1397. begin
  1398. ctypeconvnode:=tjvmtypeconvnode;
  1399. casnode:=tjvmasnode;
  1400. cisnode:=tjvmisnode;
  1401. end.