From 40fd93762b2dec79594fe498503c2aa5415d1625 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 3 Jul 2025 15:30:03 +0300 Subject: [PATCH] [mono][interp] Sign extend I4 return value since jit-ed code expects it --- src/mono/mono/mini/method-to-ir.c | 8 ++++---- src/mono/mono/mini/mini-amd64.c | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 91e7b446a5316a..1519f04131a099 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -2238,12 +2238,12 @@ mono_emit_widen_call_res (MonoCompile *cfg, MonoInst *ins, MonoMethodSignature * // LLVM code doesn't uses zero extend the full word while jit expects it. // A proper fix would be to detect if we are actually using llvm code from aot images // or make sure llvm code actually zero extends the return. -#ifdef MONO_ARCH_LLVM_SUPPORTED - gboolean might_use_llvm = TRUE; +#if defined(MONO_ARCH_LLVM_SUPPORTED) || defined(MONO_ARCH_INTERPRETER_SUPPORTED) + gboolean might_use_llvm_or_interp = TRUE; #else - gboolean might_use_llvm = FALSE; + gboolean might_use_llvm_or_interp = FALSE; #endif - if ((fsig->pinvoke || might_use_llvm) && !m_type_is_byref (fsig->ret)) { + if ((fsig->pinvoke || might_use_llvm_or_interp) && !m_type_is_byref (fsig->ret)) { int widen_op = -1; /* diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index cb6002dd87630c..a83b8ee23ac56c 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -1473,6 +1473,12 @@ mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, Mo interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage); if (temp_size) arg_set_val (ccontext, ainfo, storage); + + // amd64 backend expects I4 return value to be sign extended. Smaller integer types + // are extended in mono_emit_widen_call_res. On arm64, caller always does the sign + // extend for I4 in emit_move_return_value. + if (sig->ret->type == MONO_TYPE_I4 && ainfo->storage == ArgInIReg && ainfo->reg == AMD64_RAX) + ccontext->gregs [AMD64_RAX] = (gint64)*(gint32*)storage; } }