summaryrefslogtreecommitdiff
path: root/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il
blob: 9c9ba4946cf4e60d963579ff64db7e43800e6497 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

.assembly extern mscorlib {}
.assembly a {}
.module a.exe

// This test originally triggered an assert when computing the value number for a block assignment. In particular, the
// VN framework expected any block assignments to a tracked lclVar to have a destination address of the form
// `(addr (lclVar))` or `(addr (lclFld))`. The check that it was using to determine whether or not a block assignment
// targets a lclVar also admitted addresses formed by some combination of adds of constants to these patterns (e.g.
// `(add (const 4) (add (addr lclVar) (const 4)))`. The bits of IL that trigger the assert are called out in the method
// bodies below. They differ for 32- and 64-bit targets because on 64-bit targets, the importer will insert an
// int->long conversion when adding a constant int to any long. Due to the cast, the resulting IR is not considered to
// be an add of a constant and a lclVar address. In order to repro the bug on a 64-bit target, the input IL must
// directly produce a long constant.

.class private sequential ansi sealed beforefieldinit S extends [mscorlib]System.ValueType
{
    .field public uint8 m_fld
    .field public uint8 m_fld1
    .field public uint8 m_fld2
    .field public uint8 m_fld3
    .field public uint8 m_fld4
    .field public uint8 m_fld5
    .field public uint8 m_fld6
}

.class private sequential ansi sealed beforefieldinit T extends [mscorlib]System.ValueType
{
    .field public int32 m_int
    .field public valuetype S m_fld
}

.class private abstract auto ansi sealed beforefieldinit C extends [mscorlib]System.Object
{
    .method private static int32 Test32Bit(int32 i) noinlining
    {
        .locals init (valuetype S V_0, valuetype T V_1)

        ldloca.s V_0
        ldarg.0
        conv.u1
        stfld uint8 S::m_fld6

        // This sequence of IL repros the issue.
        ldloca.s V_1
        ldc.i4.4
        add
        ldloc.0
        stobj S

        ldloca.s V_1
        ldfld valuetype S T::m_fld
        ldfld uint8 S::m_fld6
        conv.i4
        ret
    }

    .method private static int32 Test64Bit(int32 i) noinlining
    {
        .locals init (valuetype S V_0, valuetype T V_1)

        ldloca.s V_0
        ldarg.0
        conv.u1
        stfld uint8 S::m_fld6

        // This sequence of IL repros the issue. Note that the `ldc.i8` is necessary (rather than an `ldc.i4` that is
        // implicitly converted to a long byt the `add`).
        ldloca.s V_1
        ldc.i8 4
        add
        ldloc.0
        stobj S

        ldloca.s V_1
        ldfld valuetype S T::m_fld
        ldfld uint8 S::m_fld6
        conv.i4
        ret
    }

    .method private static int32 Main()
    {
        .entrypoint
        .locals init (int32 V_0)

        ldc.i4 100
        dup

        sizeof [mscorlib]System.IntPtr
        ldc.i4 8
        beq.s _64bit

        call int32 C::Test32Bit(int32)
        bne.un.s fail
        br.s success

_64bit:
        call int32 C::Test64Bit(int32)
        bne.un.s fail

success:
        ldc.i4 100
        ret

fail:
        ldc.i4 101
        ret
    }
}