Fix for issue 15412
authorBrian Sullivan <briansul@microsoft.com>
Mon, 11 Dec 2017 19:57:22 +0000 (11:57 -0800)
committerBrian Sullivan <briansul@microsoft.com>
Tue, 12 Dec 2017 22:35:57 +0000 (14:35 -0800)
  Added an IL test case for this issue
  Added the template C# simplearg.cs that was used to create the test case simplearg.il
  Added extra logging around the initial call of impNormStructVal

src/jit/importer.cpp
tests/src/JIT/Directed/RVAInit/simplearg.cs [new file with mode: 0644]
tests/src/JIT/Directed/RVAInit/simplearg.il [new file with mode: 0644]
tests/src/JIT/Directed/RVAInit/simplearg.ilproj [new file with mode: 0644]

index f7513d4..95e98c0 100644 (file)
@@ -852,7 +852,21 @@ GenTreeArgList* Compiler::impPopList(unsigned count, CORINFO_SIG_INFO* sig, GenT
             // Morph trees that aren't already OBJs or MKREFANY to be OBJs
             assert(ti.IsType(TI_STRUCT));
             structType = ti.GetClassHandleForValueClass();
-            temp       = impNormStructVal(temp, structType, (unsigned)CHECK_SPILL_ALL);
+#ifdef DEBUG
+            if (verbose)
+            {
+                printf("Calling impNormStructVal on:\n");
+                gtDispTree(temp);
+            }
+#endif
+            temp = impNormStructVal(temp, structType, (unsigned)CHECK_SPILL_ALL);
+#ifdef DEBUG
+            if (verbose)
+            {
+                printf("resulting tree:\n");
+                gtDispTree(temp);
+            }
+#endif
         }
 
         /* NOTE: we defer bashing the type for I_IMPL to fgMorphArgs */
