jit_emit_conversion.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "jit_emit_conversion.h"
  6. #include "jit_emit_exception.h"
  7. #include "jit_emit_function.h"
  8. #include "../jit_codegen.h"
  9. #include "../jit_frontend.h"
  10. #define F32_I32_S_MIN (-2147483904.0f)
  11. #define F32_I32_S_MAX (2147483648.0f)
  12. #define F32_I32_U_MIN (-1.0f)
  13. #define F32_I32_U_MAX (4294967296.0f)
  14. #define F32_I64_S_MIN (-9223373136366403584.0f)
  15. #define F32_I64_S_MAX (9223372036854775808.0f)
  16. #define F32_I64_U_MIN (-1.0f)
  17. #define F32_I64_U_MAX (18446744073709551616.0f)
  18. #define F64_I32_S_MIN (-2147483649.0)
  19. #define F64_I32_S_MAX (2147483648.0)
  20. #define F64_I32_U_MIN (-1.0)
  21. #define F64_I32_U_MAX (4294967296.0)
  22. #define F64_I64_S_MIN (-9223372036854777856.0)
  23. #define F64_I64_S_MAX (9223372036854775808.0)
  24. #define F64_I64_U_MIN (-1.0)
  25. #define F64_I64_U_MAX (18446744073709551616.0)
  26. #define FP_TO_INT(f_ty, i_ty, f_nm, i_nm) \
  27. static i_ty i_nm##_trunc_##f_nm(f_ty fp)
  28. #define INT_TO_FP(i_ty, f_ty, i_nm, f_nm) \
  29. static f_ty f_nm##_convert_##i_nm(i_ty i)
  30. #define FP_TO_INT_SAT(f_ty, i_ty, f_nm, i_nm) \
  31. static i_ty i_nm##_trunc_##f_nm##_sat(f_ty fp)
  32. static int
  33. local_isnan(double x)
  34. {
  35. return isnan(x);
  36. }
  37. static int
  38. local_isnanf(float x)
  39. {
  40. return isnan(x);
  41. }
  42. #define RETURN_IF_NANF(fp) \
  43. if (local_isnanf(fp)) { \
  44. return 0; \
  45. }
  46. #define RETURN_IF_NAN(fp) \
  47. if (local_isnan(fp)) { \
  48. return 0; \
  49. }
  50. #define RETURN_IF_INF(fp, i_min, i_max) \
  51. if (isinf(fp)) { \
  52. return fp < 0 ? i_min : i_max; \
  53. }
  54. #define RETURN_IF_MIN(fp, f_min, i_min) \
  55. if (fp <= f_min) { \
  56. return i_min; \
  57. }
  58. #define RETURN_IF_MAX(fp, f_max, i_max) \
  59. if (fp >= f_max) { \
  60. return i_max; \
  61. }
  62. FP_TO_INT_SAT(float, int32, f32, i32)
  63. {
  64. RETURN_IF_NANF(fp)
  65. RETURN_IF_INF(fp, INT32_MIN, INT32_MAX)
  66. RETURN_IF_MIN(fp, F32_I32_S_MIN, INT32_MIN)
  67. RETURN_IF_MAX(fp, F32_I32_S_MAX, INT32_MAX)
  68. return (int32)fp;
  69. }
  70. FP_TO_INT_SAT(float, uint32, f32, u32)
  71. {
  72. RETURN_IF_NANF(fp)
  73. RETURN_IF_INF(fp, 0, UINT32_MAX)
  74. RETURN_IF_MIN(fp, F32_I32_U_MIN, 0)
  75. RETURN_IF_MAX(fp, F32_I32_U_MAX, UINT32_MAX)
  76. return (uint32)fp;
  77. }
  78. FP_TO_INT_SAT(double, int32, f64, i32)
  79. {
  80. RETURN_IF_NAN(fp)
  81. RETURN_IF_INF(fp, INT32_MIN, INT32_MAX)
  82. RETURN_IF_MIN(fp, F64_I32_S_MIN, INT32_MIN)
  83. RETURN_IF_MAX(fp, F64_I32_S_MAX, INT32_MAX)
  84. return (int32)fp;
  85. }
  86. FP_TO_INT_SAT(double, uint32, f64, u32)
  87. {
  88. RETURN_IF_NAN(fp)
  89. RETURN_IF_INF(fp, 0, UINT32_MAX)
  90. RETURN_IF_MIN(fp, F64_I32_U_MIN, 0)
  91. RETURN_IF_MAX(fp, F64_I32_U_MAX, UINT32_MAX)
  92. return (uint32)fp;
  93. }
  94. FP_TO_INT_SAT(float, int64, f32, i64)
  95. {
  96. RETURN_IF_NANF(fp)
  97. RETURN_IF_INF(fp, INT64_MIN, INT64_MAX)
  98. RETURN_IF_MIN(fp, F32_I64_S_MIN, INT64_MIN)
  99. RETURN_IF_MAX(fp, F32_I64_S_MAX, INT64_MAX)
  100. return (int64)fp;
  101. }
  102. FP_TO_INT(float, uint64, f32, u64)
  103. {
  104. return (uint64)fp;
  105. }
  106. FP_TO_INT_SAT(float, uint64, f32, u64)
  107. {
  108. RETURN_IF_NANF(fp)
  109. RETURN_IF_INF(fp, 0, UINT64_MAX)
  110. RETURN_IF_MIN(fp, F32_I64_U_MIN, 0)
  111. RETURN_IF_MAX(fp, F32_I64_U_MAX, UINT64_MAX)
  112. return (uint64)fp;
  113. }
  114. FP_TO_INT_SAT(double, int64, f64, i64)
  115. {
  116. RETURN_IF_NANF(fp)
  117. RETURN_IF_INF(fp, INT64_MIN, INT64_MAX)
  118. RETURN_IF_MIN(fp, F64_I64_S_MIN, INT64_MIN)
  119. RETURN_IF_MAX(fp, F64_I64_S_MAX, INT64_MAX)
  120. return (int64)fp;
  121. }
  122. FP_TO_INT(double, uint64, f64, u64)
  123. {
  124. return (uint64)fp;
  125. }
  126. FP_TO_INT_SAT(double, uint64, f64, u64)
  127. {
  128. RETURN_IF_NANF(fp)
  129. RETURN_IF_INF(fp, 0, UINT64_MAX)
  130. RETURN_IF_MIN(fp, F64_I64_U_MIN, 0)
  131. RETURN_IF_MAX(fp, F64_I64_U_MAX, UINT64_MAX)
  132. return (uint64)fp;
  133. }
  134. INT_TO_FP(uint64, float, u64, f32)
  135. {
  136. return (float)i;
  137. }
  138. INT_TO_FP(uint64, double, u64, f64)
  139. {
  140. return (double)i;
  141. }
  142. bool
  143. jit_compile_op_i32_wrap_i64(JitCompContext *cc)
  144. {
  145. JitReg num, res;
  146. POP_I64(num);
  147. res = jit_cc_new_reg_I32(cc);
  148. GEN_INSN(I64TOI32, res, num);
  149. PUSH_I32(res);
  150. return true;
  151. fail:
  152. return false;
  153. }
  154. static bool
  155. jit_compile_check_value_range(JitCompContext *cc, JitReg value, JitReg min_fp,
  156. JitReg max_fp)
  157. {
  158. JitReg nan_ret = jit_cc_new_reg_I32(cc);
  159. JitRegKind kind = jit_reg_kind(value);
  160. bool emit_ret = false;
  161. bh_assert(JIT_REG_KIND_F32 == kind || JIT_REG_KIND_F64 == kind);
  162. if (JIT_REG_KIND_F32 == kind && jit_reg_is_const(value)) {
  163. /* value is an f32 const */
  164. float value_f32_const = jit_cc_get_const_F32(cc, value);
  165. float min_fp_f32_const = jit_cc_get_const_F32(cc, min_fp);
  166. float max_fp_f32_const = jit_cc_get_const_F32(cc, max_fp);
  167. if (isnan(value_f32_const)) {
  168. /* throw exception if value is nan */
  169. if (!jit_emit_exception(cc, EXCE_INVALID_CONVERSION_TO_INTEGER,
  170. JIT_OP_JMP, 0, NULL))
  171. goto fail;
  172. }
  173. if (value_f32_const <= min_fp_f32_const
  174. || value_f32_const >= max_fp_f32_const) {
  175. /* throw exception if value is out of range */
  176. if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_JMP, 0,
  177. NULL))
  178. goto fail;
  179. }
  180. /* value is in range, do nothing */
  181. return true;
  182. }
  183. else if (JIT_REG_KIND_F64 == kind && jit_reg_is_const(value)) {
  184. /* value is an f64 const */
  185. double value_f64_const = jit_cc_get_const_F64(cc, value);
  186. double min_fp_f64_const = jit_cc_get_const_F64(cc, min_fp);
  187. double max_fp_f64_const = jit_cc_get_const_F64(cc, max_fp);
  188. if (isnan(value_f64_const)) {
  189. /* throw exception if value is nan */
  190. if (!jit_emit_exception(cc, EXCE_INVALID_CONVERSION_TO_INTEGER,
  191. JIT_OP_JMP, 0, NULL))
  192. goto fail;
  193. }
  194. if (value_f64_const <= min_fp_f64_const
  195. || value_f64_const >= max_fp_f64_const) {
  196. /* throw exception if value is out of range */
  197. if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_JMP, 0,
  198. NULL))
  199. goto fail;
  200. }
  201. /* value is in range, do nothing */
  202. return true;
  203. }
  204. /* If value is NaN, throw exception */
  205. if (JIT_REG_KIND_F32 == kind)
  206. emit_ret = jit_emit_callnative(cc, local_isnanf, nan_ret, &value, 1);
  207. else
  208. emit_ret = jit_emit_callnative(cc, local_isnan, nan_ret, &value, 1);
  209. if (!emit_ret)
  210. goto fail;
  211. GEN_INSN(CMP, cc->cmp_reg, nan_ret, NEW_CONST(I32, 1));
  212. if (!jit_emit_exception(cc, EXCE_INVALID_CONVERSION_TO_INTEGER, JIT_OP_BEQ,
  213. cc->cmp_reg, NULL))
  214. goto fail;
  215. /* If value is out of integer range, throw exception */
  216. GEN_INSN(CMP, cc->cmp_reg, min_fp, value);
  217. if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_BGES, cc->cmp_reg,
  218. NULL))
  219. goto fail;
  220. GEN_INSN(CMP, cc->cmp_reg, value, max_fp);
  221. if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_BGES, cc->cmp_reg,
  222. NULL))
  223. goto fail;
  224. return true;
  225. fail:
  226. return false;
  227. }
  228. bool
  229. jit_compile_op_i32_trunc_f32(JitCompContext *cc, bool sign, bool sat)
  230. {
  231. JitReg value, res;
  232. POP_F32(value);
  233. res = jit_cc_new_reg_I32(cc);
  234. if (!sat) {
  235. JitReg min_fp = NEW_CONST(F32, sign ? F32_I32_S_MIN : F32_I32_U_MIN);
  236. JitReg max_fp = NEW_CONST(F32, sign ? F32_I32_S_MAX : F32_I32_U_MAX);
  237. if (!jit_compile_check_value_range(cc, value, min_fp, max_fp))
  238. goto fail;
  239. if (sign)
  240. GEN_INSN(F32TOI32, res, value);
  241. else
  242. GEN_INSN(F32TOU32, res, value);
  243. }
  244. else {
  245. if (!jit_emit_callnative(cc,
  246. sign ? (void *)i32_trunc_f32_sat
  247. : (void *)u32_trunc_f32_sat,
  248. res, &value, 1))
  249. goto fail;
  250. }
  251. PUSH_I32(res);
  252. return true;
  253. fail:
  254. return false;
  255. }
  256. bool
  257. jit_compile_op_i32_trunc_f64(JitCompContext *cc, bool sign, bool sat)
  258. {
  259. JitReg value, res;
  260. POP_F64(value);
  261. res = jit_cc_new_reg_I32(cc);
  262. if (!sat) {
  263. JitReg min_fp = NEW_CONST(F64, sign ? F64_I32_S_MIN : F64_I32_U_MIN);
  264. JitReg max_fp = NEW_CONST(F64, sign ? F64_I32_S_MAX : F64_I32_U_MAX);
  265. if (!jit_compile_check_value_range(cc, value, min_fp, max_fp))
  266. goto fail;
  267. if (sign)
  268. GEN_INSN(F64TOI32, res, value);
  269. else
  270. GEN_INSN(F64TOU32, res, value);
  271. }
  272. else {
  273. if (!jit_emit_callnative(cc,
  274. sign ? (void *)i32_trunc_f64_sat
  275. : (void *)u32_trunc_f64_sat,
  276. res, &value, 1))
  277. goto fail;
  278. }
  279. PUSH_I32(res);
  280. return true;
  281. fail:
  282. return false;
  283. }
  284. bool
  285. jit_compile_op_i64_extend_i32(JitCompContext *cc, bool sign)
  286. {
  287. JitReg num, res;
  288. POP_I32(num);
  289. res = jit_cc_new_reg_I64(cc);
  290. if (sign)
  291. GEN_INSN(I32TOI64, res, num);
  292. else
  293. GEN_INSN(U32TOI64, res, num);
  294. PUSH_I64(res);
  295. return true;
  296. fail:
  297. return false;
  298. }
  299. bool
  300. jit_compile_op_i64_extend_i64(JitCompContext *cc, int8 bitwidth)
  301. {
  302. JitReg value, tmp, res;
  303. POP_I64(value);
  304. tmp = jit_cc_new_reg_I32(cc);
  305. res = jit_cc_new_reg_I64(cc);
  306. switch (bitwidth) {
  307. case 8:
  308. {
  309. GEN_INSN(I64TOI8, tmp, value);
  310. GEN_INSN(I8TOI64, res, tmp);
  311. break;
  312. }
  313. case 16:
  314. {
  315. GEN_INSN(I64TOI16, tmp, value);
  316. GEN_INSN(I16TOI64, res, tmp);
  317. break;
  318. }
  319. case 32:
  320. {
  321. GEN_INSN(I64TOI32, tmp, value);
  322. GEN_INSN(I32TOI64, res, tmp);
  323. break;
  324. }
  325. default:
  326. {
  327. bh_assert(0);
  328. goto fail;
  329. }
  330. }
  331. PUSH_I64(res);
  332. return true;
  333. fail:
  334. return false;
  335. }
  336. bool
  337. jit_compile_op_i32_extend_i32(JitCompContext *cc, int8 bitwidth)
  338. {
  339. JitReg value, tmp, res;
  340. POP_I32(value);
  341. tmp = jit_cc_new_reg_I32(cc);
  342. res = jit_cc_new_reg_I32(cc);
  343. switch (bitwidth) {
  344. case 8:
  345. {
  346. GEN_INSN(I32TOI8, tmp, value);
  347. GEN_INSN(I8TOI32, res, tmp);
  348. break;
  349. }
  350. case 16:
  351. {
  352. GEN_INSN(I32TOI16, tmp, value);
  353. GEN_INSN(I16TOI32, res, tmp);
  354. break;
  355. }
  356. default:
  357. {
  358. bh_assert(0);
  359. goto fail;
  360. }
  361. }
  362. PUSH_I32(res);
  363. return true;
  364. fail:
  365. return false;
  366. }
  367. bool
  368. jit_compile_op_i64_trunc_f32(JitCompContext *cc, bool sign, bool sat)
  369. {
  370. JitReg value, res;
  371. POP_F32(value);
  372. res = jit_cc_new_reg_I64(cc);
  373. if (!sat) {
  374. JitReg min_fp = NEW_CONST(F32, sign ? F32_I64_S_MIN : F32_I64_U_MIN);
  375. JitReg max_fp = NEW_CONST(F32, sign ? F32_I64_S_MAX : F32_I64_U_MAX);
  376. if (!jit_compile_check_value_range(cc, value, min_fp, max_fp))
  377. goto fail;
  378. if (sign) {
  379. GEN_INSN(F32TOI64, res, value);
  380. }
  381. else {
  382. if (!jit_emit_callnative(cc, u64_trunc_f32, res, &value, 1))
  383. goto fail;
  384. }
  385. }
  386. else {
  387. if (!jit_emit_callnative(cc,
  388. sign ? (void *)i64_trunc_f32_sat
  389. : (void *)u64_trunc_f32_sat,
  390. res, &value, 1))
  391. goto fail;
  392. }
  393. PUSH_I64(res);
  394. return true;
  395. fail:
  396. return false;
  397. }
  398. bool
  399. jit_compile_op_i64_trunc_f64(JitCompContext *cc, bool sign, bool sat)
  400. {
  401. JitReg value, res;
  402. POP_F64(value);
  403. res = jit_cc_new_reg_I64(cc);
  404. if (!sat) {
  405. JitReg min_fp = NEW_CONST(F64, sign ? F64_I64_S_MIN : F64_I64_U_MIN);
  406. JitReg max_fp = NEW_CONST(F64, sign ? F64_I64_S_MAX : F64_I64_U_MAX);
  407. if (!jit_compile_check_value_range(cc, value, min_fp, max_fp))
  408. goto fail;
  409. if (sign) {
  410. GEN_INSN(F64TOI64, res, value);
  411. }
  412. else {
  413. if (!jit_emit_callnative(cc, u64_trunc_f64, res, &value, 1))
  414. goto fail;
  415. }
  416. }
  417. else {
  418. if (!jit_emit_callnative(cc,
  419. sign ? (void *)i64_trunc_f64_sat
  420. : (void *)u64_trunc_f64_sat,
  421. res, &value, 1))
  422. goto fail;
  423. }
  424. PUSH_I64(res);
  425. return true;
  426. fail:
  427. return false;
  428. }
  429. bool
  430. jit_compile_op_f32_convert_i32(JitCompContext *cc, bool sign)
  431. {
  432. JitReg value, res;
  433. POP_I32(value);
  434. res = jit_cc_new_reg_F32(cc);
  435. if (sign) {
  436. GEN_INSN(I32TOF32, res, value);
  437. }
  438. else {
  439. GEN_INSN(U32TOF32, res, value);
  440. }
  441. PUSH_F32(res);
  442. return true;
  443. fail:
  444. return false;
  445. }
  446. bool
  447. jit_compile_op_f32_convert_i64(JitCompContext *cc, bool sign)
  448. {
  449. JitReg value, res;
  450. POP_I64(value);
  451. res = jit_cc_new_reg_F32(cc);
  452. if (sign) {
  453. GEN_INSN(I64TOF32, res, value);
  454. }
  455. else {
  456. if (!jit_emit_callnative(cc, f32_convert_u64, res, &value, 1)) {
  457. goto fail;
  458. }
  459. }
  460. PUSH_F32(res);
  461. return true;
  462. fail:
  463. return false;
  464. }
  465. bool
  466. jit_compile_op_f32_demote_f64(JitCompContext *cc)
  467. {
  468. JitReg value, res;
  469. POP_F64(value);
  470. res = jit_cc_new_reg_F32(cc);
  471. GEN_INSN(F64TOF32, res, value);
  472. PUSH_F32(res);
  473. return true;
  474. fail:
  475. return false;
  476. }
  477. bool
  478. jit_compile_op_f64_convert_i32(JitCompContext *cc, bool sign)
  479. {
  480. JitReg value, res;
  481. POP_I32(value);
  482. res = jit_cc_new_reg_F64(cc);
  483. if (sign)
  484. GEN_INSN(I32TOF64, res, value);
  485. else
  486. GEN_INSN(U32TOF64, res, value);
  487. PUSH_F64(res);
  488. return true;
  489. fail:
  490. return false;
  491. }
  492. bool
  493. jit_compile_op_f64_convert_i64(JitCompContext *cc, bool sign)
  494. {
  495. JitReg value, res;
  496. POP_I64(value);
  497. res = jit_cc_new_reg_F64(cc);
  498. if (sign) {
  499. GEN_INSN(I64TOF64, res, value);
  500. }
  501. else {
  502. if (!jit_emit_callnative(cc, f64_convert_u64, res, &value, 1)) {
  503. goto fail;
  504. }
  505. }
  506. PUSH_F64(res);
  507. return true;
  508. fail:
  509. return false;
  510. }
  511. bool
  512. jit_compile_op_f64_promote_f32(JitCompContext *cc)
  513. {
  514. JitReg value, res;
  515. POP_F32(value);
  516. res = jit_cc_new_reg_F64(cc);
  517. GEN_INSN(F32TOF64, res, value);
  518. PUSH_F64(res);
  519. return true;
  520. fail:
  521. return false;
  522. }
  523. bool
  524. jit_compile_op_i64_reinterpret_f64(JitCompContext *cc)
  525. {
  526. JitReg value, res;
  527. POP_F64(value);
  528. res = jit_cc_new_reg_I64(cc);
  529. GEN_INSN(F64CASTI64, res, value);
  530. PUSH_I64(res);
  531. return true;
  532. fail:
  533. return false;
  534. }
  535. bool
  536. jit_compile_op_i32_reinterpret_f32(JitCompContext *cc)
  537. {
  538. JitReg value, res;
  539. POP_F32(value);
  540. res = jit_cc_new_reg_I32(cc);
  541. GEN_INSN(F32CASTI32, res, value);
  542. PUSH_I32(res);
  543. return true;
  544. fail:
  545. return false;
  546. }
  547. bool
  548. jit_compile_op_f64_reinterpret_i64(JitCompContext *cc)
  549. {
  550. JitReg value, res;
  551. POP_I64(value);
  552. res = jit_cc_new_reg_F64(cc);
  553. GEN_INSN(I64CASTF64, res, value);
  554. PUSH_F64(res);
  555. return true;
  556. fail:
  557. return false;
  558. }
  559. bool
  560. jit_compile_op_f32_reinterpret_i32(JitCompContext *cc)
  561. {
  562. JitReg value, res;
  563. POP_I32(value);
  564. res = jit_cc_new_reg_F32(cc);
  565. GEN_INSN(I32CASTF32, res, value);
  566. PUSH_F32(res);
  567. return true;
  568. fail:
  569. return false;
  570. }