From 3a1fe1c959f7820d006e59bf9da0d5278168cc97 Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Tue, 25 Jul 2017 15:43:05 -0700 Subject: Treat byref-typed uses of int-typed lclVars as type int in LB. This is consistent with the behvaior of both JIT32 and RyuJIT. This resolves an assertion originating from the following scenario: 1. The input IL contains a lclVar of type `Foo*`, which the JIT imports as `TYP_I_IMPL` (which is `TYP_INT` in this case). 2. This lclVar is used as the `this` argument to a number of method calls. This is legal as per ECMA-335 section III.3.19 ("Correct CIL also allows a native int to be passed as a byref (&); in which case following the store the value will be tracked by garbage collection.") 3. All of the method calls to which this lclVar is passed as a byref are inlined. This produces many uses of the lclVar as a byref (i.e. we see nodes like `lclVar V06 byref` even though V06's varDsc has type int). 4. The lclVar is assigned a register `r`. At its first appearance--which is the first occasion in which it is loaded into this register--it is used as `TYP_BYREF`. When the code generator processes this appearance, it first sets the appropriate bit for `r` in `gcInfo.gcRegByrefSetCur` (`gcInfo.gcMarkRegPtrVal`, called by `genCodeForTree_REG_VAR1`) and then sets the appropriate bit for `r` in `regSet.rsMaskVars` (`genUpdateLife`). 5. The lclVar is used as `TYP_INT` as the operand to a `GT_RETURN` node. When the code generator processes this appearance, it attempts to update the GC-ness of `r` by calling `gcInfo.gcMarkRegPtrVal` (again via `genCodeForTree_REG_VAR1`). This function, though, explicitly excludes registers that contain live variables from its update, so `r` remains in `gcInfo.gcRegByrefSetCur` after this call. After calling `gcMarkRegPtrVal`, `genCodeForTree_REG_VAR1` calls `genUpdateLife`, which removes the the lclVar from `regSet.rsMaskVars`. 6. An assertion intended to verify that the only registers that are live after processing a statement are registers that contain lclVars fires, as `gcRegByrefSetCur` still contains `r`. Fixes VSO 468732. --- .../JitBlue/DevDiv_468732/DevDiv_468732.cs | 30 +++++++++++++++ .../JitBlue/DevDiv_468732/DevDiv_468732.csproj | 43 ++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.csproj (limited to 'tests/src/JIT/Regression') diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.cs new file mode 100644 index 0000000000..6b184038ae --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.cs @@ -0,0 +1,30 @@ +// 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. + +// Repro case for a bug involving byref-typed appearances of int-typed lclVars. + +using System.Runtime.CompilerServices; + +struct S +{ + int i; + + void N() + { + i = 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static unsafe S* Test(S* s) + { + s->N(); + return s; + } + + static unsafe int Main() + { + S s; + return Test(&s)->i; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.csproj new file mode 100644 index 0000000000..d072caa451 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.csproj @@ -0,0 +1,43 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {1D93D1C3-458A-44ED-ABCC-7D0739B28C92} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + True + + + + + + + + + + + -- cgit v1.2.3