@@ -1599,7 +1613,7 @@ GenTreePtr Compiler::impNormStructVal(GenTreePtr           structVal,
 
         case GT_COMMA:
         {
-            // The second thing could either be a block node or a GT_SIMD or a GT_COMMA node.
+            // The second thing could either be a block node or a GT_FIELD or a GT_SIMD or a GT_COMMA node.
             GenTree* blockNode = structVal->gtOp.gtOp2;
             assert(blockNode->gtType == structType);
 
@@ -1616,6 +1630,12 @@ GenTreePtr Compiler::impNormStructVal(GenTreePtr           structVal,
                 } while (blockNode->OperGet() == GT_COMMA);
             }
 
+            if (blockNode->OperGet() == GT_FIELD)
+            {
+                // If we have a GT_FIELD then wrap it in a GT_OBJ.
+                blockNode = gtNewObjNode(structHnd, gtNewOperNode(GT_ADDR, TYP_BYREF, blockNode));
+            }
+
 #ifdef FEATURE_SIMD
             if (blockNode->OperGet() == GT_SIMD)
             {
@@ -1625,7 +1645,7 @@ GenTreePtr Compiler::impNormStructVal(GenTreePtr           structVal,
             else
 #endif
             {
-                assert(blockNode->OperIsBlk());
+                noway_assert(blockNode->OperIsBlk());
 
                 // Sink the GT_COMMA below the blockNode addr.
                 // That is GT_COMMA(op1, op2=blockNode) is tranformed into
@@ -1649,7 +1669,7 @@ GenTreePtr Compiler::impNormStructVal(GenTreePtr           structVal,
         break;
 
         default:
-            assert(!"Unexpected node in impNormStructVal()");
+            noway_assert(!"Unexpected node in impNormStructVal()");
             break;
     }
     structVal->gtType  = structType;
diff --git a/tests/src/JIT/Directed/RVAInit/simplearg.cs b/tests/src/JIT/Directed/RVAInit/simplearg.cs
new file mode 100644 (file)
index 0000000..e8fb7f2
--- /dev/null
@@ -0,0 +1,51 @@
+// This is the template C# code from which the simplearg.il test case is derived
+// It was produced by ildasm of the exe produced by this C# program
+// The IL is edited to remove beforefieldinit
+//  and to add an RVA initialization for the field 'Holder.RvaStatic'
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace SimpleArg
+{
+    struct MyValue
+    {
+        public int IntValue;
+        public int PadValue;
+        public long LongValue;
+
+        public MyValue(int init1, long init2) { IntValue = init1; PadValue = 0; LongValue = init2; }
+    }
+
+    class Holder
+    {
+        public static MyValue RvaStatic;
+        public static MyValue NormalStatic = new MyValue(47, 11);
+    }
+
+    class Program
+    {
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static int Method(MyValue arg)
+        {
+            return arg.IntValue;
+        }
+
+        static int Main(string[] args)
+        {
+            int result = Method(Holder.RvaStatic);
+            result += Method(Holder.NormalStatic);
+
+            if (result == 100)
+            {
+                Console.WriteLine("Passed");
+            }
+            else
+            {
+                Console.WriteLine("Failed");
+                Console.WriteLine(result);
+            }
+            return result;
+        }
+    }
+}
diff --git a/tests/src/JIT/Directed/RVAInit/simplearg.il b/tests/src/JIT/Directed/RVAInit/simplearg.il
new file mode 100644 (file)
index 0000000..64975d7
--- /dev/null
@@ -0,0 +1,153 @@
+
+//  Microsoft (R) .NET Framework IL Disassembler.  Version 4.7.3071.0
+//  Copyright (c) Microsoft Corporation.  All rights reserved.
+
+// This is a repro case for GitHub issue #15412 ( https://github.com/dotnet/coreclr/issues/15412 )
+
+// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
+  .ver 4:0:0:0
+}
+.assembly repro2
+{
+  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
+  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
+                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module repro2.exe
+// MVID: {07A1F03C-A750-4BCF-8997-C0AC2CBDB844}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       // WINDOWS_CUI
+.corflags 0x00000001    //  ILONLY
+// Image base: 0x000001BBF9F70000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class private sequential ansi sealed SimpleArg.MyValue
+       extends [mscorlib]System.ValueType
+{
+  .field public int32 IntValue
+  .field public int32 PadValue
+  .field public int64 LongValue
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor(int32 init1,
+                               int64 init2) cil managed
+  {
+    // Code size       22 (0x16)
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ldarg.1
+    IL_0002:  stfld      int32 SimpleArg.MyValue::IntValue
+    IL_0007:  ldarg.0
+    IL_0008:  ldc.i4.0
+    IL_0009:  stfld      int32 SimpleArg.MyValue::PadValue
+    IL_000e:  ldarg.0
+    IL_000f:  ldarg.2
+    IL_0010:  stfld      int64 SimpleArg.MyValue::LongValue
+    IL_0015:  ret
+  } // end of method MyValue::.ctor
+
+} // end of class SimpleArg.MyValue
+
+.class private auto ansi SimpleArg.Holder
+       extends [mscorlib]System.Object
+{
+  .field public static valuetype SimpleArg.MyValue RvaStatic at PreInitValue   // {31, 0, 12 }
+  .field public static valuetype SimpleArg.MyValue NormalStatic                // {69, 0, 11 }
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    // Code size       7 (0x7)
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
+    IL_0006:  ret
+  } // end of method Holder::.ctor
+
+  .method private hidebysig specialname rtspecialname static 
+          void  .cctor() cil managed
+  {
+    // Code size       16 (0x10)
+    .maxstack  8
+    IL_0000:  ldc.i4.s   69
+    IL_0002:  ldc.i4.s   11
+    IL_0004:  conv.i8
+    IL_0005:  newobj     instance void SimpleArg.MyValue::.ctor(int32,
+                                                                int64)
+    IL_000a:  stsfld     valuetype SimpleArg.MyValue SimpleArg.Holder::NormalStatic
+    IL_000f:  ret
+  } // end of method Holder::.cctor
+
+} // end of class SimpleArg.Holder
+
+.class private auto ansi SimpleArg.Program
+       extends [mscorlib]System.Object
+{
+  .method private hidebysig static int32 
+          Method(valuetype SimpleArg.MyValue arg) cil managed noinlining
+  {
+    // Code size       8 (0x8)
+    .maxstack  8
+    IL_0000:  ldarga.s   arg
+    IL_0002:  ldfld      int32 SimpleArg.MyValue::IntValue
+    IL_0007:  ret
+  } // end of method Program::Method
+
+  .method private hidebysig static int32 
+          Main(string[] args) cil managed
+  {
+    .entrypoint
+    // Code size       59 (0x3b)
+    .maxstack  2
+    .locals init (int32 V_0)
+    IL_0000:  ldsfld     valuetype SimpleArg.MyValue SimpleArg.Holder::RvaStatic
+    IL_0005:  call       int32 SimpleArg.Program::Method(valuetype SimpleArg.MyValue)
+    IL_000a:  stloc.0
+    IL_000b:  ldloc.0
+    IL_000c:  ldsfld     valuetype SimpleArg.MyValue SimpleArg.Holder::NormalStatic
+    IL_0011:  call       int32 SimpleArg.Program::Method(valuetype SimpleArg.MyValue)
+    IL_0016:  add
+    IL_0017:  stloc.0
+    IL_0018:  ldloc.0
+    IL_0019:  ldc.i4.s   100
+    IL_001b:  bne.un.s   IL_0029
+
+    IL_001d:  ldstr      "Passed"
+    IL_0022:  call       void [mscorlib]System.Console::WriteLine(string)
+    IL_0027:  br.s       IL_0039
+
+    IL_0029:  ldstr      "Failed"
+    IL_002e:  call       void [mscorlib]System.Console::WriteLine(string)
+    IL_0033:  ldloc.0
+    IL_0034:  call       void [mscorlib]System.Console::WriteLine(int32)
+    IL_0039:  ldloc.0
+    IL_003a:  ret
+  } // end of method Program::Main
+
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    // Code size       7 (0x7)
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
+    IL_0006:  ret
+  } // end of method Program::.ctor
+
+} // end of class SimpleArg.Program
+
+.data PreInitValue = bytearray(1F 00 00 00
+                               00 00 00 00
+                               0C 00 00 00 00 00 00 00)
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file repro2.res
diff --git a/tests/src/JIT/Directed/RVAInit/simplearg.ilproj b/tests/src/JIT/Directed/RVAInit/simplearg.ilproj
new file mode 100644 (file)
index 0000000..224901b
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <RestorePackages>true</RestorePackages>
+    <CLRTestPriority>1</CLRTestPriority>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "></PropertyGroup>
+  <PropertyGroup>
+    <DebugType>PdbOnly</DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup></PropertyGroup>
+  <ItemGroup>
+    <Compile Include="simplearg.il" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
\ No newline at end of file