Skip to content

Commit 2ec2c9b

Browse files
committed
Port fix for dotnet#1241 to 3.1
1 parent 5558d18 commit 2ec2c9b

File tree

3 files changed

+123
-12
lines changed

3 files changed

+123
-12
lines changed

src/jit/morph.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10186,6 +10186,7 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
1018610186
GenTreeLclVarCommon* lclVarTree = nullptr;
1018710187
GenTreeLclVarCommon* srcLclVarTree = nullptr;
1018810188
unsigned destLclNum = BAD_VAR_NUM;
10189+
unsigned modifiedLclNum = BAD_VAR_NUM;
1018910190
LclVarDsc* destLclVar = nullptr;
1019010191
FieldSeqNode* destFldSeq = nullptr;
1019110192
bool destDoFldAsg = false;
@@ -10201,10 +10202,11 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
1020110202
{
1020210203
blockWidthIsConst = true;
1020310204
destOnStack = true;
10205+
modifiedLclNum = dest->AsLclVarCommon()->GetLclNum();
1020410206
if (dest->gtOper == GT_LCL_VAR)
1020510207
{
1020610208
lclVarTree = dest->AsLclVarCommon();
10207-
destLclNum = lclVarTree->gtLclNum;
10209+
destLclNum = modifiedLclNum;
1020810210
destLclVar = &lvaTable[destLclNum];
1020910211
if (destLclVar->lvType == TYP_STRUCT)
1021010212
{
@@ -10259,26 +10261,27 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
1025910261
noway_assert(destAddr->TypeGet() == TYP_BYREF || destAddr->TypeGet() == TYP_I_IMPL);
1026010262
if (destAddr->IsLocalAddrExpr(this, &lclVarTree, &destFldSeq))
1026110263
{
10262-
destOnStack = true;
10263-
destLclNum = lclVarTree->gtLclNum;
10264-
destLclVar = &lvaTable[destLclNum];
10264+
destOnStack = true;
10265+
destLclNum = lclVarTree->GetLclNum();
10266+
modifiedLclNum = destLclNum;
10267+
destLclVar = &lvaTable[destLclNum];
1026510268
}
1026610269
}
1026710270
}
1026810271

10269-
if (destLclVar != nullptr)
10270-
{
1027110272
#if LOCAL_ASSERTION_PROP
10272-
// Kill everything about destLclNum (and its field locals)
10273-
if (optLocalAssertionProp)
10273+
// Kill everything about modifiedLclNum (and its field locals)
10274+
if ((modifiedLclNum != BAD_VAR_NUM) && optLocalAssertionProp)
10275+
{
10276+
if (optAssertionCount > 0)
1027410277
{
10275-
if (optAssertionCount > 0)
10276-
{
10277-
fgKillDependentAssertions(destLclNum DEBUGARG(tree));
10278-
}
10278+
fgKillDependentAssertions(modifiedLclNum DEBUGARG(tree));
1027910279
}
10280+
}
1028010281
#endif // LOCAL_ASSERTION_PROP
1028110282

10283+
if (destLclVar != nullptr)
10284+
{
1028210285
if (destLclVar->lvPromoted && blockWidthIsConst)
1028310286
{
1028410287
noway_assert(varTypeIsStruct(destLclVar));
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Linq;
7+
using System.Numerics;
8+
using System.Runtime.CompilerServices;
9+
10+
namespace Runtime_1241
11+
{
12+
13+
public struct Vertex
14+
{
15+
public Vector3 Position;
16+
public Vector2 TexCoords;
17+
18+
public Vertex(Vector3 pos, Vector2 tex)
19+
{
20+
Position = pos;
21+
TexCoords = tex;
22+
}
23+
}
24+
25+
class Program
26+
{
27+
static int Main()
28+
{
29+
int returnVal = 100;
30+
31+
// This prints all zeros in the failure case.
32+
Console.WriteLine("Replacing array element with new struct directly");
33+
{
34+
var bug = Bug.Create();
35+
bug.MutateBroken();
36+
37+
Console.WriteLine(bug.Vertices[0].Position);
38+
if ((bug.Vertices[0].Position.X != 1) || (bug.Vertices[0].Position.Y != 1) || (bug.Vertices[0].Position.Z != 1))
39+
{
40+
returnVal = -1;
41+
}
42+
}
43+
44+
// Works
45+
Console.WriteLine("Replacing array element with new struct, stored in a local variable first");
46+
{
47+
var bug = Bug.Create();
48+
bug.MutateWorks();
49+
50+
Console.WriteLine(bug.Vertices[0].Position);
51+
if ((bug.Vertices[0].Position.X != 1) || (bug.Vertices[0].Position.Y != 1) || (bug.Vertices[0].Position.Z != 1))
52+
{
53+
returnVal = -1;
54+
}
55+
}
56+
57+
return returnVal;
58+
}
59+
}
60+
61+
public class Bug
62+
{
63+
public static Bug Create()
64+
{
65+
return new Bug
66+
{
67+
Vertices = Enumerable.Range(1, 100).Select(i => new Vertex(new Vector3(i), Vector2.One)).ToArray()
68+
};
69+
}
70+
71+
public Vertex[] Vertices { get; set; }
72+
73+
public void MutateBroken()
74+
{
75+
for (var i = 0; i < Vertices.Length; i++)
76+
{
77+
var vert = Vertices[i];
78+
79+
Vertices[i] = new Vertex(vert.Position, vert.TexCoords);
80+
}
81+
}
82+
83+
public void MutateWorks()
84+
{
85+
for (var i = 0; i < Vertices.Length; i++)
86+
{
87+
var vert = Vertices[i];
88+
89+
var newVert = new Vertex(vert.Position, vert.TexCoords);
90+
91+
Vertices[i] = newVert;
92+
}
93+
}
94+
}
95+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<CLRTestPriority>1</CLRTestPriority>
5+
</PropertyGroup>
6+
<PropertyGroup>
7+
<DebugType />
8+
<Optimize>True</Optimize>
9+
</PropertyGroup>
10+
<ItemGroup>
11+
<Compile Include="$(MSBuildProjectName).cs" />
12+
</ItemGroup>
13+
</Project>

0 commit comments

Comments
 (0)