njvmcnv.pas 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537
  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. if not assigned(procdef.import_name) then
  350. constrparas:=ccallparanode.create(cstringconstnode.createstr(procdef.procsym.realname),constrparas)
  351. else
  352. constrparas:=ccallparanode.create(cstringconstnode.createstr(procdef.import_name^),constrparas);
  353. procdefparas:=nil;
  354. jlclass:=tobjectdef(search_system_type('JLCLASS').typedef);
  355. { in reverse to make it easier to build the arrayconstructorn }
  356. for i:=procdef.paras.count-1 downto 0 do
  357. begin
  358. pvs:=tparavarsym(procdef.paras[i]);
  359. { self is is an implicit parameter for normal methods }
  360. if (vo_is_self in pvs.varoptions) and
  361. not(po_classmethod in procdef.procoptions) then
  362. continue;
  363. { in case of an arraydef, pass by jlclass.forName() to get the classdef
  364. (could be optimized by adding support to loadvmtaddrnode to also deal
  365. with arrays, although we'd have to create specific arraydefs for var/
  366. out/constref parameters }
  367. pushaddr:=paramanager.push_copyout_param(pvs.varspez,pvs.vardef,procdef.proccalloption);
  368. if pushaddr or
  369. (pvs.vardef.typ=arraydef) then
  370. begin
  371. encodedtype:=jvmencodetype(pvs.vardef,false);
  372. if pushaddr then
  373. encodedtype:='['+encodedtype;
  374. newpara:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(jlclass)),'FORNAME',
  375. ccallparanode.create(cstringconstnode.createstr(encodedtype),nil));
  376. end
  377. else
  378. begin
  379. corrclass:=jvmgetcorrespondingclassdef(pvs.vardef);
  380. if pvs.vardef.typ in [orddef,floatdef] then
  381. begin
  382. { get the class representing the primitive type }
  383. fvs:=search_struct_member(tobjectdef(corrclass),'FTYPE');
  384. newpara:=nil;
  385. if not handle_staticfield_access(fvs,false,newpara) then
  386. internalerror(2011072417);
  387. end
  388. else
  389. newpara:=cloadvmtaddrnode.create(ctypenode.create(corrclass));
  390. newpara:=ctypeconvnode.create_explicit(newpara,jlclass);
  391. end;
  392. procdefparas:=carrayconstructornode.create(newpara,procdefparas);
  393. end;
  394. if not assigned(procdefparas) then
  395. procdefparas:=carrayconstructornode.create(nil,nil);
  396. constrparas:=ccallparanode.create(procdefparas,constrparas);
  397. result:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(tprocvardef(resultdef).classdef)),'CREATE',constrparas);
  398. { typecast to the procvar type }
  399. if tprocvardef(resultdef).is_addressonly then
  400. result:=ctypeconvnode.create_explicit(result,resultdef)
  401. else
  402. begin
  403. result:=ctypeconvnode.create_explicit(result,getpointerdef(resultdef));
  404. result:=cderefnode.create(result)
  405. end;
  406. { reused }
  407. tloadnode(left).left:=nil;
  408. end;
  409. {*****************************************************************************
  410. SecondTypeConv
  411. *****************************************************************************}
  412. procedure tjvmtypeconvnode.second_int_to_int;
  413. var
  414. ressize,
  415. leftsize : longint;
  416. begin
  417. { insert range check if not explicit conversion }
  418. if not(nf_explicit in flags) then
  419. hlcg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
  420. { is the result size smaller? when typecasting from void
  421. we always reuse the current location, because there is
  422. nothing that we can load in a register }
  423. ressize:=resultdef.size;
  424. leftsize :=left.resultdef.size;
  425. if ((ressize<>leftsize) or
  426. ((location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  427. (location.reference.arrayreftype<>art_none) and
  428. (is_widechar(left.resultdef)<>is_widechar(resultdef))) or
  429. is_bitpacked_access(left)) and
  430. not is_void(left.resultdef) then
  431. begin
  432. location_copy(location,left.location);
  433. { reuse a loc_reference when the newsize is larger than
  434. than the original and 4 bytes, because all <= 4 byte loads will
  435. result in a stack slot that occupies 4 bytes.
  436. Except
  437. a) for arrays (they use different load instructions for
  438. differently sized data types) or symbols (idem)
  439. b) when going from 4 to 8 bytes, because these are different
  440. data types
  441. }
  442. if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  443. not assigned(location.reference.symbol) and
  444. (location.reference.arrayreftype=art_none) and
  445. (ressize>leftsize) and
  446. (ressize=4) then
  447. begin
  448. location.size:=def_cgsize(resultdef);
  449. { no adjustment of the offset even though Java is big endian,
  450. because the load instruction will remain the same }
  451. end
  452. else
  453. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,false);
  454. end
  455. else
  456. begin
  457. if (ressize < sizeof(aint)) and
  458. (def_cgsize(left.resultdef)<>def_cgsize(resultdef)) then
  459. begin
  460. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  461. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  462. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location,location.register);
  463. end
  464. else
  465. location_copy(location,left.location);
  466. end;
  467. end;
  468. procedure tjvmtypeconvnode.second_int_to_real;
  469. var
  470. srcsize, ressize: longint;
  471. procedure convertsignedstackloc;
  472. begin
  473. case srcsize of
  474. 4:
  475. case ressize of
  476. 4:
  477. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2f));
  478. 8:
  479. begin
  480. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2d));
  481. thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
  482. end;
  483. else
  484. internalerror(2011010601);
  485. end;
  486. 8:
  487. case ressize of
  488. 4:
  489. begin
  490. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2f));
  491. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  492. end;
  493. 8:
  494. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2d));
  495. else
  496. internalerror(2011010602);
  497. end;
  498. else
  499. internalerror(2011010603);
  500. end;
  501. end;
  502. var
  503. signeddef : tdef;
  504. l1 : tasmlabel;
  505. begin
  506. srcsize:=left.resultdef.size;
  507. ressize:=resultdef.size;
  508. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  509. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  510. { first always convert as if it's a signed number }
  511. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  512. convertsignedstackloc;
  513. if not is_signed(left.resultdef) then
  514. begin
  515. { if it was unsigned, add high(cardinal)+1/high(qword)+1 in case
  516. the signed interpretation is < 0 }
  517. current_asmdata.getjumplabel(l1);
  518. if srcsize=4 then
  519. signeddef:=s32inttype
  520. else
  521. signeddef:=s64inttype;
  522. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,signeddef,OC_GTE,0,left.location,l1);
  523. if srcsize=4 then
  524. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,4294967296.0)
  525. else
  526. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,18446744073709551616.0);
  527. if ressize=4 then
  528. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_fadd))
  529. else
  530. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dadd));
  531. hlcg.a_label(current_asmdata.CurrAsmList,l1);
  532. end;
  533. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  534. end;
  535. procedure tjvmtypeconvnode.second_proc_to_procvar;
  536. begin
  537. internalerror(2011072506);
  538. end;
  539. procedure tjvmtypeconvnode.second_bool_to_int;
  540. var
  541. newsize: tcgsize;
  542. oldTrueLabel,oldFalseLabel : tasmlabel;
  543. begin
  544. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  545. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  546. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  547. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  548. secondpass(left);
  549. location_copy(location,left.location);
  550. newsize:=def_cgsize(resultdef);
  551. { byte(bytebool) or word(wordbool) or longint(longbool) must be }
  552. { accepted for var parameters and assignments, and must not }
  553. { change the ordinal value or value location. }
  554. { htypechk.valid_for_assign ensures that such locations with a }
  555. { size<sizeof(register) cannot be LOC_CREGISTER (they otherwise }
  556. { could be in case of a plain assignment), and LOC_REGISTER can }
  557. { never be an assignment target. The remaining LOC_REGISTER/ }
  558. { LOC_CREGISTER locations do have to be sign/zero-extended. }
  559. { -- Note: this does not work for Java and 2/4 byte sized
  560. values, because bytebool/wordbool are signed and
  561. are stored in 4 byte locations -> will result in
  562. "byte" with the value high(cardinal); see remark
  563. in second_int_to_int above regarding consequences }
  564. if not(nf_explicit in flags) or
  565. (location.loc in [LOC_FLAGS,LOC_JUMP]) or
  566. ((newsize<>left.location.size) and
  567. ((left.resultdef.size<>resultdef.size) or
  568. not(left.resultdef.size in [4,8]))
  569. ) then
  570. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  571. else
  572. { may differ in sign, e.g. bytebool -> byte }
  573. location.size:=newsize;
  574. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  575. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  576. end;
  577. procedure tjvmtypeconvnode.second_int_to_bool;
  578. var
  579. hlabel1,hlabel2,oldTrueLabel,oldFalseLabel : tasmlabel;
  580. newsize : tcgsize;
  581. begin
  582. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  583. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  584. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  585. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  586. secondpass(left);
  587. if codegenerror then
  588. exit;
  589. { Explicit typecasts from any ordinal type to a boolean type }
  590. { must not change the ordinal value }
  591. if (nf_explicit in flags) and
  592. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
  593. begin
  594. location_copy(location,left.location);
  595. newsize:=def_cgsize(resultdef);
  596. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  597. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  598. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  599. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  600. else
  601. location.size:=newsize;
  602. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  603. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  604. exit;
  605. end;
  606. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  607. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  608. current_asmdata.getjumplabel(hlabel2);
  609. case left.location.loc of
  610. LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
  611. begin
  612. current_asmdata.getjumplabel(hlabel1);
  613. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location,hlabel1);
  614. end;
  615. LOC_JUMP :
  616. begin
  617. hlabel1:=current_procinfo.CurrFalseLabel;
  618. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  619. end;
  620. else
  621. internalerror(10062);
  622. end;
  623. if not(is_cbool(resultdef)) then
  624. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,1,R_INTREGISTER)
  625. else
  626. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,-1,R_INTREGISTER);
  627. { we jump over the next constant load -> they don't appear on the
  628. stack simulataneously }
  629. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  630. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel2);
  631. hlcg.a_label(current_asmdata.CurrAsmList,hlabel1);
  632. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,0,R_INTREGISTER);
  633. hlcg.a_label(current_asmdata.CurrAsmList,hlabel2);
  634. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  635. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  636. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  637. end;
  638. procedure tjvmtypeconvnode.second_elem_to_openarray;
  639. var
  640. primitivetype: boolean;
  641. opc: tasmop;
  642. mangledname: string;
  643. basereg: tregister;
  644. arrayref: treference;
  645. begin
  646. { create an array with one element of the required type }
  647. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s32inttype,1,R_INTREGISTER);
  648. mangledname:=jvmarrtype(left.resultdef,primitivetype);
  649. if primitivetype then
  650. opc:=a_newarray
  651. else
  652. opc:=a_anewarray;
  653. { doesn't change stack height: one int replaced by one reference }
  654. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opc,current_asmdata.RefAsmSymbol(mangledname)));
  655. { store the data in the newly created array }
  656. basereg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
  657. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,java_jlobject,basereg);
  658. reference_reset_base(arrayref,basereg,0,4);
  659. arrayref.arrayreftype:=art_indexconst;
  660. arrayref.indexoffset:=0;
  661. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location,arrayref);
  662. location_reset_ref(location,LOC_REFERENCE,OS_ADDR,4);
  663. tg.gethltemp(current_asmdata.CurrAsmList,java_jlobject,4,tt_normal,location.reference);
  664. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,java_jlobject,java_jlobject,basereg,location.reference);
  665. end;
  666. procedure get_most_nested_types(var fromdef, todef: tdef);
  667. begin
  668. while is_dynamic_array(fromdef) and
  669. is_dynamic_array(todef) do
  670. begin
  671. fromdef:=tarraydef(fromdef).elementdef;
  672. todef:=tarraydef(todef).elementdef;
  673. end;
  674. fromdef:=maybe_find_real_class_definition(fromdef,false);
  675. todef:=maybe_find_real_class_definition(todef,false);
  676. end;
  677. function tjvmtypeconvnode.do_target_specific_explicit_typeconv(check_only: boolean; out resnode: tnode): boolean;
  678. { handle explicit typecast from int to to real or vice versa }
  679. function int_real_explicit_typecast(fdef: tfloatdef; const singlemethod, doublemethod: string): tnode;
  680. var
  681. csym: ttypesym;
  682. psym: tsym;
  683. begin
  684. { use the float/double to raw bits methods to get the bit pattern }
  685. if fdef.floattype=s32real then
  686. begin
  687. csym:=search_system_type('JLFLOAT');
  688. psym:=search_struct_member(tobjectdef(csym.typedef),singlemethod);
  689. end
  690. else
  691. begin
  692. csym:=search_system_type('JLDOUBLE');
  693. psym:=search_struct_member(tobjectdef(csym.typedef),doublemethod);
  694. end;
  695. if not assigned(psym) or
  696. (psym.typ<>procsym) then
  697. internalerror(2011012901);
  698. { call the (static class) method to get the raw bits }
  699. result:=ccallnode.create(ccallparanode.create(left,nil),
  700. tprocsym(psym),psym.owner,
  701. cloadvmtaddrnode.create(ctypenode.create(csym.typedef)),[]);
  702. { convert the result to the result type of this type conversion node }
  703. inserttypeconv_explicit(result,resultdef);
  704. { left is reused }
  705. left:=nil;
  706. end;
  707. function ord_enum_explicit_typecast(fdef: torddef; todef: tenumdef): tnode;
  708. var
  709. psym: tsym;
  710. begin
  711. { we only create a class for the basedefs }
  712. todef:=todef.getbasedef;
  713. psym:=search_struct_member(todef.classdef,'FPCVALUEOF');
  714. if not assigned(psym) or
  715. (psym.typ<>procsym) then
  716. internalerror(2011062601);
  717. result:=ccallnode.create(ccallparanode.create(left,nil),
  718. tprocsym(psym),psym.owner,
  719. cloadvmtaddrnode.create(ctypenode.create(todef.classdef)),[]);
  720. { convert the result to the result type of this type conversion node }
  721. inserttypeconv_explicit(result,resultdef);
  722. { left is reused }
  723. left:=nil;
  724. end;
  725. function enum_ord_explicit_typecast(fdef: tenumdef; todef: torddef): tnode;
  726. var
  727. psym: tsym;
  728. begin
  729. { we only create a class for the basedef }
  730. fdef:=fdef.getbasedef;
  731. psym:=search_struct_member(fdef.classdef,'FPCORDINAL');
  732. if not assigned(psym) or
  733. (psym.typ<>procsym) then
  734. internalerror(2011062602);
  735. result:=ccallnode.create(nil,tprocsym(psym),psym.owner,left,[]);
  736. { convert the result to the result type of this type conversion node }
  737. inserttypeconv_explicit(result,resultdef);
  738. { left is reused }
  739. left:=nil;
  740. end;
  741. function from_set_explicit_typecast: tnode;
  742. var
  743. helpername: string;
  744. setconvdef: tdef;
  745. begin
  746. if tsetdef(left.resultdef).elementdef.typ=enumdef then
  747. begin
  748. setconvdef:=java_juenumset;
  749. helpername:='fpc_enumset_to_'
  750. end
  751. else
  752. begin
  753. setconvdef:=java_jubitset;
  754. helpername:='fpc_bitset_to_'
  755. end;
  756. if left.resultdef.size<=4 then
  757. helpername:=helpername+'int'
  758. else
  759. helpername:=helpername+'long';
  760. result:=ccallnode.createintern(helpername,ccallparanode.create(
  761. genintconstnode(left.resultdef.size),ccallparanode.create(genintconstnode(tsetdef(left.resultdef).setbase),
  762. ccallparanode.create(ctypeconvnode.create_explicit(left,setconvdef),nil))));
  763. left:=nil;
  764. end;
  765. function to_set_explicit_typecast: tnode;
  766. var
  767. enumclassdef: tobjectdef;
  768. mp: tnode;
  769. helpername: string;
  770. begin
  771. if tsetdef(resultdef).elementdef.typ=enumdef then
  772. begin
  773. inserttypeconv_explicit(left,s64inttype);
  774. enumclassdef:=tenumdef(tsetdef(resultdef).elementdef).getbasedef.classdef;
  775. mp:=cloadvmtaddrnode.create(ctypenode.create(enumclassdef));
  776. helpername:='fpcLongToEnumSet';
  777. { enumclass.fpcLongToEnumSet(left,setbase,setsize) }
  778. result:=ccallnode.createinternmethod(mp,helpername,
  779. ccallparanode.create(genintconstnode(resultdef.size),
  780. ccallparanode.create(genintconstnode(tsetdef(resultdef).setbase),
  781. ccallparanode.create(left,nil))));
  782. end
  783. else
  784. begin
  785. if left.resultdef.size<=4 then
  786. begin
  787. helpername:='fpc_int_to_bitset';
  788. inserttypeconv_explicit(left,s32inttype);
  789. end
  790. else
  791. begin
  792. helpername:='fpc_long_to_bitset';
  793. inserttypeconv_explicit(left,s64inttype);
  794. end;
  795. result:=ccallnode.createintern(helpername,
  796. ccallparanode.create(genintconstnode(resultdef.size),
  797. ccallparanode.create(genintconstnode(tsetdef(resultdef).setbase),
  798. ccallparanode.create(left,nil))));
  799. end;
  800. end;
  801. function procvar_to_procvar(fromdef, todef: tdef): tnode;
  802. var
  803. fsym: tsym;
  804. begin
  805. result:=nil;
  806. if fromdef=todef then
  807. exit;
  808. fsym:=tfieldvarsym(search_struct_member(tprocvardef(fromdef).classdef,'METHOD'));
  809. if not assigned(fsym) or
  810. (fsym.typ<>fieldvarsym) then
  811. internalerror(2011072414);
  812. { can either be a procvar or a procvarclass }
  813. if fromdef.typ=procvardef then
  814. begin
  815. left:=ctypeconvnode.create_explicit(left,tprocvardef(fromdef).classdef);
  816. include(left.flags,nf_load_procvar);
  817. typecheckpass(left);
  818. end;
  819. result:=csubscriptnode.create(fsym,left);
  820. { create destination procvartype with info from source }
  821. result:=ccallnode.createinternmethod(
  822. cloadvmtaddrnode.create(ctypenode.create(tprocvardef(todef).classdef)),
  823. 'CREATE',ccallparanode.create(result,nil));
  824. left:=nil;
  825. end;
  826. function procvar_to_tmethod(fromdef, todef: tdef): tnode;
  827. var
  828. fsym: tsym;
  829. begin
  830. { must be procedure-of-object -> implicit pointer type -> get address
  831. before typecasting to corresponding classdef }
  832. left:=caddrnode.create_internal(left);
  833. inserttypeconv_explicit(left,tprocvardef(fromdef).classdef);
  834. fsym:=tfieldvarsym(search_struct_member(tprocvardef(fromdef).classdef,'METHOD'));
  835. if not assigned(fsym) or
  836. (fsym.typ<>fieldvarsym) then
  837. internalerror(2011072414);
  838. result:=csubscriptnode.create(fsym,left);
  839. left:=nil;
  840. end;
  841. function tmethod_to_procvar(fromdef, todef: tdef): tnode;
  842. var
  843. fsym: tsym;
  844. begin
  845. fsym:=tfieldvarsym(search_struct_member(tprocvardef(todef).classdef,'METHOD'));
  846. if not assigned(fsym) or
  847. (fsym.typ<>fieldvarsym) then
  848. internalerror(2011072415);
  849. result:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(tprocvardef(todef).classdef)),
  850. 'CREATE',ccallparanode.create(left,nil));
  851. left:=nil;
  852. end;
  853. function ptr_no_typecheck_required(fromdef, todef: tdef): boolean;
  854. function check_type_equality(def1,def2: tdef): boolean;
  855. begin
  856. result:=true;
  857. if is_ansistring(def1) and
  858. (def2=java_ansistring) then
  859. exit;
  860. if is_wide_or_unicode_string(def1) and
  861. (def2=java_jlstring) then
  862. exit;
  863. if def1.typ=pointerdef then
  864. begin
  865. if is_shortstring(tpointerdef(def1).pointeddef) and
  866. (def2=java_shortstring) then
  867. exit;
  868. { pointer-to-set to JUEnumSet/JUBitSet }
  869. if (tpointerdef(def1).pointeddef.typ=setdef) then
  870. begin
  871. if not assigned(tsetdef(tpointerdef(def1).pointeddef).elementdef) then
  872. begin
  873. if (def2=java_jubitset) or
  874. (def2=java_juenumset) then
  875. exit;
  876. end
  877. else if tsetdef(tpointerdef(def1).pointeddef).elementdef.typ=enumdef then
  878. begin
  879. if def2=java_juenumset then
  880. exit;
  881. end
  882. else if def2=java_jubitset then
  883. exit;
  884. end;
  885. end;
  886. result:=false;
  887. end;
  888. function check_array_type_equality(def1,def2: tdef): boolean;
  889. begin
  890. result:=true;
  891. if is_shortstring(def1) and
  892. (def2=java_shortstring) then
  893. exit;
  894. result:=false;
  895. end;
  896. begin
  897. result:=true;
  898. { check procvar conversion compatibility via their classes }
  899. if fromdef.typ=procvardef then
  900. fromdef:=tprocvardef(fromdef).classdef;
  901. if todef.typ=procvardef then
  902. todef:=tprocvardef(todef).classdef;
  903. if (todef=java_jlobject) or
  904. (todef=voidpointertype) then
  905. exit;
  906. if compare_defs(fromdef,todef,nothingn)>=te_equal then
  907. exit;
  908. { trecorddef.is_related() must work for inheritance/method checking,
  909. but do not allow records to be directly typecasted into class/
  910. pointer types (you have to use FpcBaseRecordType(@rec) instead) }
  911. if not is_record(fromdef) and
  912. fromdef.is_related(todef) then
  913. exit;
  914. if check_type_equality(fromdef,todef) then
  915. exit;
  916. if check_type_equality(todef,fromdef) then
  917. exit;
  918. if (fromdef.typ=pointerdef) and
  919. (tpointerdef(fromdef).pointeddef.typ=recorddef) and
  920. (todef=java_fpcbaserecordtype) then
  921. exit;
  922. { all classrefs are currently java.lang.Class at the bytecode level }
  923. if (fromdef.typ=classrefdef) and
  924. (todef.typ=objectdef) and
  925. (todef=search_system_type('JLCLASS').typedef) then
  926. exit;
  927. if (fromdef.typ=classrefdef) and
  928. (todef.typ=classrefdef) and
  929. tclassrefdef(fromdef).pointeddef.is_related(tclassrefdef(todef).pointeddef) then
  930. exit;
  931. { special case: "array of shortstring" to "array of ShortstringClass"
  932. and "array of <record>" to "array of FpcRecordBaseType" (normally
  933. you have to use ShortstringClass(@shortstrvar) etc, but that's not
  934. possible in case of passing arrays to e.g. setlength) }
  935. if is_dynamic_array(left.resultdef) and
  936. is_dynamic_array(resultdef) then
  937. begin
  938. if check_array_type_equality(fromdef,todef) or
  939. check_array_type_equality(todef,fromdef) then
  940. exit;
  941. if is_record(fromdef) and
  942. (todef=java_fpcbaserecordtype) then
  943. exit;
  944. end;
  945. result:=false;
  946. end;
  947. var
  948. fromclasscompatible,
  949. toclasscompatible: boolean;
  950. fromdef,
  951. todef: tdef;
  952. fromarrtype,
  953. toarrtype: char;
  954. begin
  955. resnode:=nil;
  956. if not(convtype in [tc_equal,tc_int_2_int,tc_int_2_bool,tc_bool_2_int,tc_class_2_intf]) or
  957. ((convtype in [tc_equal,tc_int_2_int,tc_bool_2_int,tc_int_2_bool]) and
  958. ((left.resultdef.typ=orddef) and
  959. (resultdef.typ=orddef))) then
  960. begin
  961. result:=false;
  962. exit
  963. end;
  964. { This routine is only called for explicit typeconversions of same-sized
  965. entities that aren't handled by normal type conversions -> bit pattern
  966. reinterpretations. In the JVM, many of these also need special
  967. handling because of the type safety. }
  968. { don't allow conversions between object-based and non-object-based
  969. types }
  970. fromclasscompatible:=
  971. (left.resultdef.typ=formaldef) or
  972. (left.resultdef.typ=pointerdef) or
  973. is_java_class_or_interface(left.resultdef) or
  974. is_dynamic_array(left.resultdef) or
  975. ((left.resultdef.typ in [stringdef,classrefdef]) and
  976. not is_shortstring(left.resultdef)) or
  977. (left.resultdef.typ=enumdef) or
  978. { procvar2procvar needs special handling }
  979. ((left.resultdef.typ=procvardef) and
  980. tprocvardef(left.resultdef).is_addressonly and
  981. (resultdef.typ<>procvardef));
  982. toclasscompatible:=
  983. (resultdef.typ=pointerdef) or
  984. is_java_class_or_interface(resultdef) or
  985. is_dynamic_array(resultdef) or
  986. ((resultdef.typ in [stringdef,classrefdef]) and
  987. not is_shortstring(resultdef)) or
  988. (resultdef.typ=enumdef) or
  989. ((resultdef.typ=procvardef) and
  990. tprocvardef(resultdef).is_addressonly);
  991. { typescasts from void (the result of untyped_ptr^) to an implicit
  992. pointertype (record, array, ...) also needs a typecheck }
  993. if is_void(left.resultdef) and
  994. jvmimplicitpointertype(resultdef) then
  995. begin
  996. fromclasscompatible:=true;
  997. toclasscompatible:=true;
  998. end;
  999. if fromclasscompatible and toclasscompatible then
  1000. begin
  1001. { we need an as-node to check the validity of the conversion (since
  1002. it wasn't handled by another type conversion, we know it can't
  1003. have been valid normally)
  1004. Exceptions: (most nested) destination is
  1005. * java.lang.Object, since everything is compatible with that type
  1006. * related to source
  1007. * a primitive that are represented by the same type in Java
  1008. (e.g., byte and shortint) }
  1009. { in case of arrays, check the compatibility of the innermost types }
  1010. fromdef:=left.resultdef;
  1011. todef:=resultdef;
  1012. get_most_nested_types(fromdef,todef);
  1013. { in case of enums, get the equivalent class definitions }
  1014. if (fromdef.typ=enumdef) then
  1015. fromdef:=tenumdef(fromdef).getbasedef;
  1016. if (todef.typ=enumdef) then
  1017. todef:=tenumdef(todef).getbasedef;
  1018. fromarrtype:=jvmarrtype_setlength(fromdef);
  1019. toarrtype:=jvmarrtype_setlength(todef);
  1020. if not ptr_no_typecheck_required(fromdef,todef) then
  1021. begin
  1022. if (fromarrtype in ['A','R','T','E','L','P']) or
  1023. (fromarrtype<>toarrtype) then
  1024. begin
  1025. if not check_only and
  1026. not assignment_side then
  1027. begin
  1028. resnode:=ctypenode.create(resultdef);
  1029. if resultdef.typ=objectdef then
  1030. resnode:=cloadvmtaddrnode.create(resnode);
  1031. resnode:=casnode.create_internal(left,resnode);
  1032. if resultdef.typ=classrefdef then
  1033. tjvmasnode(resnode).classreftypecast:=true;
  1034. left:=nil;
  1035. end
  1036. end
  1037. { typecasting from a child to a parent type on the assignment side
  1038. will (rightly) mess up the type safety verification of the JVM }
  1039. else if assignment_side then
  1040. CGMessage(type_e_no_managed_assign_generic_typecast);
  1041. end;
  1042. result:=true;
  1043. exit;
  1044. end;
  1045. { a formaldef can be converted to anything, but not on the assignment
  1046. side }
  1047. if (left.resultdef.typ=formaldef) and
  1048. not assignment_side then
  1049. begin
  1050. if resultdef.typ in [orddef,floatdef] then
  1051. begin
  1052. if not check_only then
  1053. begin
  1054. resnode:=cinlinenode.create(in_unbox_x_y,false,
  1055. ccallparanode.create(ctypenode.create(resultdef),
  1056. ccallparanode.create(left,nil)));
  1057. left:=nil;
  1058. end;
  1059. result:=true;
  1060. exit;
  1061. end
  1062. else if jvmimplicitpointertype(resultdef) then
  1063. begin
  1064. { typecast formaldef to pointer to the type, then deref, so that
  1065. a proper checkcast is inserted }
  1066. if not check_only then
  1067. begin
  1068. resnode:=ctypeconvnode.create_explicit(left,getpointerdef(resultdef));
  1069. resnode:=cderefnode.create(resnode);
  1070. left:=nil;
  1071. end;
  1072. result:=true;
  1073. exit;
  1074. end;
  1075. result:=false;
  1076. exit;
  1077. end;
  1078. { procvar to tmethod and vice versa, and procvar to procvar }
  1079. if isvalidprocvartypeconv(left.resultdef,resultdef) then
  1080. begin
  1081. if not check_only then
  1082. begin
  1083. if (left.resultdef.typ=procvardef) and
  1084. (resultdef.typ=procvardef) then
  1085. resnode:=procvar_to_procvar(left.resultdef,resultdef)
  1086. else if left.resultdef.typ=procvardef then
  1087. resnode:=procvar_to_tmethod(left.resultdef,resultdef)
  1088. else
  1089. resnode:=tmethod_to_procvar(left.resultdef,resultdef);
  1090. end;
  1091. result:=true;
  1092. exit;
  1093. end;
  1094. { don't allow conversions between different classes of primitive types,
  1095. except for a few special cases }
  1096. { float to int/enum explicit type conversion: get the bits }
  1097. if (left.resultdef.typ=floatdef) and
  1098. (is_integer(resultdef) or
  1099. (resultdef.typ=enumdef)) then
  1100. begin
  1101. if not check_only then
  1102. resnode:=int_real_explicit_typecast(tfloatdef(left.resultdef),'FLOATTORAWINTBITS','DOUBLETORAWLONGBITS');
  1103. result:=true;
  1104. exit;
  1105. end;
  1106. { int to float explicit type conversion: also use the bits }
  1107. if (is_integer(left.resultdef) or
  1108. (left.resultdef.typ=enumdef)) and
  1109. (resultdef.typ=floatdef) then
  1110. begin
  1111. if not check_only then
  1112. begin
  1113. if (left.resultdef.typ=enumdef) then
  1114. inserttypeconv_explicit(left,s32inttype);
  1115. resnode:=int_real_explicit_typecast(tfloatdef(resultdef),'INTBITSTOFLOAT','LONGBITSTODOUBLE');
  1116. end;
  1117. result:=true;
  1118. exit;
  1119. end;
  1120. { enums }
  1121. if (left.resultdef.typ=enumdef) or
  1122. (resultdef.typ=enumdef) then
  1123. begin
  1124. { both enum? }
  1125. if (resultdef.typ=left.resultdef.typ) then
  1126. begin
  1127. { same base type -> nothing special }
  1128. fromdef:=tenumdef(left.resultdef).getbasedef;
  1129. todef:=tenumdef(resultdef).getbasedef;
  1130. if fromdef=todef then
  1131. begin
  1132. result:=false;
  1133. exit;
  1134. end;
  1135. { convert via ordinal intermediate }
  1136. if not check_only then
  1137. begin;
  1138. inserttypeconv_explicit(left,s32inttype);
  1139. inserttypeconv_explicit(left,resultdef);
  1140. resnode:=left;
  1141. left:=nil
  1142. end;
  1143. result:=true;
  1144. exit;
  1145. end;
  1146. { enum to orddef & vice versa }
  1147. if left.resultdef.typ=orddef then
  1148. begin
  1149. if not check_only then
  1150. resnode:=ord_enum_explicit_typecast(torddef(left.resultdef),tenumdef(resultdef));
  1151. result:=true;
  1152. exit;
  1153. end
  1154. else if resultdef.typ=orddef then
  1155. begin
  1156. if not check_only then
  1157. resnode:=enum_ord_explicit_typecast(tenumdef(left.resultdef),torddef(resultdef));
  1158. result:=true;
  1159. exit;
  1160. end
  1161. end;
  1162. { sets }
  1163. if (left.resultdef.typ=setdef) or
  1164. (resultdef.typ=setdef) then
  1165. begin
  1166. { set -> ord/enum/other-set-type }
  1167. if (resultdef.typ in [orddef,enumdef]) then
  1168. begin
  1169. if not check_only then
  1170. begin
  1171. resnode:=from_set_explicit_typecast;
  1172. { convert to desired result }
  1173. inserttypeconv_explicit(resnode,resultdef);
  1174. end;
  1175. result:=true;
  1176. exit;
  1177. end
  1178. { ord/enum -> set }
  1179. else if (left.resultdef.typ in [orddef,enumdef]) then
  1180. begin
  1181. if not check_only then
  1182. begin
  1183. resnode:=to_set_explicit_typecast;
  1184. { convert to desired result }
  1185. inserttypeconv_explicit(resnode,getpointerdef(resultdef));
  1186. resnode:=cderefnode.create(resnode);
  1187. end;
  1188. result:=true;
  1189. exit;
  1190. end;
  1191. { if someone needs it, float->set and set->float explicit typecasts
  1192. could also be added (cannot be handled by the above, because
  1193. float(intvalue) will convert rather than re-interpret the value) }
  1194. end;
  1195. { anything not explicitly handled is a problem }
  1196. result:=true;
  1197. CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
  1198. end;
  1199. function tjvmtypeconvnode.target_specific_explicit_typeconv: boolean;
  1200. var
  1201. dummyres: tnode;
  1202. begin
  1203. result:=do_target_specific_explicit_typeconv(true,dummyres);
  1204. end;
  1205. function tjvmtypeconvnode.target_specific_general_typeconv: boolean;
  1206. begin
  1207. result:=false;
  1208. { on the JVM platform, enums can always be converted to class instances,
  1209. because enums /are/ class instances there. To prevent the
  1210. typechecking/conversion code from assuming it can treat it like any
  1211. ordinal constant, firstpass() it so that the ordinal constant gets
  1212. replaced with a load of a staticvarsym. This is not done in
  1213. pass_typecheck, because that would prevent many optimizations }
  1214. if (left.nodetype=ordconstn) and
  1215. (left.resultdef.typ=enumdef) and
  1216. (resultdef.typ=objectdef) then
  1217. firstpass(left);
  1218. end;
  1219. {*****************************************************************************
  1220. AsNode and IsNode common helpers
  1221. *****************************************************************************}
  1222. function asis_target_specific_typecheck(node: tasisnode): boolean;
  1223. var
  1224. realtodef: tdef;
  1225. begin
  1226. if not(nf_internal in node.flags) then
  1227. begin
  1228. { handle using normal code }
  1229. result:=false;
  1230. exit;
  1231. end;
  1232. result:=true;
  1233. { these are converted type conversion nodes, to insert the checkcast
  1234. operations }
  1235. realtodef:=node.right.resultdef;
  1236. if (realtodef.typ=classrefdef) and
  1237. ((node.nodetype<>asn) or
  1238. not tjvmasnode(node).classreftypecast) then
  1239. realtodef:=tclassrefdef(realtodef).pointeddef;
  1240. realtodef:=maybe_find_real_class_definition(realtodef,false);
  1241. if result then
  1242. if node.nodetype=asn then
  1243. node.resultdef:=realtodef
  1244. else
  1245. node.resultdef:=pasbool8type;
  1246. end;
  1247. function asis_pass_1(node: tasisnode; const methodname: string): tnode;
  1248. var
  1249. ps: tsym;
  1250. call: tnode;
  1251. jlclass: tobjectdef;
  1252. begin
  1253. result:=nil;
  1254. firstpass(node.left);
  1255. if not(node.right.nodetype in [typen,loadvmtaddrn]) then
  1256. begin
  1257. if (node.nodetype=isn) or
  1258. not assigned(tasnode(node).call) then
  1259. begin
  1260. if not is_javaclassref(node.right.resultdef) then
  1261. internalerror(2011041920);
  1262. firstpass(node.right);
  1263. jlclass:=tobjectdef(search_system_type('JLCLASS').typedef);
  1264. ps:=search_struct_member(jlclass,methodname);
  1265. if not assigned(ps) or
  1266. (ps.typ<>procsym) then
  1267. internalerror(2011041910);
  1268. call:=ccallnode.create(ccallparanode.create(node.left,nil),tprocsym(ps),ps.owner,ctypeconvnode.create_explicit(node.right,jlclass),[]);
  1269. node.left:=nil;
  1270. node.right:=nil;
  1271. firstpass(call);
  1272. if codegenerror then
  1273. exit;
  1274. if node.nodetype=isn then
  1275. result:=call
  1276. else
  1277. begin
  1278. tasnode(node).call:=call;
  1279. node.expectloc:=call.expectloc;
  1280. end;
  1281. end;
  1282. end
  1283. else
  1284. begin
  1285. node.expectloc:=LOC_REGISTER;
  1286. result:=nil;
  1287. end;
  1288. end;
  1289. function asis_generate_code(node: tasisnode; opcode: tasmop): boolean;
  1290. var
  1291. checkdef: tdef;
  1292. begin
  1293. if (node.nodetype=asn) and
  1294. assigned(tasnode(node).call) then
  1295. begin
  1296. result:=false;
  1297. exit;
  1298. end;
  1299. result:=true;
  1300. secondpass(node.left);
  1301. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,node.left.resultdef,node.left.location);
  1302. location_freetemp(current_asmdata.CurrAsmList,node.left.location);
  1303. { Perform a checkcast instruction, which will raise an exception in case
  1304. the actual type does not match/inherit from the expected type.
  1305. Object types need the full type name (package+class name), arrays only
  1306. the array definition }
  1307. if node.nodetype=asn then
  1308. checkdef:=node.resultdef
  1309. else if node.right.resultdef.typ=classrefdef then
  1310. checkdef:=tclassrefdef(node.right.resultdef).pointeddef
  1311. else
  1312. checkdef:=node.right.resultdef;
  1313. { replace special types with their equivalent class type }
  1314. if (checkdef.typ=pointerdef) and
  1315. jvmimplicitpointertype(tpointerdef(checkdef).pointeddef) then
  1316. checkdef:=tpointerdef(checkdef).pointeddef;
  1317. if (checkdef=voidpointertype) or
  1318. (checkdef.typ=formaldef) then
  1319. checkdef:=java_jlobject
  1320. else if checkdef.typ=enumdef then
  1321. checkdef:=tenumdef(checkdef).classdef
  1322. else if checkdef.typ=setdef then
  1323. begin
  1324. if tsetdef(checkdef).elementdef.typ=enumdef then
  1325. checkdef:=java_juenumset
  1326. else
  1327. checkdef:=java_jubitset;
  1328. end
  1329. else if checkdef.typ=procvardef then
  1330. checkdef:=tprocvardef(checkdef).classdef
  1331. else if is_wide_or_unicode_string(checkdef) then
  1332. checkdef:=java_jlstring
  1333. else if is_ansistring(checkdef) then
  1334. checkdef:=java_ansistring
  1335. else if is_shortstring(checkdef) then
  1336. checkdef:=java_shortstring;
  1337. if checkdef.typ in [objectdef,recorddef] then
  1338. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
  1339. else if checkdef.typ=classrefdef then
  1340. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol('java/lang/Class')))
  1341. else
  1342. current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef,false))));
  1343. location_reset(node.location,LOC_REGISTER,OS_ADDR);
  1344. node.location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,node.resultdef);
  1345. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,node.resultdef,node.location.register);
  1346. end;
  1347. {*****************************************************************************
  1348. TJVMAsNode
  1349. *****************************************************************************}
  1350. function tjvmasnode.target_specific_typecheck: boolean;
  1351. begin
  1352. result:=asis_target_specific_typecheck(self);
  1353. end;
  1354. function tjvmasnode.pass_1: tnode;
  1355. begin
  1356. result:=asis_pass_1(self,'CAST');
  1357. end;
  1358. procedure tjvmasnode.pass_generate_code;
  1359. begin
  1360. if not asis_generate_code(self,a_checkcast) then
  1361. inherited;
  1362. end;
  1363. function tjvmasnode.dogetcopy: tnode;
  1364. begin
  1365. result:=inherited dogetcopy;
  1366. tjvmasnode(result).classreftypecast:=classreftypecast;
  1367. end;
  1368. function tjvmasnode.docompare(p: tnode): boolean;
  1369. begin
  1370. result:=
  1371. inherited docompare(p) and
  1372. (tjvmasnode(p).classreftypecast=classreftypecast);
  1373. end;
  1374. constructor tjvmasnode.ppuload(t: tnodetype; ppufile: tcompilerppufile);
  1375. begin
  1376. inherited;
  1377. classreftypecast:=boolean(ppufile.getbyte);
  1378. end;
  1379. procedure tjvmasnode.ppuwrite(ppufile: tcompilerppufile);
  1380. begin
  1381. inherited ppuwrite(ppufile);
  1382. ppufile.putbyte(byte(classreftypecast));
  1383. end;
  1384. {*****************************************************************************
  1385. TJVMIsNode
  1386. *****************************************************************************}
  1387. function tjvmisnode.target_specific_typecheck: boolean;
  1388. begin
  1389. result:=asis_target_specific_typecheck(self);
  1390. end;
  1391. function tjvmisnode.pass_1: tnode;
  1392. begin
  1393. result:=asis_pass_1(self,'ISINSTANCE');
  1394. end;
  1395. procedure tjvmisnode.pass_generate_code;
  1396. begin
  1397. if not asis_generate_code(self,a_instanceof) then
  1398. inherited;
  1399. end;
  1400. begin
  1401. ctypeconvnode:=tjvmtypeconvnode;
  1402. casnode:=tjvmasnode;
  1403. cisnode:=tjvmisnode;
  1404. end.