Переглянути джерело

Fix fast-jit callnative translation (#2765)

Lock i32 registers before and after preparing the function arguments
to prevent they are overwritten.
Wenyong Huang 2 роки тому
батько
коміт
0b8a904193
1 змінених файлів з 32 додано та 2 видалено
  1. 32 2
      core/iwasm/fast-jit/fe/jit_emit_function.c

+ 32 - 2
core/iwasm/fast-jit/fe/jit_emit_function.c

@@ -827,23 +827,45 @@ emit_callnative(JitCompContext *cc, JitReg native_func_reg, JitReg res,
                 JitReg *params, uint32 param_count)
 {
     JitInsn *insn;
+    char *i32_arg_names[] = { "edi", "esi", "edx", "ecx" };
     char *i64_arg_names[] = { "rdi", "rsi", "rdx", "rcx", "r8", "r9" };
     char *f32_arg_names[] = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" };
     char *f64_arg_names[] = { "xmm0_f64", "xmm1_f64", "xmm2_f64",
                               "xmm3_f64", "xmm4_f64", "xmm5_f64" };
-    JitReg i64_arg_regs[6], f32_arg_regs[6], f64_arg_regs[6], res_reg = 0;
+    JitReg i32_arg_regs[4], i64_arg_regs[6];
+    JitReg f32_arg_regs[6], f64_arg_regs[6], res_reg = 0;
     JitReg eax_hreg = jit_codegen_get_hreg_by_name("eax");
     JitReg xmm0_hreg = jit_codegen_get_hreg_by_name("xmm0");
-    uint32 i, i64_reg_idx, float_reg_idx;
+    uint32 i, i64_reg_idx, float_reg_idx, lock_i32_reg_num;
 
     bh_assert(param_count <= 6);
 
+    for (i = 0; i < 4; i++) {
+        i32_arg_regs[i] = jit_codegen_get_hreg_by_name(i32_arg_names[i]);
+    }
+
     for (i = 0; i < 6; i++) {
         i64_arg_regs[i] = jit_codegen_get_hreg_by_name(i64_arg_names[i]);
         f32_arg_regs[i] = jit_codegen_get_hreg_by_name(f32_arg_names[i]);
         f64_arg_regs[i] = jit_codegen_get_hreg_by_name(f64_arg_names[i]);
     }
 
+    lock_i32_reg_num = param_count < 4 ? param_count : 4;
+
+    /*
+     * Lock i32 registers so that they won't be allocated for the operand
+     * of below I32TOI64 insn, which may have been overwritten in the
+     * previous MOV, for example, in the below insns:
+     *   MOV             I5, I15
+     *   I32TOI64        I6, i5
+     *   CALLNATIVE      VOID, native_func, I5, I6
+     * i5 is used in the second insn, but it has been overwritten in I5
+     * by the first insn
+     */
+    for (i = 0; i < lock_i32_reg_num; i++) {
+        GEN_INSN(MOV, i32_arg_regs[i], i32_arg_regs[i]);
+    }
+
     i64_reg_idx = float_reg_idx = 0;
     for (i = 0; i < param_count; i++) {
         switch (jit_reg_kind(params[i])) {
@@ -865,6 +887,14 @@ emit_callnative(JitCompContext *cc, JitReg native_func_reg, JitReg res,
         }
     }
 
+    /*
+     * Announce the locked i32 registers are being used, and do necessary
+     * spill ASAP
+     */
+    for (i = 0; i < lock_i32_reg_num; i++) {
+        GEN_INSN(MOV, i32_arg_regs[i], i32_arg_regs[i]);
+    }
+
     if (res) {
         switch (jit_reg_kind(res)) {
             case JIT_REG_KIND_I32: