[mono][interp] Fix a few local store warnings (#66766)
authorVlad Brezae <brezaevlad@gmail.com>
Mon, 21 Mar 2022 14:18:33 +0000 (16:18 +0200)
committerGitHub <noreply@github.com>
Mon, 21 Mar 2022 14:18:33 +0000 (16:18 +0200)
* [mono][interp] Fix warning when storing function pointers

* [mono][interp] Fix storing of R4 or R8 into local of different size

The IL execution stack operates on generic floating type F, which can be stored in local of both float32 or float64. We however operate on the real types and need to add implicit conversions if necessary.

* [mono][interp] Fix ckfinite

It was previously handling only R8 correctly.

* [mono][interp] Add implicit conversion between nint and int32

* [mono][interp] Change warning to error

src/mono/mono/mini/interp/interp.c
src/mono/mono/mini/interp/mintops.def
src/mono/mono/mini/interp/transform.c

index 04fb3a2..51409f3 100644 (file)
@@ -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);
index 59f909b..623711e 100644 (file)
@@ -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)
index 6e8a5b4..6ba370b 100644 (file)
@@ -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);