aot_emit_conversion.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot_emit_conversion.h"
  6. #include "aot_emit_exception.h"
  7. #include "aot_emit_numberic.h"
  8. #include "../aot/aot_intrinsic.h"
  9. #include "../aot/aot_runtime.h"
  10. static bool
  11. trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  12. LLVMValueRef operand, LLVMTypeRef src_type, LLVMTypeRef dest_type,
  13. LLVMValueRef min_value, LLVMValueRef max_value,
  14. char *name, bool sign)
  15. {
  16. LLVMBasicBlockRef check_nan_succ, check_overflow_succ;
  17. LLVMValueRef is_less, is_greater, res;
  18. if (comp_ctx->disable_llvm_intrinsics
  19. && aot_intrinsic_check_capability(
  20. comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) {
  21. LLVMTypeRef param_types[3];
  22. LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_UNO, true);
  23. param_types[0] = I32_TYPE;
  24. param_types[1] = src_type;
  25. param_types[2] = src_type;
  26. res = aot_call_llvm_intrinsic(
  27. comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp",
  28. I32_TYPE, param_types, 3, opcond, operand, operand);
  29. if (!res) {
  30. goto fail;
  31. }
  32. res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast");
  33. }
  34. else {
  35. res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, operand, operand,
  36. "fcmp_is_nan");
  37. }
  38. if (!res) {
  39. aot_set_last_error("llvm build fcmp failed.");
  40. goto fail;
  41. }
  42. if (!(check_nan_succ =
  43. LLVMAppendBasicBlockInContext(comp_ctx->context,
  44. func_ctx->func,
  45. "check_nan_succ"))) {
  46. aot_set_last_error("llvm add basic block failed.");
  47. goto fail;
  48. }
  49. LLVMMoveBasicBlockAfter(check_nan_succ,
  50. LLVMGetInsertBlock(comp_ctx->builder));
  51. if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_CONVERSION_TO_INTEGER,
  52. true, res, check_nan_succ)))
  53. goto fail;
  54. if (comp_ctx->disable_llvm_intrinsics
  55. && aot_intrinsic_check_capability(
  56. comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) {
  57. LLVMTypeRef param_types[3];
  58. LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_LE, true);
  59. param_types[0] = I32_TYPE;
  60. param_types[1] = src_type;
  61. param_types[2] = src_type;
  62. is_less = aot_call_llvm_intrinsic(
  63. comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp",
  64. I32_TYPE, param_types, 3, opcond, operand, min_value);
  65. if (!is_less) {
  66. goto fail;
  67. }
  68. is_less =
  69. LLVMBuildIntCast(comp_ctx->builder, is_less, INT1_TYPE, "bit_cast");
  70. }
  71. else {
  72. is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
  73. min_value, "fcmp_min_value");
  74. }
  75. if (!is_less) {
  76. aot_set_last_error("llvm build fcmp failed.");
  77. goto fail;
  78. }
  79. if (comp_ctx->disable_llvm_intrinsics
  80. && aot_intrinsic_check_capability(
  81. comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) {
  82. LLVMTypeRef param_types[3];
  83. LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_GE, true);
  84. param_types[0] = I32_TYPE;
  85. param_types[1] = src_type;
  86. param_types[2] = src_type;
  87. is_greater = aot_call_llvm_intrinsic(
  88. comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp",
  89. I32_TYPE, param_types, 3, opcond, operand, max_value);
  90. if (!is_greater) {
  91. goto fail;
  92. }
  93. is_greater = LLVMBuildIntCast(comp_ctx->builder, is_greater, INT1_TYPE,
  94. "bit_cast");
  95. }
  96. else {
  97. is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
  98. max_value, "fcmp_min_value");
  99. }
  100. if (!is_greater) {
  101. aot_set_last_error("llvm build fcmp failed.");
  102. goto fail;
  103. }
  104. if (!(res = LLVMBuildOr(comp_ctx->builder, is_less, is_greater, "is_overflow"))) {
  105. aot_set_last_error("llvm build logic and failed.");
  106. goto fail;
  107. }
  108. /* Check if float value out of range */
  109. if (!(check_overflow_succ =
  110. LLVMAppendBasicBlockInContext(comp_ctx->context,
  111. func_ctx->func,
  112. "check_overflow_succ"))) {
  113. aot_set_last_error("llvm add basic block failed.");
  114. goto fail;
  115. }
  116. LLVMMoveBasicBlockAfter(check_overflow_succ,
  117. LLVMGetInsertBlock(comp_ctx->builder));
  118. if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
  119. true, res, check_overflow_succ)))
  120. goto fail;
  121. if (comp_ctx->disable_llvm_intrinsics
  122. && aot_intrinsic_check_capability(comp_ctx, name)) {
  123. LLVMTypeRef param_types[1];
  124. param_types[0] = src_type;
  125. res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, name, dest_type,
  126. param_types, 1, operand);
  127. }
  128. else {
  129. if (sign)
  130. res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name);
  131. else
  132. res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name);
  133. }
  134. if (!res) {
  135. aot_set_last_error("llvm build conversion failed.");
  136. return false;
  137. }
  138. if (dest_type == I32_TYPE)
  139. PUSH_I32(res);
  140. else if (dest_type == I64_TYPE)
  141. PUSH_I64(res);
  142. return true;
  143. fail:
  144. return false;
  145. }
  146. #define ADD_BASIC_BLOCK(block, name) do { \
  147. if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \
  148. func_ctx->func, \
  149. name))) { \
  150. aot_set_last_error("llvm add basic block failed."); \
  151. goto fail; \
  152. } \
  153. \
  154. LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \
  155. } while (0)
  156. static bool
  157. trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  158. LLVMValueRef operand, LLVMTypeRef src_type, LLVMTypeRef dest_type,
  159. LLVMValueRef min_value, LLVMValueRef max_value,
  160. char *name, bool sign)
  161. {
  162. LLVMBasicBlockRef check_nan_succ, check_less_succ, check_greater_succ;
  163. LLVMBasicBlockRef is_nan_block, is_less_block, is_greater_block, res_block;
  164. LLVMValueRef is_less, is_greater, res, phi;
  165. LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO;
  166. LLVMValueRef vmin, vmax;
  167. if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO,
  168. operand, operand, "fcmp_is_nan"))) {
  169. aot_set_last_error("llvm build fcmp failed.");
  170. goto fail;
  171. }
  172. ADD_BASIC_BLOCK(check_nan_succ, "check_nan_succ");
  173. ADD_BASIC_BLOCK(is_nan_block, "is_nan_block");
  174. ADD_BASIC_BLOCK(check_less_succ, "check_less_succ");
  175. ADD_BASIC_BLOCK(is_less_block, "is_less_block");
  176. ADD_BASIC_BLOCK(check_greater_succ, "check_greater_succ");
  177. ADD_BASIC_BLOCK(is_greater_block, "is_greater_block");
  178. ADD_BASIC_BLOCK(res_block, "res_block");
  179. if (!LLVMBuildCondBr(comp_ctx->builder, res,
  180. is_nan_block, check_nan_succ)) {
  181. aot_set_last_error("llvm build cond br failed.");
  182. goto fail;
  183. }
  184. /* Start to translate is_nan block */
  185. LLVMPositionBuilderAtEnd(comp_ctx->builder, is_nan_block);
  186. if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
  187. aot_set_last_error("llvm build br failed.");
  188. goto fail;
  189. }
  190. /* Start to translate check_nan_succ block */
  191. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ);
  192. if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
  193. min_value, "fcmp_min_value"))) {
  194. aot_set_last_error("llvm build fcmp failed.");
  195. goto fail;
  196. }
  197. if (!LLVMBuildCondBr(comp_ctx->builder, is_less,
  198. is_less_block, check_less_succ)) {
  199. aot_set_last_error("llvm build cond br failed.");
  200. goto fail;
  201. }
  202. /* Start to translate is_less block */
  203. LLVMPositionBuilderAtEnd(comp_ctx->builder, is_less_block);
  204. if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
  205. aot_set_last_error("llvm build br failed.");
  206. goto fail;
  207. }
  208. /* Start to translate check_less_succ block */
  209. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ);
  210. if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
  211. max_value, "fcmp_max_value"))) {
  212. aot_set_last_error("llvm build fcmp failed.");
  213. goto fail;
  214. }
  215. if (!LLVMBuildCondBr(comp_ctx->builder, is_greater,
  216. is_greater_block, check_greater_succ)) {
  217. aot_set_last_error("llvm build cond br failed.");
  218. goto fail;
  219. }
  220. /* Start to translate is_greater block */
  221. LLVMPositionBuilderAtEnd(comp_ctx->builder, is_greater_block);
  222. if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
  223. aot_set_last_error("llvm build br failed.");
  224. goto fail;
  225. }
  226. /* Start to translate check_greater_succ block */
  227. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_greater_succ);
  228. if (comp_ctx->disable_llvm_intrinsics
  229. && aot_intrinsic_check_capability(comp_ctx, name)) {
  230. LLVMTypeRef param_types[1];
  231. param_types[0] = src_type;
  232. res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, name, dest_type,
  233. param_types, 1, operand);
  234. }
  235. else {
  236. if (sign)
  237. res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name);
  238. else
  239. res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name);
  240. }
  241. if (!res) {
  242. aot_set_last_error("llvm build conversion failed.");
  243. return false;
  244. }
  245. if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
  246. aot_set_last_error("llvm build br failed.");
  247. goto fail;
  248. }
  249. /* Start to translate res_block */
  250. LLVMPositionBuilderAtEnd(comp_ctx->builder, res_block);
  251. /* Create result phi */
  252. if (!(phi = LLVMBuildPhi(comp_ctx->builder,
  253. dest_type,
  254. "trunc_sat_result_phi"))) {
  255. aot_set_last_error("llvm build phi failed.");
  256. return false;
  257. }
  258. /* Add phi incoming values */
  259. if (dest_type == I32_TYPE) {
  260. if (sign) {
  261. vmin = I32_CONST(INT32_MIN);
  262. vmax = I32_CONST(INT32_MAX);
  263. }
  264. else {
  265. vmin = I32_CONST(0);
  266. vmax = I32_CONST(UINT32_MAX);
  267. }
  268. }
  269. else if (dest_type == I64_TYPE) {
  270. if (sign) {
  271. vmin = I64_CONST(INT64_MIN);
  272. vmax = I64_CONST(INT64_MAX);
  273. }
  274. else {
  275. vmin = I64_CONST(0);
  276. vmax = I64_CONST(UINT64_MAX);
  277. }
  278. }
  279. LLVMAddIncoming(phi, &zero, &is_nan_block, 1);
  280. LLVMAddIncoming(phi, &vmin, &is_less_block, 1);
  281. LLVMAddIncoming(phi, &vmax, &is_greater_block, 1);
  282. LLVMAddIncoming(phi, &res, &check_greater_succ, 1);
  283. if (dest_type == I32_TYPE)
  284. PUSH_I32(phi);
  285. else if (dest_type == I64_TYPE)
  286. PUSH_I64(phi);
  287. return true;
  288. fail:
  289. return false;
  290. }
  291. bool
  292. aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  293. {
  294. LLVMValueRef value, res;
  295. POP_I64(value);
  296. if (!(res = LLVMBuildTrunc(comp_ctx->builder, value, I32_TYPE, "i32_wrap_i64"))) {
  297. aot_set_last_error("llvm build conversion failed.");
  298. return false;
  299. }
  300. PUSH_I32(res);
  301. return true;
  302. fail:
  303. return false;
  304. }
  305. bool
  306. aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  307. bool sign, bool saturating)
  308. {
  309. LLVMValueRef value;
  310. LLVMValueRef min_value, max_value;
  311. POP_F32(value);
  312. if (sign) {
  313. min_value = F32_CONST(-2147483904.0f);
  314. max_value = F32_CONST(2147483648.0f);
  315. }
  316. else {
  317. min_value = F32_CONST(-1.0f);
  318. max_value = F32_CONST(4294967296.0f);
  319. }
  320. if (!saturating)
  321. return trunc_float_to_int(comp_ctx, func_ctx, value,
  322. F32_TYPE, I32_TYPE, min_value, max_value,
  323. sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
  324. else
  325. return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
  326. F32_TYPE, I32_TYPE, min_value, max_value,
  327. sign ? "i32_trunc_sat_f32_s" :
  328. "i32_trunc_sat_f32_u", sign);
  329. fail:
  330. return false;
  331. }
  332. bool
  333. aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  334. bool sign, bool saturating)
  335. {
  336. LLVMValueRef value;
  337. LLVMValueRef min_value, max_value;
  338. POP_F64(value);
  339. if (sign) {
  340. min_value = F64_CONST(-2147483649.0);
  341. max_value = F64_CONST(2147483648.0);
  342. }
  343. else {
  344. min_value = F64_CONST(-1.0);
  345. max_value = F64_CONST(4294967296.0);
  346. }
  347. if (!saturating)
  348. return trunc_float_to_int(comp_ctx, func_ctx, value,
  349. F64_TYPE, I32_TYPE, min_value, max_value,
  350. sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
  351. else
  352. return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
  353. F64_TYPE, I32_TYPE, min_value, max_value,
  354. sign ? "i32_trunc_sat_f64_s" :
  355. "i32_trunc_sat_f64_u", sign);
  356. fail:
  357. return false;
  358. }
  359. bool
  360. aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  361. bool sign)
  362. {
  363. LLVMValueRef value, res;
  364. POP_I32(value);
  365. if (sign)
  366. res = LLVMBuildSExt(comp_ctx->builder, value, I64_TYPE, "i64_extend_i32_s");
  367. else
  368. res = LLVMBuildZExt(comp_ctx->builder, value, I64_TYPE, "i64_extend_i32_u");
  369. if (!res) {
  370. aot_set_last_error("llvm build conversion failed.");
  371. return false;
  372. }
  373. PUSH_I64(res);
  374. return true;
  375. fail:
  376. return false;
  377. }
  378. bool
  379. aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  380. int8 bitwidth)
  381. {
  382. LLVMValueRef value, res, cast_value = NULL;
  383. POP_I64(value);
  384. if (bitwidth == 8) {
  385. cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
  386. INT8_TYPE, true, "i8_intcast_i64");
  387. }
  388. else if (bitwidth == 16) {
  389. cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
  390. INT16_TYPE, true, "i16_intcast_i64");
  391. }
  392. else if (bitwidth == 32) {
  393. cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
  394. I32_TYPE, true, "i32_intcast_i64");
  395. }
  396. if (!cast_value) {
  397. aot_set_last_error("llvm build conversion failed.");
  398. return false;
  399. }
  400. res = LLVMBuildSExt(comp_ctx->builder, cast_value, I64_TYPE, "i64_extend_i64_s");
  401. if (!res) {
  402. aot_set_last_error("llvm build conversion failed.");
  403. return false;
  404. }
  405. PUSH_I64(res);
  406. return true;
  407. fail:
  408. return false;
  409. }
  410. bool
  411. aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  412. int8 bitwidth)
  413. {
  414. LLVMValueRef value, res, cast_value = NULL;
  415. POP_I32(value);
  416. if (bitwidth == 8) {
  417. cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
  418. INT8_TYPE, true, "i8_intcast_i32");
  419. }
  420. else if (bitwidth == 16) {
  421. cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
  422. INT16_TYPE, true, "i16_intcast_i32");
  423. }
  424. if (!cast_value) {
  425. aot_set_last_error("llvm build conversion failed.");
  426. return false;
  427. }
  428. res = LLVMBuildSExt(comp_ctx->builder, cast_value, I32_TYPE, "i32_extend_i32_s");
  429. if (!res) {
  430. aot_set_last_error("llvm build conversion failed.");
  431. return false;
  432. }
  433. PUSH_I32(res);
  434. return true;
  435. fail:
  436. return false;
  437. }
  438. bool
  439. aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  440. bool sign, bool saturating)
  441. {
  442. LLVMValueRef value;
  443. LLVMValueRef min_value, max_value;
  444. POP_F32(value);
  445. if (sign) {
  446. min_value = F32_CONST(-9223373136366403584.0f);
  447. max_value = F32_CONST(9223372036854775808.0f);
  448. }
  449. else {
  450. min_value = F32_CONST(-1.0f);
  451. max_value = F32_CONST(18446744073709551616.0f);
  452. }
  453. if (!saturating)
  454. return trunc_float_to_int(comp_ctx, func_ctx, value,
  455. F32_TYPE, I64_TYPE, min_value, max_value,
  456. sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
  457. else
  458. return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
  459. F32_TYPE, I64_TYPE, min_value, max_value,
  460. sign ? "i64_trunc_sat_f32_s" :
  461. "i64_trunc_sat_f32_u", sign);
  462. fail:
  463. return false;
  464. }
  465. bool
  466. aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  467. bool sign, bool saturating)
  468. {
  469. LLVMValueRef value;
  470. LLVMValueRef min_value, max_value;
  471. POP_F64(value);
  472. if (sign) {
  473. min_value = F64_CONST(-9223372036854777856.0);
  474. max_value = F64_CONST(9223372036854775808.0);
  475. }
  476. else {
  477. min_value = F64_CONST(-1.0);
  478. max_value = F64_CONST(18446744073709551616.0);
  479. }
  480. if (!saturating)
  481. return trunc_float_to_int(comp_ctx, func_ctx, value,
  482. F64_TYPE, I64_TYPE, min_value, max_value,
  483. sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
  484. else
  485. return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
  486. F64_TYPE, I64_TYPE, min_value, max_value,
  487. sign ? "i64_trunc_sat_f64_s" :
  488. "i64_trunc_sat_f64_u", sign);
  489. fail:
  490. return false;
  491. }
  492. bool
  493. aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  494. bool sign)
  495. {
  496. LLVMValueRef value, res;
  497. POP_I32(value);
  498. if (comp_ctx->disable_llvm_intrinsics
  499. && aot_intrinsic_check_capability(
  500. comp_ctx, sign ? "f32_convert_i32_s" : "f32_convert_i32_u")) {
  501. LLVMTypeRef param_types[1];
  502. param_types[0] = I32_TYPE;
  503. res = aot_call_llvm_intrinsic(
  504. comp_ctx, func_ctx, sign ? "f32_convert_i32_s" : "f32_convert_i32_u",
  505. F32_TYPE, param_types, 1, value);
  506. }
  507. else {
  508. if (sign)
  509. res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE,
  510. "f32_convert_i32_s");
  511. else
  512. res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE,
  513. "f32_convert_i32_u");
  514. }
  515. if (!res) {
  516. aot_set_last_error("llvm build conversion failed.");
  517. return false;
  518. }
  519. PUSH_F32(res);
  520. return true;
  521. fail:
  522. return false;
  523. }
  524. bool
  525. aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  526. bool sign)
  527. {
  528. LLVMValueRef value, res;
  529. POP_I64(value);
  530. if (comp_ctx->disable_llvm_intrinsics
  531. && aot_intrinsic_check_capability(
  532. comp_ctx, sign ? "f32_convert_i64_s" : "f32_convert_i64_u")) {
  533. LLVMTypeRef param_types[1];
  534. param_types[0] = I64_TYPE;
  535. res = aot_call_llvm_intrinsic(
  536. comp_ctx, func_ctx, sign ? "f32_convert_i64_s" : "f32_convert_i64_u",
  537. F32_TYPE, param_types, 1, value);
  538. }
  539. else {
  540. if (sign)
  541. res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE,
  542. "f32_convert_i64_s");
  543. else
  544. res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE,
  545. "f32_convert_i64_u");
  546. }
  547. if (!res) {
  548. aot_set_last_error("llvm build conversion failed.");
  549. return false;
  550. }
  551. PUSH_F32(res);
  552. return true;
  553. fail:
  554. return false;
  555. }
  556. bool
  557. aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  558. {
  559. LLVMValueRef value, res;
  560. POP_F64(value);
  561. if (comp_ctx->disable_llvm_intrinsics
  562. && aot_intrinsic_check_capability(comp_ctx, "f32_demote_f64")) {
  563. LLVMTypeRef param_types[1];
  564. param_types[0] = F64_TYPE;
  565. res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_demote_f64",
  566. F32_TYPE, param_types, 1, value);
  567. }
  568. else {
  569. res = LLVMBuildFPTrunc(comp_ctx->builder, value, F32_TYPE,
  570. "f32_demote_f64");
  571. }
  572. if (!res) {
  573. aot_set_last_error("llvm build conversion failed.");
  574. return false;
  575. }
  576. PUSH_F32(res);
  577. return true;
  578. fail:
  579. return false;
  580. }
  581. bool
  582. aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  583. bool sign)
  584. {
  585. LLVMValueRef value, res;
  586. POP_I32(value);
  587. if (comp_ctx->disable_llvm_intrinsics
  588. && aot_intrinsic_check_capability(
  589. comp_ctx, sign ? "f64_convert_i32_s" : "f64_convert_i32_u")) {
  590. LLVMTypeRef param_types[1];
  591. param_types[0] = I32_TYPE;
  592. res = aot_call_llvm_intrinsic(
  593. comp_ctx, func_ctx, sign ? "f64_convert_i32_s" : "f64_convert_i32_u",
  594. F64_TYPE, param_types, 1, value);
  595. }
  596. else {
  597. if (sign)
  598. res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE,
  599. "f64_convert_i32_s");
  600. else
  601. res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE,
  602. "f64_convert_i32_u");
  603. }
  604. if (!res) {
  605. aot_set_last_error("llvm build conversion failed.");
  606. return false;
  607. }
  608. PUSH_F64(res);
  609. return true;
  610. fail:
  611. return false;
  612. }
  613. bool
  614. aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  615. bool sign)
  616. {
  617. LLVMValueRef value, res;
  618. POP_I64(value);
  619. if (comp_ctx->disable_llvm_intrinsics
  620. && aot_intrinsic_check_capability(
  621. comp_ctx, sign ? "f64_convert_i64_s" : "f64_convert_i64_u")) {
  622. LLVMTypeRef param_types[1];
  623. param_types[0] = I64_TYPE;
  624. res = aot_call_llvm_intrinsic(
  625. comp_ctx, func_ctx, sign ? "f64_convert_i64_s" : "f64_convert_i64_u",
  626. F64_TYPE, param_types, 1, value);
  627. }
  628. else {
  629. if (sign)
  630. res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE,
  631. "f64_convert_i64_s");
  632. else
  633. res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE,
  634. "f64_convert_i64_u");
  635. }
  636. if (!res) {
  637. aot_set_last_error("llvm build conversion failed.");
  638. return false;
  639. }
  640. PUSH_F64(res);
  641. return true;
  642. fail:
  643. return false;
  644. }
  645. bool
  646. aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  647. {
  648. LLVMValueRef value, res;
  649. POP_F32(value);
  650. if (comp_ctx->disable_llvm_intrinsics
  651. && aot_intrinsic_check_capability(comp_ctx, "f64_promote_f32")) {
  652. LLVMTypeRef param_types[1];
  653. param_types[0] = F32_TYPE;
  654. res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f64_promote_f32",
  655. F64_TYPE, param_types, 1, value);
  656. }
  657. else {
  658. res = LLVMBuildFPExt(comp_ctx->builder, value, F64_TYPE,
  659. "f64_promote_f32");
  660. }
  661. if (!res) {
  662. aot_set_last_error("llvm build conversion failed.");
  663. return false;
  664. }
  665. PUSH_F64(res);
  666. /* Avoid the promote being optimized away */
  667. PUSH_F64(F64_CONST(1.0));
  668. return aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, FLOAT_MUL);
  669. fail:
  670. return false;
  671. }
  672. bool
  673. aot_compile_op_i64_reinterpret_f64(AOTCompContext *comp_ctx,
  674. AOTFuncContext *func_ctx)
  675. {
  676. LLVMValueRef value;
  677. POP_F64(value);
  678. if (!(value = LLVMBuildBitCast(comp_ctx->builder, value,
  679. I64_TYPE, "i64"))) {
  680. aot_set_last_error("llvm build fp to si failed.");
  681. return false;
  682. }
  683. PUSH_I64(value);
  684. return true;
  685. fail:
  686. return false;
  687. }
  688. bool
  689. aot_compile_op_i32_reinterpret_f32(AOTCompContext *comp_ctx,
  690. AOTFuncContext *func_ctx)
  691. {
  692. LLVMValueRef value;
  693. POP_F32(value);
  694. if (!(value = LLVMBuildBitCast(comp_ctx->builder, value,
  695. I32_TYPE, "i32"))) {
  696. aot_set_last_error("llvm build fp to si failed.");
  697. return false;
  698. }
  699. PUSH_I32(value);
  700. return true;
  701. fail:
  702. return false;
  703. }
  704. bool
  705. aot_compile_op_f64_reinterpret_i64(AOTCompContext *comp_ctx,
  706. AOTFuncContext *func_ctx)
  707. {
  708. LLVMValueRef value;
  709. POP_I64(value);
  710. if (!(value = LLVMBuildBitCast(comp_ctx->builder, value,
  711. F64_TYPE, "f64"))) {
  712. aot_set_last_error("llvm build si to fp failed.");
  713. return false;
  714. }
  715. PUSH_F64(value);
  716. return true;
  717. fail:
  718. return false;
  719. }
  720. bool
  721. aot_compile_op_f32_reinterpret_i32(AOTCompContext *comp_ctx,
  722. AOTFuncContext *func_ctx)
  723. {
  724. LLVMValueRef value;
  725. POP_I32(value);
  726. if (!(value = LLVMBuildBitCast(comp_ctx->builder, value,
  727. F32_TYPE, "f32"))) {
  728. aot_set_last_error("llvm build si to fp failed.");
  729. return false;
  730. }
  731. PUSH_F32(value);
  732. return true;
  733. fail:
  734. return false;
  735. }