njvmcnv.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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,defcmp;
  21. type
  22. tjvmtypeconvnode = class(tcgtypeconvnode)
  23. protected
  24. procedure second_int_to_int;override;
  25. { procedure second_string_to_string;override; }
  26. { procedure second_cstring_to_pchar;override; }
  27. { procedure second_string_to_chararray;override; }
  28. { procedure second_array_to_pointer;override; }
  29. function first_int_to_real: tnode; override;
  30. { procedure second_pointer_to_array;override; }
  31. { procedure second_chararray_to_string;override; }
  32. { procedure second_char_to_string;override; }
  33. procedure second_int_to_real;override;
  34. { procedure second_real_to_real;override; }
  35. { procedure second_cord_to_pointer;override; }
  36. { procedure second_proc_to_procvar;override; }
  37. procedure second_bool_to_int;override;
  38. procedure second_int_to_bool;override;
  39. { procedure second_load_smallset;override; }
  40. { procedure second_ansistring_to_pchar;override; }
  41. { procedure second_pchar_to_string;override; }
  42. { procedure second_class_to_intf;override; }
  43. { procedure second_char_to_char;override; }
  44. end;
  45. implementation
  46. uses
  47. verbose,globals,globtype,
  48. symconst,symtype,symdef,aasmbase,aasmdata,
  49. defutil,
  50. cgbase,cgutils,pass_1,pass_2,
  51. ncon,ncal,procinfo,
  52. nutils,
  53. cpubase,aasmcpu,
  54. tgobj,hlcgobj,hlcgcpu;
  55. {*****************************************************************************
  56. FirstTypeConv
  57. *****************************************************************************}
  58. function tjvmtypeconvnode.first_int_to_real: tnode;
  59. begin
  60. if not is_64bitint(left.resultdef) then
  61. if is_signed(left.resultdef) or
  62. (left.resultdef.size<4) then
  63. inserttypeconv(left,s32inttype)
  64. else
  65. inserttypeconv(left,u32inttype);
  66. firstpass(left);
  67. result := nil;
  68. expectloc:=LOC_FPUREGISTER;
  69. end;
  70. {*****************************************************************************
  71. SecondTypeConv
  72. *****************************************************************************}
  73. procedure tjvmtypeconvnode.second_int_to_int;
  74. var
  75. ressize,
  76. leftsize : longint;
  77. begin
  78. { insert range check if not explicit conversion }
  79. if not(nf_explicit in flags) then
  80. hlcg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
  81. { is the result size smaller? when typecasting from void
  82. we always reuse the current location, because there is
  83. nothing that we can load in a register }
  84. ressize:=resultdef.size;
  85. leftsize :=left.resultdef.size;
  86. if ((ressize<>leftsize) or
  87. ((location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  88. (location.reference.arrayreftype<>art_none) and
  89. (is_widechar(left.resultdef)<>is_widechar(resultdef))) or
  90. is_bitpacked_access(left)) and
  91. not is_void(left.resultdef) then
  92. begin
  93. location_copy(location,left.location);
  94. { reuse a loc_reference when the newsize is smaller than
  95. than the original, except
  96. a) for arrays (they use different load instructions for
  97. differently sized data types)
  98. b) when going from 8 to 4 bytes, because these are different
  99. data types
  100. -- note that this is different from other targets, and will
  101. break stuff like passing byte(shortintvar) to a var-parameter;
  102. although that may be "fixed" again because we have to use
  103. copy-in/copy-out to emulate var-parameters anyway... }
  104. if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  105. (location.reference.arrayreftype=art_none) and
  106. (ressize<leftsize) and
  107. (leftsize<=4) then
  108. begin
  109. location.size:=def_cgsize(resultdef);
  110. { no adjustment of the ffset even though Java is big endian,
  111. because the load instruction will remain the same }
  112. end
  113. else
  114. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,false);
  115. end
  116. else
  117. begin
  118. location_copy(location,left.location);
  119. location.size:=def_cgsize(resultdef);
  120. if (ressize < sizeof(aint)) and
  121. (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
  122. (def_cgsize(left.resultdef)<>def_cgsize(resultdef)) then
  123. begin
  124. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  125. location.loc:=LOC_REGISTER;
  126. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register);
  127. end;
  128. end;
  129. end;
  130. procedure tjvmtypeconvnode.second_int_to_real;
  131. var
  132. srcsize, ressize: longint;
  133. procedure convertsignedstackloc;
  134. begin
  135. case srcsize of
  136. 4:
  137. case ressize of
  138. 4:
  139. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2f));
  140. 8:
  141. begin
  142. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i2d));
  143. thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
  144. end;
  145. else
  146. internalerror(2011010601);
  147. end;
  148. 8:
  149. case ressize of
  150. 4:
  151. begin
  152. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2f));
  153. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  154. end;
  155. 8:
  156. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_l2d));
  157. else
  158. internalerror(2011010602);
  159. end;
  160. else
  161. internalerror(2011010603);
  162. end;
  163. end;
  164. var
  165. href : treference;
  166. signeddef : tdef;
  167. l1 : tasmlabel;
  168. begin
  169. srcsize:=left.resultdef.size;
  170. ressize:=resultdef.size;
  171. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  172. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  173. { first always convert as if it's a signed number }
  174. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  175. convertsignedstackloc;
  176. if not is_signed(left.resultdef) then
  177. begin
  178. { if it was unsigned, add high(cardinal)+1/high(qword)+1 in case
  179. the signed interpretation is < 0 }
  180. current_asmdata.getjumplabel(l1);
  181. if srcsize=4 then
  182. signeddef:=s32inttype
  183. else
  184. signeddef:=s64inttype;
  185. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,signeddef,OC_GTE,0,left.location,l1);
  186. if srcsize=4 then
  187. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,4294967296.0)
  188. else
  189. thlcgjvm(hlcg).a_loadfpu_const_stack(current_asmdata.CurrAsmList,resultdef,18446744073709551616.0);
  190. if ressize=4 then
  191. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_fadd))
  192. else
  193. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dadd));
  194. hlcg.a_label(current_asmdata.CurrAsmList,l1);
  195. end;
  196. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  197. end;
  198. procedure tjvmtypeconvnode.second_bool_to_int;
  199. var
  200. newsize: tcgsize;
  201. oldTrueLabel,oldFalseLabel : tasmlabel;
  202. begin
  203. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  204. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  205. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  206. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  207. secondpass(left);
  208. location_copy(location,left.location);
  209. newsize:=def_cgsize(resultdef);
  210. { byte(bytebool) or word(wordbool) or longint(longbool) must be }
  211. { accepted for var parameters and assignments, and must not }
  212. { change the ordinal value or value location. }
  213. { htypechk.valid_for_assign ensures that such locations with a }
  214. { size<sizeof(register) cannot be LOC_CREGISTER (they otherwise }
  215. { could be in case of a plain assignment), and LOC_REGISTER can }
  216. { never be an assignment target. The remaining LOC_REGISTER/ }
  217. { LOC_CREGISTER locations do have to be sign/zero-extended. }
  218. { -- Note: this does not work for Java and 2/4 byte sized
  219. values, because bytebool/wordbool are signed and
  220. are stored in 4 byte locations -> will result in
  221. "byte" with the value high(cardinal); see remark
  222. in second_int_to_int above regarding consequences }
  223. if not(nf_explicit in flags) or
  224. (location.loc in [LOC_FLAGS,LOC_JUMP]) or
  225. ((newsize<>left.location.size) and
  226. ((left.resultdef.size<>resultdef.size) or
  227. not(left.resultdef.size in [4,8]))
  228. ) then
  229. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  230. else
  231. { may differ in sign, e.g. bytebool -> byte }
  232. location.size:=newsize;
  233. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  234. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  235. end;
  236. procedure tjvmtypeconvnode.second_int_to_bool;
  237. var
  238. href: treference;
  239. hreg2 : tregister;
  240. hlabel1,hlabel2,oldTrueLabel,oldFalseLabel : tasmlabel;
  241. newsize : tcgsize;
  242. begin
  243. oldTrueLabel:=current_procinfo.CurrTrueLabel;
  244. oldFalseLabel:=current_procinfo.CurrFalseLabel;
  245. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  246. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  247. secondpass(left);
  248. if codegenerror then
  249. exit;
  250. { Explicit typecasts from any ordinal type to a boolean type }
  251. { must not change the ordinal value }
  252. if (nf_explicit in flags) and
  253. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
  254. begin
  255. location_copy(location,left.location);
  256. newsize:=def_cgsize(resultdef);
  257. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  258. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  259. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  260. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  261. else
  262. location.size:=newsize;
  263. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  264. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  265. exit;
  266. end;
  267. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  268. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  269. current_asmdata.getjumplabel(hlabel2);
  270. case left.location.loc of
  271. LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
  272. begin
  273. current_asmdata.getjumplabel(hlabel1);
  274. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location,hlabel1);
  275. end;
  276. LOC_JUMP :
  277. begin
  278. hlabel1:=current_procinfo.CurrFalseLabel;
  279. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  280. end;
  281. else
  282. internalerror(10062);
  283. end;
  284. if not(is_cbool(resultdef)) then
  285. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,1,R_INTREGISTER)
  286. else
  287. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,-1,R_INTREGISTER);
  288. { we jump over the next constant load -> they don't appear on the
  289. stack simulataneously }
  290. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  291. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel2);
  292. hlcg.a_label(current_asmdata.CurrAsmList,hlabel1);
  293. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,0,R_INTREGISTER);
  294. hlcg.a_label(current_asmdata.CurrAsmList,hlabel2);
  295. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  296. current_procinfo.CurrTrueLabel:=oldTrueLabel;
  297. current_procinfo.CurrFalseLabel:=oldFalseLabel;
  298. end;
  299. begin
  300. ctypeconvnode:=tjvmtypeconvnode;
  301. end.