From 30cddad5fb4c3d290906a6e6c33ecd8b07d8b48c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 2 Oct 2017 16:26:17 +0200 Subject: [PATCH] [jit] Fix the saving of the 'cfg->ret_var_set' flag when inlining, it was set to FALSE before it was saved, causing invalid code to be generated in some cases when doing nested inlining. Fixes #59608. (#5654) --- mono/mini/iltests.il | 47 ++++++++++++++++++++++++++++++++++++++++ mono/mini/method-to-ir.c | 9 ++++---- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/mono/mini/iltests.il b/mono/mini/iltests.il index b5796520341..30419d9178a 100644 --- a/mono/mini/iltests.il +++ b/mono/mini/iltests.il @@ -3044,4 +3044,51 @@ L_3: valuetype [mscorlib]System.Decimal) IL_0028: ret } + + .method private hidebysig static void fail_inline() cil managed + { + // Code size 9 (0x9) + .maxstack 8 + IL_0000: ldc.i4.s 16 + IL_0002: conv.u + IL_0003: ldc.i4.1 + IL_0004: mul.ovf.un + IL_0005: localloc + IL_0007: pop + IL_0008: ret + } + + .method private hidebysig static int32 + always_inline(int32 op) cil managed aggressiveinlining + { + // Code size 24 (0x18) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0009 + + IL_0003: ldarg.0 + IL_0004: ldc.i4.2 + IL_0005: beq.s IL_000b + + IL_0007: br.s IL_000d + + IL_0009: ldc.i4.0 + IL_000a: ret + + IL_000b: ldc.i4.3 + IL_000c: ret + + IL_000d: call void Tests::fail_inline() + IL_0012: newobj instance void [mscorlib]System.Exception::.ctor() + IL_0017: throw + } + + .method public hidebysig static int32 test_3_regress_59608() cil managed + { + .maxstack 8 + IL_0000: ldc.i4.2 + IL_0001: call int32 Tests::always_inline(int32) + IL_000c: ret + } + } diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 3ac76cdfd8d..ce326f3c2d3 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -6134,9 +6134,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, prev_args = cfg->args; prev_arg_types = cfg->arg_types; prev_inlined_method = cfg->inlined_method; - cfg->inlined_method = cmethod; - cfg->ret_var_set = FALSE; - cfg->inline_depth ++; + prev_ret_var_set = cfg->ret_var_set; prev_real_offset = cfg->real_offset; prev_cbb_hash = cfg->cbb_hash; prev_cil_offset_to_bb = cfg->cil_offset_to_bb; @@ -6146,9 +6144,12 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, prev_cbb = cfg->cbb; prev_current_method = cfg->current_method; prev_generic_context = cfg->generic_context; - prev_ret_var_set = cfg->ret_var_set; prev_disable_inline = cfg->disable_inline; + cfg->inlined_method = cmethod; + cfg->ret_var_set = FALSE; + cfg->inline_depth ++; + if (ip && *ip == CEE_CALLVIRT && !(cmethod->flags & METHOD_ATTRIBUTE_STATIC)) virtual_ = TRUE; -- 2.25.1