diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index e63528ca4fdaf..bd1807c64d165 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -5745,12 +5745,6 @@ call:; sp [-1].data.l = (gint64)sp [-1].data.f; ++ip; MINT_IN_BREAK; - MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8) - if ((guint64)sp [-1].data.l > G_MAXINT32) - goto overflow_label; - sp [-1].data.i = (gint32)sp [-1].data.l; - ++ip; - MINT_IN_BREAK; MINT_IN_CASE(MINT_BOX) { mono_interp_box (frame, ip, sp); ip += 3; @@ -6016,7 +6010,7 @@ call:; ++ip; MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_OVF_I4_U8) - if (sp [-1].data.l < 0 || sp [-1].data.l > G_MAXINT32) + if ((guint64)sp [-1].data.l > G_MAXINT32) goto overflow_label; sp [-1].data.i = (gint32) sp [-1].data.l; ++ip; diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index ed7f2a66fd14f..15171dcd00e89 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -658,7 +658,6 @@ OPDEF(MINT_CONV_OVF_I4_U8, "conv.ovf.i4.u8", 1, Pop1, Push1, MintOpNoArgs) OPDEF(MINT_CONV_OVF_I4_R4, "conv.ovf.i4.r4", 1, Pop1, Push1, MintOpNoArgs) OPDEF(MINT_CONV_OVF_I4_R8, "conv.ovf.i4.r8", 1, Pop1, Push1, MintOpNoArgs) -OPDEF(MINT_CONV_OVF_I4_UN_I8, "conv.ovf.i4.un.i8", 1, Pop1, Push1, MintOpNoArgs) OPDEF(MINT_CONV_OVF_I4_UN_R8, "conv.ovf.i4.un.r8", 1, Pop1, Push1, MintOpNoArgs) OPDEF(MINT_CONV_OVF_U4_I4, "conv.ovf.u4.i4", 1, Pop1, Push1, MintOpNoArgs) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 71e1c742340e5..3e29bf4ba6d69 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -5059,7 +5059,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, break; case STACK_TYPE_I8: #if SIZEOF_VOID_P == 4 - interp_add_ins (td, MINT_CONV_OVF_I4_UN_I8); + interp_add_ins (td, MINT_CONV_OVF_I4_U8); #endif break; case STACK_TYPE_I4: @@ -6783,6 +6783,14 @@ interp_local_deadce (TransformData *td, int *local_ref_count) result.field_dst = (cast_type)sp->val.field_src; \ break; +#define INTERP_FOLD_CONV_FULL(opcode,stack_type_dst,field_dst,stack_type_src,field_src,cast_type,cond) \ + case opcode: \ + g_assert (sp->val.type == stack_type_src); \ + if (!(cond)) goto cfold_failed; \ + result.type = stack_type_dst; \ + result.field_dst = (cast_type)sp->val.field_src; \ + break; + static InterpInst* interp_fold_unop (TransformData *td, StackContentInfo *sp, InterpInst *ins) { @@ -6835,6 +6843,30 @@ interp_fold_unop (TransformData *td, StackContentInfo *sp, InterpInst *ins) INTERP_FOLD_CONV (MINT_CONV_I8_I4, STACK_VALUE_I8, l, STACK_VALUE_I4, i, gint32); INTERP_FOLD_CONV (MINT_CONV_I8_U4, STACK_VALUE_I8, l, STACK_VALUE_I4, i, guint32); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I1_I4, STACK_VALUE_I4, i, STACK_VALUE_I4, i, gint8, sp [0].val.i >= G_MININT8 && sp [0].val.i <= G_MAXINT8); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I1_I8, STACK_VALUE_I4, i, STACK_VALUE_I8, l, gint8, sp [0].val.l >= G_MININT8 && sp [0].val.l <= G_MAXINT8); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I1_U4, STACK_VALUE_I4, i, STACK_VALUE_I4, i, gint8, sp [0].val.i >= 0 && sp [0].val.i <= G_MAXINT8); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I1_U8, STACK_VALUE_I4, i, STACK_VALUE_I8, l, gint8, sp [0].val.l >= 0 && sp [0].val.l <= G_MAXINT8); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_U1_I4, STACK_VALUE_I4, i, STACK_VALUE_I4, i, guint8, sp [0].val.i >= 0 && sp [0].val.i <= G_MAXUINT8); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_U1_I8, STACK_VALUE_I4, i, STACK_VALUE_I8, l, guint8, sp [0].val.l >= 0 && sp [0].val.l <= G_MAXUINT8); + + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I2_I4, STACK_VALUE_I4, i, STACK_VALUE_I4, i, gint16, sp [0].val.i >= G_MININT16 && sp [0].val.i <= G_MAXINT16); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I2_I8, STACK_VALUE_I4, i, STACK_VALUE_I8, i, gint16, sp [0].val.l >= G_MININT16 && sp [0].val.l <= G_MAXINT16); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I2_U4, STACK_VALUE_I4, i, STACK_VALUE_I4, i, gint16, sp [0].val.i >= 0 && sp [0].val.i <= G_MAXINT16); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I2_U8, STACK_VALUE_I4, i, STACK_VALUE_I8, l, gint16, sp [0].val.l >= 0 && sp [0].val.l <= G_MAXINT16); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_U2_I4, STACK_VALUE_I4, i, STACK_VALUE_I4, i, guint16, sp [0].val.i >= 0 && sp [0].val.i <= G_MAXUINT16); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_U2_I8, STACK_VALUE_I4, i, STACK_VALUE_I8, l, guint16, sp [0].val.l >= 0 && sp [0].val.l <= G_MAXUINT16); + + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I4_U4, STACK_VALUE_I4, i, STACK_VALUE_I4, i, gint32, sp [0].val.i >= 0); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I4_I8, STACK_VALUE_I4, i, STACK_VALUE_I8, l, gint32, sp [0].val.l >= G_MININT32 && sp [0].val.l <= G_MAXINT32); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I4_U8, STACK_VALUE_I4, i, STACK_VALUE_I8, l, gint32, sp [0].val.l >= 0 && sp [0].val.l <= G_MAXINT32); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_U4_I4, STACK_VALUE_I4, i, STACK_VALUE_I4, i, guint32, sp [0].val.i >= 0); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_U4_I8, STACK_VALUE_I4, i, STACK_VALUE_I8, l, guint32, sp [0].val.l >= 0 && sp [0].val.l <= G_MAXINT32); + + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_I8_U8, STACK_VALUE_I8, l, STACK_VALUE_I8, l, gint64, sp [0].val.l >= 0); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_U8_I4, STACK_VALUE_I8, l, STACK_VALUE_I4, i, guint64, sp [0].val.i >= 0); + INTERP_FOLD_CONV_FULL (MINT_CONV_OVF_U8_I8, STACK_VALUE_I8, l, STACK_VALUE_I8, l, guint64, sp [0].val.l >= 0); + default: goto cfold_failed; }