diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 04fb3a2ef9e3a352740c3bf855993e850aa88277..51409f34111971be8684850e27c41fe4a993ea2c 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -6390,7 +6390,15 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; ip += 3; MINT_IN_BREAK; } - MINT_IN_CASE(MINT_CKFINITE) { + MINT_IN_CASE(MINT_CKFINITE_R4) { + float val = LOCAL_VAR (ip [2], float); + if (!mono_isfinite (val)) + THROW_EX (interp_get_exception_arithmetic (frame, ip), ip); + LOCAL_VAR (ip [1], float) = val; + ip += 3; + MINT_IN_BREAK; + } + MINT_IN_CASE(MINT_CKFINITE_R8) { double val = LOCAL_VAR (ip [2], double); if (!mono_isfinite (val)) THROW_EX (interp_get_exception_arithmetic (frame, ip), ip); diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 59f909b24b3659a2360de1a197bee59127c592d8..623711ef5a1dcc67def34107377e07c4a2773593 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -646,7 +646,8 @@ OPDEF(MINT_SHR_I4_IMM, "shr.i4.imm", 4, 1, 1, MintOpShortInt) OPDEF(MINT_SHR_I8_IMM, "shr.i8.imm", 4, 1, 1, MintOpShortInt) -OPDEF(MINT_CKFINITE, "ckfinite", 3, 1, 1, MintOpNoArgs) +OPDEF(MINT_CKFINITE_R4, "ckfinite.r4", 3, 1, 1, MintOpNoArgs) +OPDEF(MINT_CKFINITE_R8, "ckfinite.r8", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_MKREFANY, "mkrefany", 4, 1, 1, MintOpClassToken) OPDEF(MINT_REFANYTYPE, "refanytype", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_REFANYVAL, "refanyval", 4, 1, 1, MintOpNoArgs) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 6e8a5b4d7e18f8b7ade7037ba8c2d363752b1862..6ba370ba518239be93685f9916991e31b2068ea9 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -908,9 +908,9 @@ shift_op(TransformData *td, int mint_op) static int can_store (int st_value, int vt_value) { - if (st_value == STACK_TYPE_O || st_value == STACK_TYPE_MP) + if (st_value == STACK_TYPE_O || st_value == STACK_TYPE_MP || st_value == STACK_TYPE_F) st_value = STACK_TYPE_I; - if (vt_value == STACK_TYPE_O || vt_value == STACK_TYPE_MP) + if (vt_value == STACK_TYPE_O || vt_value == STACK_TYPE_MP || vt_value == STACK_TYPE_F) vt_value = STACK_TYPE_I; return st_value == vt_value; } @@ -1031,11 +1031,19 @@ store_local (TransformData *td, int local) int mt = td->locals [local].mt; CHECK_STACK (td, 1); #if SIZEOF_VOID_P == 8 + // nint and int32 can be used interchangeably. Add implicit conversions. if (td->sp [-1].type == STACK_TYPE_I4 && stack_type [mt] == STACK_TYPE_I8) interp_add_conv (td, td->sp - 1, NULL, STACK_TYPE_I8, MINT_CONV_I8_I4); + else if (td->sp [-1].type == STACK_TYPE_I8 && stack_type [mt] == STACK_TYPE_I4) + interp_add_conv (td, td->sp - 1, NULL, STACK_TYPE_I4, MINT_MOV_8); #endif + if (td->sp [-1].type == STACK_TYPE_R4 && stack_type [mt] == STACK_TYPE_R8) + interp_add_conv (td, td->sp - 1, NULL, STACK_TYPE_R8, MINT_CONV_R8_R4); + else if (td->sp [-1].type == STACK_TYPE_R8 && stack_type [mt] == STACK_TYPE_R4) + interp_add_conv (td, td->sp - 1, NULL, STACK_TYPE_R4, MINT_CONV_R4_R8); + if (!can_store(td->sp [-1].type, stack_type [mt])) { - g_warning("%s.%s: Store local stack type mismatch %d %d", + g_error ("%s.%s: Store local stack type mismatch %d %d", m_class_get_name (td->method->klass), td->method->name, stack_type [mt], td->sp [-1].type); } @@ -6341,15 +6349,22 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, } td->ip += 4; break; - case CEE_CKFINITE: + case CEE_CKFINITE: { CHECK_STACK (td, 1); - interp_add_ins (td, MINT_CKFINITE); + int stack_type = td->sp [-1].type; + switch (stack_type) { + case STACK_TYPE_R4: interp_add_ins (td, MINT_CKFINITE_R4); break; + case STACK_TYPE_R8: interp_add_ins (td, MINT_CKFINITE_R8); break; + default: + g_error ("Invalid stack type"); + } td->sp--; interp_ins_set_sreg (td->last_ins, td->sp [0].local); - push_simple_type (td, STACK_TYPE_R8); + push_simple_type (td, stack_type); interp_ins_set_dreg (td->last_ins, td->sp [-1].local); ++td->ip; break; + } case CEE_MKREFANY: CHECK_STACK (td, 1);