[jit] Fix is_reference checks for intrinsics with byref parameters. (mono/mono#17338)
authorZoltan Varga <vargaz@gmail.com>
Wed, 16 Oct 2019 01:45:04 +0000 (21:45 -0400)
committerGitHub <noreply@github.com>
Wed, 16 Oct 2019 01:45:04 +0000 (21:45 -0400)
Found by https://github.com/mono/mono/issues/17335.

Commit migrated from https://github.com/mono/mono/commit/08e8a7f2c3c43366358901d304bfe2808962577a

src/mono/mono/mini/intrinsics.c

index f9b5eb3..db08645 100644 (file)
@@ -638,6 +638,14 @@ emit_jit_helpers_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSi
        return NULL;
 }
 
+static gboolean
+byref_arg_is_reference (MonoType *t)
+{
+       g_assert (t->byref);
+
+       return mini_type_is_reference (m_class_get_byval_arg (mono_class_from_mono_type_internal (t)));
+}
+
 MonoInst*
 mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
 {
@@ -933,9 +941,9 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        return ins;
                } else if (strcmp (cmethod->name, "MemoryBarrier") == 0 && fsig->param_count == 0) {
                        return mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
-               } else if (!strcmp (cmethod->name, "VolatileRead") && fsig->param_count == 1) {
+               } else if (!strcmp (cmethod->name, "VolatileRead") && fsig->param_count == 1 && fsig->params [0]->byref) {
                        guint32 opcode = 0;
-                       gboolean is_ref = mini_type_is_reference (fsig->params [0]);
+                       gboolean is_ref = byref_arg_is_reference (fsig->params [0]);
 
                        if (fsig->params [0]->type == MONO_TYPE_I1)
                                opcode = OP_LOADI1_MEMBASE;
@@ -1007,9 +1015,9 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
 
                                return ins;
                        }
-               } else if (!strcmp (cmethod->name, "VolatileWrite") && fsig->param_count == 2) {
+               } else if (!strcmp (cmethod->name, "VolatileWrite") && fsig->param_count == 2 && fsig->params [0]->byref) {
                        guint32 opcode = 0;
-                       gboolean is_ref = mini_type_is_reference (fsig->params [0]);
+                       gboolean is_ref = byref_arg_is_reference (fsig->params [0]);
 
                        if (fsig->params [0]->type == MONO_TYPE_I1 || fsig->params [0]->type == MONO_TYPE_U1)
                                opcode = OP_STOREI1_MEMBASE_REG;
@@ -1154,10 +1162,10 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                                MONO_ADD_INS (cfg->cbb, ins);
                        }
                }
-               else if (strcmp (cmethod->name, "Exchange") == 0 && fsig->param_count == 2) {
+               else if (strcmp (cmethod->name, "Exchange") == 0 && fsig->param_count == 2 && fsig->params [0]->byref) {
                        MonoInst *f2i = NULL, *i2f;
                        guint32 opcode, f2i_opcode, i2f_opcode;
-                       gboolean is_ref = mini_type_is_reference (fsig->params [0]);
+                       gboolean is_ref = byref_arg_is_reference (fsig->params [0]);
                        gboolean is_float = fsig->params [0]->type == MONO_TYPE_R4 || fsig->params [0]->type == MONO_TYPE_R8;
 
                        if (fsig->params [0]->type == MONO_TYPE_I4 ||
@@ -1230,7 +1238,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                                ins->type = STACK_R8;
                                break;
                        default:
-                               g_assert (mini_type_is_reference (fsig->params [0]));
+                               g_assert (is_ref);
                                ins->type = STACK_OBJ;
                                break;
                        }
@@ -1405,8 +1413,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        gboolean is_float = t->type == MONO_TYPE_R4 || t->type == MONO_TYPE_R8;
 
                        g_assert (t->byref);
-                       /* t is a byref type, so the reference check is more complicated */
-                       is_ref = mini_type_is_reference (m_class_get_byval_arg (mono_class_from_mono_type_internal (t)));
+                       is_ref = byref_arg_is_reference (t);
                        if (t->type == MONO_TYPE_I1)
                                opcode = OP_ATOMIC_LOAD_I1;
                        else if (t->type == MONO_TYPE_U1 || t->type == MONO_TYPE_BOOLEAN)
@@ -1487,7 +1494,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        gboolean is_ref;
 
                        g_assert (t->byref);
-                       is_ref = mini_type_is_reference (m_class_get_byval_arg (mono_class_from_mono_type_internal (t)));
+                       is_ref = byref_arg_is_reference (t);
                        if (t->type == MONO_TYPE_I1)
                                opcode = OP_ATOMIC_STORE_I1;
                        else if (t->type == MONO_TYPE_U1 || t->type == MONO_TYPE_BOOLEAN)