From 0b8a90419309a5db65c65127d7a86aedf36240f1 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 15 Nov 2023 18:30:51 +0800 Subject: [PATCH] Fix fast-jit callnative translation (#2765) Lock i32 registers before and after preparing the function arguments to prevent they are overwritten. --- core/iwasm/fast-jit/fe/jit_emit_function.c | 34 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/core/iwasm/fast-jit/fe/jit_emit_function.c b/core/iwasm/fast-jit/fe/jit_emit_function.c index 3ac9e3ed6..43a71e26a 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_function.c +++ b/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: