Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/coreclr/src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15512,6 +15512,13 @@ GenTree* Compiler::gtNewTempAssign(
}
#endif

// Added this noway_assert for runtime\issue 44895, to protect against silent bad codegen
//
if ((dstTyp == TYP_STRUCT) && (valTyp == TYP_REF))
{
noway_assert(!"Incompatible types for gtNewTempAssign");
}

// Floating Point assignments can be created during inlining
// see "Zero init inlinee locals:" in fgInlinePrependStatements
// thus we may need to set compFloatingPointUsed to true here.
Expand Down
37 changes: 31 additions & 6 deletions src/coreclr/src/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17619,16 +17619,38 @@ void Compiler::fgMorphStructField(GenTree* tree, GenTree* parent)
}
// Access the promoted field as a field of a non-promoted struct with the same class handle.
}
#ifdef DEBUG
else if (tree->TypeGet() == TYP_STRUCT)
else
{
// The field tree accesses it as a struct, but the promoted lcl var for the field
// says that it has another type. It can happen only if struct promotion faked
// field type for a struct of single field of scalar type aligned at their natural boundary.
// As we already checked this above, we must have a tree with a TYP_STRUCT type
//
assert(tree->TypeGet() == TYP_STRUCT);

// The field tree accesses it as a struct, but the promoted LCL_VAR field
// says that it has another type. This happens when struct promotion unwraps
// a single field struct to get to its ultimate type.
//
// Note that currently, we cannot have a promoted LCL_VAR field with a struct type.
//
// This mismatch in types can lead to problems for some parent node type like GT_RETURN.
// So we check the parent node and only allow this optimization when we have
// a GT_ADDR or a GT_ASG.
//
// Note that for a GT_ASG we have to do some additional work,
// see below after the SetOper(GT_LCL_VAR)
//
if (!parent->OperIs(GT_ADDR, GT_ASG))
{
// Don't transform other operations such as GT_RETURN
//
return;
}
#ifdef DEBUG
// This is an additional DEBUG-only sanity check
//
assert(structPromotionHelper != nullptr);
structPromotionHelper->CheckRetypedAsScalar(field->gtFldHnd, fieldType);
}
#endif // DEBUG
}
}

tree->SetOper(GT_LCL_VAR);
Expand All @@ -17638,6 +17660,9 @@ void Compiler::fgMorphStructField(GenTree* tree, GenTree* parent)

if (parent->gtOper == GT_ASG)
{
// If we are changing the left side of an assignment, we need to set
// these two flags:
//
if (parent->AsOp()->gtOp1 == tree)
{
tree->gtFlags |= GTF_VAR_DEF;
Expand Down
37 changes: 37 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_44895/Runtime_44895.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

public struct Text
{
private readonly string _value;
public Text(string value) => _value = value;
public string Value => _value ?? string.Empty;
}

public class TextProperty
{
public Text GetValue(Text? a = null, Text? b = null, Text? c = null, Text? d = null)
{
if (a.HasValue) return a.Value;
if (b.HasValue) return b.Value;
if (c.HasValue) return c.Value;
if (d.HasValue) return d.Value;
return default;
}
}

public class Repro
{
public static int Main()
{
string test = "test";
TextProperty t = new TextProperty();
Text gv = t.GetValue(new Text(test));
bool result = test.Equals(gv.Value);
Console.WriteLine(result ? "Pass" : "Fail");
if (!result) Console.WriteLine($"got '{gv.Value}', expected '{test}'");
return result ? 100 : -1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>