IL_0018: ldloc.0
ret
}
+
+ .field private static int32 byte_val
+ .field private static int32 short_val
+
+ .method public static int32 test_0_implicit_widen_or_local_stores () cil managed
+ {
+ .maxstack 1
+ .locals init (
+ unsigned int8 V_0,
+ int8 V_1,
+ int16 V_2,
+ unsigned int16 V_3)
+
+ ldc.i4 256
+ stsfld int32 Tests::byte_val
+ ldc.i4 65536
+ stsfld int32 Tests::short_val
+
+ ldsfld int32 Tests::byte_val
+ stloc.0
+ ldloc.0
+ brfalse L_0
+
+ ldc.i4.1
+ ret
+L_0:
+ ldsfld int32 Tests::byte_val
+ stloc.1
+ ldloc.1
+ conv.i4
+ brfalse L_1
+
+ ldc.i4.2
+ ret
+L_1:
+ ldsfld int32 Tests::short_val
+ stloc.2
+ ldloc.2
+ brfalse L_2
+
+ ldc.i4.3
+ ret
+L_2:
+ ldsfld int32 Tests::short_val
+ stloc.3
+ ldloc.3
+ brfalse L_3
+
+ ldc.i4.4
+ ret
+L_3:
+ ldc.i4.0
+ ret
+ }
}
cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
}
+static guint32
+mono_type_to_stloc_coerce (MonoType *type)
+{
+ if (type->byref)
+ return 0;
+
+ type = mini_get_underlying_type (type);
+handle_enum:
+ switch (type->type) {
+ case MONO_TYPE_I1:
+ return OP_ICONV_TO_I1;
+ case MONO_TYPE_U1:
+ return OP_ICONV_TO_U1;
+ case MONO_TYPE_I2:
+ return OP_ICONV_TO_I2;
+ case MONO_TYPE_U2:
+ return OP_ICONV_TO_U2;
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ case MONO_TYPE_TYPEDBYREF:
+ case MONO_TYPE_GENERICINST:
+ return 0;
+ case MONO_TYPE_VALUETYPE:
+ if (type->data.klass->enumtype) {
+ type = mono_class_enum_basetype (type->data.klass);
+ goto handle_enum;
+ }
+ return 0;
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR: //TODO I believe we don't need to handle gsharedvt as there won't be match and, for example, u1 is not covariant to u32
+ return 0;
+ default:
+ g_error ("unknown type 0x%02x in mono_type_to_stloc_coerce", type->type);
+ }
+ return -1;
+}
+
static void
emit_stloc_ir (MonoCompile *cfg, MonoInst **sp, MonoMethodHeader *header, int n)
{
MonoInst *ins;
+ guint32 coerce_op = mono_type_to_stloc_coerce (header->locals [n]);
+
+ if (coerce_op) {
+ if (cfg->cbb->last_ins == sp [0] && sp [0]->opcode == coerce_op) {
+ if (cfg->verbose_level > 2)
+ printf ("Found existing coercing that is enough\n");
+ } else {
+ MONO_INST_NEW (cfg, ins, coerce_op);
+ ins->dreg = alloc_ireg (cfg);
+ ins->sreg1 = sp [0]->dreg;
+ ins->type = STACK_I4;
+ ins->klass = mono_class_from_mono_type (header->locals [n]);
+ MONO_ADD_INS (cfg->cbb, ins);
+ *sp = mono_decompose_opcode (cfg, ins);
+ }
+ }
+
+
guint32 opcode = mono_type_to_regmove (cfg, header->locals [n]);
if ((opcode == OP_MOVE) && cfg->cbb->last_ins == sp [0] &&
((sp [0]->opcode == OP_ICONST) || (sp [0]->opcode == OP_I8CONST))) {