X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fdecompose.c;h=34e9ee967676146508274945390a747edc07d900;hb=5600f484aa032bddfe71c1d85a80a33a32ae4a92;hp=8fa6bb3eb3c00b8d2165ed54cc2eef8dcee851d6;hpb=0900c61969ca862b0bcc967b4413e539acf07dbb;p=mono.git diff --git a/mono/mini/decompose.c b/mono/mini/decompose.c index 8fa6bb3eb3c..34e9ee96767 100644 --- a/mono/mini/decompose.c +++ b/mono/mini/decompose.c @@ -20,165 +20,15 @@ MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMetho void mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native); void mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass); -/* - * mono_decompose_opcode: - * - * Decompose complex opcodes into ones closer to opcodes supported by - * the given architecture. - * Returns a MonoInst which represents the result of the decomposition, and can - * be pushed on the IL stack. This is needed because the original instruction is - * nullified. - * Sets the cfg exception if an opcode is not supported. - */ -MonoInst* -mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) +/* Decompose complex long opcodes on 64 bit machines or when using LLVM */ +static gboolean +decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins) { MonoInst *repl = NULL; - int type = ins->type; - int dreg = ins->dreg; - - /* FIXME: Instead of = NOP, don't emit the original ins at all */ -#ifdef MONO_ARCH_HAVE_DECOMPOSE_OPTS - mono_arch_decompose_opts (cfg, ins); -#endif + *repl_ins = NULL; - /* - * The code below assumes that we are called immediately after emitting - * ins. This means we can emit code using the normal code generation - * macros. - */ switch (ins->opcode) { - /* this doesn't make sense on ppc and other architectures */ -#if !defined(MONO_ARCH_NO_IOV_CHECK) - case OP_IADD_OVF: - if (COMPILE_LLVM (cfg)) - break; - ins->opcode = OP_IADDCC; - MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException"); - break; - case OP_IADD_OVF_UN: - if (COMPILE_LLVM (cfg)) - break; - ins->opcode = OP_IADDCC; - MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException"); - break; - case OP_ISUB_OVF: - if (COMPILE_LLVM (cfg)) - break; - ins->opcode = OP_ISUBCC; - MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException"); - break; - case OP_ISUB_OVF_UN: - if (COMPILE_LLVM (cfg)) - break; - ins->opcode = OP_ISUBCC; - MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException"); - break; -#endif - case OP_ICONV_TO_OVF_I1: - MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127); - MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException"); - MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -128); - MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1); - NULLIFY_INS (ins); - break; - case OP_ICONV_TO_OVF_I1_UN: - /* probe values between 0 to 127 */ - MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127); - MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1); - NULLIFY_INS (ins); - break; - case OP_ICONV_TO_OVF_U1: - case OP_ICONV_TO_OVF_U1_UN: - /* probe value to be within 0 to 255 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255); - MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xff); - NULLIFY_INS (ins); - break; - case OP_ICONV_TO_OVF_I2: - /* Probe value to be within -32768 and 32767 */ - MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767); - MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException"); - MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -32768); - MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1); - NULLIFY_INS (ins); - break; - case OP_ICONV_TO_OVF_I2_UN: - /* Convert uint value into short, value within 0 and 32767 */ - MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767); - MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1); - NULLIFY_INS (ins); - break; - case OP_ICONV_TO_OVF_U2: - case OP_ICONV_TO_OVF_U2_UN: - /* Probe value to be within 0 and 65535 */ - MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0xffff); - MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xffff); - NULLIFY_INS (ins); - break; - case OP_ICONV_TO_OVF_U4: - case OP_ICONV_TO_OVF_I4_UN: -#if SIZEOF_REGISTER == 4 - case OP_ICONV_TO_OVF_U: - case OP_ICONV_TO_OVF_I_UN: -#endif - MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0); - MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1); - NULLIFY_INS (ins); - break; - case OP_ICONV_TO_I4: - case OP_ICONV_TO_U4: - case OP_ICONV_TO_OVF_I4: - case OP_ICONV_TO_OVF_U4_UN: -#if SIZEOF_REGISTER == 4 - case OP_ICONV_TO_OVF_I: - case OP_ICONV_TO_OVF_U_UN: -#endif - ins->opcode = OP_MOVE; - break; - case OP_ICONV_TO_I: -#if SIZEOF_REGISTER == 8 - ins->opcode = OP_SEXT_I4; -#else - ins->opcode = OP_MOVE; -#endif - break; - case OP_ICONV_TO_U: -#if SIZEOF_REGISTER == 8 - ins->opcode = OP_ZEXT_I4; -#else - ins->opcode = OP_MOVE; -#endif - break; - - case OP_FCONV_TO_R8: - ins->opcode = OP_FMOVE; - break; - - case OP_FCONV_TO_OVF_I1_UN: - case OP_FCONV_TO_OVF_I2_UN: - case OP_FCONV_TO_OVF_I4_UN: - case OP_FCONV_TO_OVF_I8_UN: - case OP_FCONV_TO_OVF_U1_UN: - case OP_FCONV_TO_OVF_U2_UN: - case OP_FCONV_TO_OVF_U4_UN: - case OP_FCONV_TO_OVF_U8_UN: - case OP_FCONV_TO_OVF_I_UN: - case OP_FCONV_TO_OVF_U_UN: - cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM; - cfg->exception_message = g_strdup_printf ("float conv.ovf.un opcodes not supported."); - break; - - /* Long opcodes on 64 bit machines */ -#if SIZEOF_REGISTER == 8 case OP_LCONV_TO_I4: MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_IMM, ins->dreg, ins->sreg1, 0); NULLIFY_INS (ins); @@ -237,7 +87,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) break; case OP_ICONV_TO_OVF_U8: case OP_ICONV_TO_OVF_U: - MONO_EMIT_NEW_COMPARE_IMM (cfg,ins->sreg1, 0); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg,ins->sreg1, 0); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, ins->dreg, ins->sreg1); NULLIFY_INS (ins); @@ -252,88 +102,93 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_I1: - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 127); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 127); MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException"); - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, -128); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -128); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I1, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_I1_UN: - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 127); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 127); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I1, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_U1: /* probe value to be within 0 to 255 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 255); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xff); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_U1_UN: /* probe value to be within 0 to 255 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 255); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xff); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_I2: /* Probe value to be within -32768 and 32767 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 32767); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 32767); MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException"); - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, -32768); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -32768); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I2, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_I2_UN: /* Probe value to be within 0 and 32767 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 32767); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 32767); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I2, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_U2: /* Probe value to be within 0 and 65535 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0xffff); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffff); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xffff); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_U2_UN: /* Probe value to be within 0 and 65535 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0xffff); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffff); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xffff); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_I4: - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0x7fffffff); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0x7fffffff); MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException"); /* The int cast is needed for the VS compiler. See Compiler Warning (level 2) C4146. */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, ((int)-2147483648)); +#if SIZEOF_REGISTER == 8 + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, ((int)-2147483648)); +#else + g_assert (COMPILE_LLVM (cfg)); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -2147483648LL); +#endif MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_I4_UN: - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0x7fffffff); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0x7fffffff); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_U4: - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0xffffffffUL); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffffffffUL); MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, ins->sreg1, 0); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_U4_UN: - MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0xffffffff); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffffffff); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1); NULLIFY_INS (ins); @@ -346,23 +201,194 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) break; case OP_LCONV_TO_OVF_I_UN: case OP_LCONV_TO_OVF_I8_UN: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, ins->sreg1, 0); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; case OP_LCONV_TO_OVF_U8: case OP_LCONV_TO_OVF_U: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, ins->sreg1, 0); + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1); NULLIFY_INS (ins); break; + default: + return FALSE; + } + + *repl_ins = repl; + return TRUE; +} + +/* + * mono_decompose_opcode: + * + * Decompose complex opcodes into ones closer to opcodes supported by + * the given architecture. + * Returns a MonoInst which represents the result of the decomposition, and can + * be pushed on the IL stack. This is needed because the original instruction is + * nullified. + * Sets the cfg exception if an opcode is not supported. + */ +MonoInst* +mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) +{ + MonoInst *repl = NULL; + int type = ins->type; + int dreg = ins->dreg; + + /* FIXME: Instead of = NOP, don't emit the original ins at all */ + +#ifdef MONO_ARCH_HAVE_DECOMPOSE_OPTS + mono_arch_decompose_opts (cfg, ins); +#endif + + /* + * The code below assumes that we are called immediately after emitting + * ins. This means we can emit code using the normal code generation + * macros. + */ + switch (ins->opcode) { + /* this doesn't make sense on ppc and other architectures */ +#if !defined(MONO_ARCH_NO_IOV_CHECK) + case OP_IADD_OVF: + if (COMPILE_LLVM (cfg)) + break; + ins->opcode = OP_IADDCC; + MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException"); + break; + case OP_IADD_OVF_UN: + if (COMPILE_LLVM (cfg)) + break; + ins->opcode = OP_IADDCC; + MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException"); + break; + case OP_ISUB_OVF: + if (COMPILE_LLVM (cfg)) + break; + ins->opcode = OP_ISUBCC; + MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException"); + break; + case OP_ISUB_OVF_UN: + if (COMPILE_LLVM (cfg)) + break; + ins->opcode = OP_ISUBCC; + MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException"); + break; +#endif + case OP_ICONV_TO_OVF_I1: + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127); + MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException"); + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -128); + MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException"); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1); + NULLIFY_INS (ins); + break; + case OP_ICONV_TO_OVF_I1_UN: + /* probe values between 0 to 127 */ + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127); + MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException"); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1); + NULLIFY_INS (ins); + break; + case OP_ICONV_TO_OVF_U1: + case OP_ICONV_TO_OVF_U1_UN: + /* probe value to be within 0 to 255 */ + MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255); + MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException"); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xff); + NULLIFY_INS (ins); + break; + case OP_ICONV_TO_OVF_I2: + /* Probe value to be within -32768 and 32767 */ + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767); + MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException"); + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -32768); + MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException"); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1); + NULLIFY_INS (ins); + break; + case OP_ICONV_TO_OVF_I2_UN: + /* Convert uint value into short, value within 0 and 32767 */ + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767); + MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException"); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1); + NULLIFY_INS (ins); + break; + case OP_ICONV_TO_OVF_U2: + case OP_ICONV_TO_OVF_U2_UN: + /* Probe value to be within 0 and 65535 */ + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0xffff); + MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException"); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xffff); + NULLIFY_INS (ins); + break; + case OP_ICONV_TO_OVF_U4: + case OP_ICONV_TO_OVF_I4_UN: +#if SIZEOF_REGISTER == 4 + case OP_ICONV_TO_OVF_U: + case OP_ICONV_TO_OVF_I_UN: +#endif + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0); + MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException"); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1); + NULLIFY_INS (ins); + break; + case OP_ICONV_TO_I4: + case OP_ICONV_TO_U4: + case OP_ICONV_TO_OVF_I4: + case OP_ICONV_TO_OVF_U4_UN: +#if SIZEOF_REGISTER == 4 + case OP_ICONV_TO_OVF_I: + case OP_ICONV_TO_OVF_U_UN: #endif + ins->opcode = OP_MOVE; + break; + case OP_ICONV_TO_I: +#if SIZEOF_REGISTER == 8 + ins->opcode = OP_SEXT_I4; +#else + ins->opcode = OP_MOVE; +#endif + break; + case OP_ICONV_TO_U: +#if SIZEOF_REGISTER == 8 + ins->opcode = OP_ZEXT_I4; +#else + ins->opcode = OP_MOVE; +#endif + break; + + case OP_FCONV_TO_R8: + ins->opcode = OP_FMOVE; + break; + + case OP_FCONV_TO_OVF_I1_UN: + case OP_FCONV_TO_OVF_I2_UN: + case OP_FCONV_TO_OVF_I4_UN: + case OP_FCONV_TO_OVF_I8_UN: + case OP_FCONV_TO_OVF_U1_UN: + case OP_FCONV_TO_OVF_U2_UN: + case OP_FCONV_TO_OVF_U4_UN: + case OP_FCONV_TO_OVF_U8_UN: + case OP_FCONV_TO_OVF_I_UN: + case OP_FCONV_TO_OVF_U_UN: + cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM; + cfg->exception_message = g_strdup_printf ("float conv.ovf.un opcodes not supported."); + break; default: { MonoJitICallInfo *info; +#if SIZEOF_REGISTER == 8 + if (decompose_long_opcode (cfg, ins, &repl)) + break; +#else + if (COMPILE_LLVM (cfg) && decompose_long_opcode (cfg, ins, &repl)) + break; +#endif + info = mono_find_jit_opcode_emulation (ins->opcode); if (info) { MonoInst **args; @@ -1079,6 +1105,18 @@ mono_decompose_vtype_opts (MonoCompile *cfg) EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, &ins->klass->byval_arg); mini_emit_initobj (cfg, dest, NULL, ins->klass); + + if (cfg->compute_gc_maps) { + MonoInst *tmp; + + /* + * Tell the GC map code that the vtype is considered live after + * the initialization. + */ + MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF); + tmp->inst_c1 = ins->dreg; + MONO_ADD_INS (cfg->cbb, tmp); + } break; case OP_STOREV_MEMBASE: { src_var = get_vreg_to_inst (cfg, ins->sreg1); @@ -1301,13 +1339,16 @@ mono_decompose_array_access_opts (MonoCompile *cfg) for (ins = bb->code; ins; ins = ins->next) { switch (ins->opcode) { case OP_LDLEN: - NEW_LOAD_MEMBASE_FAULT (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1, - G_STRUCT_OFFSET (MonoArray, max_length)); + NEW_LOAD_MEMBASE_FLAGS (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1, + G_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_CONSTANT_LOAD); MONO_ADD_INS (cfg->cbb, dest); break; case OP_BOUNDS_CHECK: MONO_EMIT_NULL_CHECK (cfg, ins->sreg1); - MONO_ARCH_EMIT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2); + if (COMPILE_LLVM (cfg)) + MONO_EMIT_DEFAULT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->flags & MONO_INST_FAULT); + else + MONO_ARCH_EMIT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2); break; case OP_NEWARR: if (cfg->opt & MONO_OPT_SHARED) { @@ -1336,8 +1377,8 @@ mono_decompose_array_access_opts (MonoCompile *cfg) } break; case OP_STRLEN: - MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT (cfg, OP_LOADI4_MEMBASE, ins->dreg, - ins->sreg1, G_STRUCT_OFFSET (MonoString, length)); + MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, ins->dreg, + ins->sreg1, G_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_CONSTANT_LOAD); break; default: break; @@ -1486,6 +1527,7 @@ mono_decompose_soft_float (MonoCompile *cfg) MonoCallInst *call2; MonoInst *iargs [1]; MonoInst *conv; + GSList *l; /* Convert the call into a call returning an int */ MONO_INST_NEW_CALL (cfg, call2, OP_CALL); @@ -1506,6 +1548,10 @@ mono_decompose_soft_float (MonoCompile *cfg) call2->inst.dreg = mono_alloc_ireg (cfg); MONO_ADD_INS (cfg->cbb, (MonoInst*)call2); + /* Remap OUTARG_VT instructions referencing this call */ + for (l = call->outarg_vts; l; l = l->next) + ((MonoInst*)(l->data))->inst_p0 = call2; + /* FIXME: Optimize this */ /* Emit an r4->r8 conversion */