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
}
}
|