فهرست منبع

Fix XIP issues of fp to int cast and int rem/div (#1654)

Huang Qi 3 سال پیش
والد
کامیت
94cecbe4cb

+ 3 - 0
core/iwasm/aot/aot_intrinsic.c

@@ -57,6 +57,8 @@ static const aot_intrinsic g_intrinsic_mapping[] = {
     { "i32_trunc_f32_s", "aot_intrinsic_f32_to_i32", AOT_INTRINSIC_FLAG_F32_TO_I32 },
     { "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 },
     { "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 },
+    { "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 },
+    { "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 },
     { "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 },
     { "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 },
     { "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP },
@@ -665,6 +667,7 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx)
         else {
             add_f32_common_intrinsics(comp_ctx);
             add_f64_common_intrinsics(comp_ctx);
+            add_i64_common_intrinsics(comp_ctx);
             add_common_float_integer_convertion(comp_ctx);
         }
     }

+ 2 - 0
core/iwasm/aot/aot_reloc.h

@@ -103,6 +103,8 @@ typedef struct {
     REG_SYM(aot_intrinsic_f32_to_u32),    \
     REG_SYM(aot_intrinsic_f64_to_i32),    \
     REG_SYM(aot_intrinsic_f64_to_u32),    \
+    REG_SYM(aot_intrinsic_f64_to_i64),    \
+    REG_SYM(aot_intrinsic_f64_to_u64),    \
     REG_SYM(aot_intrinsic_f32_to_f64),    \
     REG_SYM(aot_intrinsic_f32_cmp),       \
     REG_SYM(aot_intrinsic_f64_cmp),       \

+ 24 - 4
core/iwasm/compilation/aot_emit_conversion.c

@@ -261,10 +261,30 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                                       param_types, 1, operand);
     }
     else {
-        if (sign)
-            res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name);
-        else
-            res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name);
+        char intrinsic[128];
+
+        /* Integer width is always 32 or 64 here. */
+
+        snprintf(intrinsic, sizeof(intrinsic), "i%d_trunc_f%d_%c",
+                 LLVMGetIntTypeWidth(dest_type),
+                 LLVMGetTypeKind(src_type) == LLVMFloatTypeKind ? 32 : 64,
+                 sign ? 's' : 'u');
+
+        if (comp_ctx->disable_llvm_intrinsics
+            && aot_intrinsic_check_capability(comp_ctx, intrinsic)) {
+            res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
+                                          dest_type, &src_type, 1, operand);
+        }
+        else {
+            if (sign) {
+                res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type,
+                                      name);
+            }
+            else {
+                res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type,
+                                      name);
+            }
+        }
     }
 
     if (!res) {

+ 25 - 14
core/iwasm/compilation/aot_emit_numberic.c

@@ -400,6 +400,7 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMValueRef left, right, cmp_div_zero, overflow, res;
     LLVMBasicBlockRef check_div_zero_succ, check_overflow_succ;
     LLVMTypeRef param_types[2];
+    const char *intrinsic = NULL;
 
     param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE;
 
@@ -561,22 +562,24 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                                          check_overflow_succ)))
                     goto fail;
 
-                LLVM_BUILD_OP(SDiv, left, right, res, "div_s", false);
-                PUSH_INT(res);
-                return true;
-            case INT_DIV_U:
-                if (comp_ctx->disable_llvm_intrinsics && is_i32
-                    && aot_intrinsic_check_capability(comp_ctx, "i32.div_u")) {
+                if (comp_ctx->disable_llvm_intrinsics && !is_i32
+                    && aot_intrinsic_check_capability(comp_ctx, "i64.div_s")) {
                     res = aot_call_llvm_intrinsic(comp_ctx, func_ctx,
-                                                  "i32.div_u", param_types[0],
+                                                  "i64.div_s", param_types[0],
                                                   param_types, 2, left, right);
                 }
-                else if (comp_ctx->disable_llvm_intrinsics && !is_i32
-                         && aot_intrinsic_check_capability(comp_ctx,
-                                                           "i64.div_u")) {
-                    res = aot_call_llvm_intrinsic(comp_ctx, func_ctx,
-                                                  "i64.div_u", param_types[0],
-                                                  param_types, 2, left, right);
+                else {
+                    LLVM_BUILD_OP(SDiv, left, right, res, "div_s", false);
+                }
+                PUSH_INT(res);
+                return true;
+            case INT_DIV_U:
+                intrinsic = is_i32 ? "i32.div_u" : "i64.div_u";
+                if (comp_ctx->disable_llvm_intrinsics
+                    && aot_intrinsic_check_capability(comp_ctx, intrinsic)) {
+                    res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
+                                                  param_types[0], param_types,
+                                                  2, left, right);
                 }
                 else {
                     LLVM_BUILD_OP(UDiv, left, right, res, "div_u", false);
@@ -592,7 +595,15 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 return compile_rems(comp_ctx, func_ctx, left, right, overflow,
                                     is_i32);
             case INT_REM_U:
-                LLVM_BUILD_OP(URem, left, right, res, "rem_u", false);
+                if (comp_ctx->disable_llvm_intrinsics && !is_i32
+                    && aot_intrinsic_check_capability(comp_ctx, "i64.rem_u")) {
+                    res = aot_call_llvm_intrinsic(comp_ctx, func_ctx,
+                                                  "i64.rem_u", param_types[0],
+                                                  param_types, 2, left, right);
+                }
+                else {
+                    LLVM_BUILD_OP(URem, left, right, res, "rem_u", false);
+                }
                 PUSH_INT(res);
                 return true;
             default: