njvmcnv.pas 60 KB

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