njvmcnv.pas 63 KB

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