Skip to content

Commit

Permalink
Jit: Fix SetIndirExceptionFlags.
Browse files Browse the repository at this point in the history
SetIndirExceptionFlags should not set `GTF_IND_NONFAULTING` flag if the
address has `GTF_EXCEPT` flag.

The failing scenario was:

We were setting `GTF_IND_NONFAULTING` on this indirection (since `ADDR` Node
can't be null)

```
               [000003] *--XG-------              *  IND       int
               [000002] ---XG-------              \--*  ADDR      byref  Zero Fseq[i]
               [000001] ---XG-------                 \--*  FIELD     struct s
               [000000] ------------                    \--*  LCL_VAR   ref    V00 arg0
```
this was then transformed to

```
               [000003] *---G-------              *  IND       int
               [000013] -----+------              \--*  ADD       byref
               [000000] -----+------                 +--*  LCL_VAR   ref    V00 arg0
               [000012] -----+------                 \--*  CNS_INT   long   8 field offset Fseq[s, i]
```
The `GTF_EXCEPT` flag was cleared on `IND` because it had `GTF_IND_NONFAULTING`set
and the address no longer had  `GTF_EXCEPT` flag.

Fixes dotnet/coreclr#27027.


Commit migrated from dotnet/coreclr@f58ce06
  • Loading branch information
erozenfeld committed Oct 11, 2019
1 parent e6c64c6 commit 45ca544
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 18 deletions.
34 changes: 33 additions & 1 deletion src/coreclr/src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7953,7 +7953,7 @@ void Compiler::gtUpdateNodeOperSideEffects(GenTree* tree)
tree->gtFlags &= ~GTF_EXCEPT;
if (tree->OperIsIndirOrArrLength())
{
tree->gtFlags |= GTF_IND_NONFAULTING;
tree->SetIndirExceptionFlags(this);
}
}

Expand Down Expand Up @@ -9271,6 +9271,38 @@ bool GenTree::Precedes(GenTree* other)
return false;
}

//------------------------------------------------------------------------------
// SetIndirExceptionFlags : Set GTF_EXCEPT and GTF_IND_NONFAULTING flags as appropriate
// on an indirection or an array length node.
//
// Arguments:
// comp - compiler instance
//

void GenTree::SetIndirExceptionFlags(Compiler* comp)
{
GenTree* addr = nullptr;
if (OperIsIndir())
{
addr = AsIndir()->Addr();
}
else
{
assert(gtOper == GT_ARR_LENGTH);
addr = AsArrLen()->ArrRef();
}

if (OperMayThrow(comp) || ((addr->gtFlags & GTF_EXCEPT) != 0))
{
gtFlags |= GTF_EXCEPT;
}
else
{
gtFlags &= ~GTF_EXCEPT;
gtFlags |= GTF_IND_NONFAULTING;
}
}

#ifdef DEBUG

/* static */ int GenTree::gtDispFlags(unsigned flags, unsigned debugFlags)
Expand Down
6 changes: 1 addition & 5 deletions src/coreclr/src/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -2101,11 +2101,7 @@ struct GenTree
gtFlags &= ~GTF_REUSE_REG_VAL;
}

void SetIndirExceptionFlags(Compiler* comp)
{
assert(OperIsIndirOrArrLength());
gtFlags |= OperMayThrow(comp) ? GTF_EXCEPT : GTF_IND_NONFAULTING;
}
void SetIndirExceptionFlags(Compiler* comp);

#if MEASURE_NODE_SIZE
static void DumpNodeSizes(FILE* fp);
Expand Down
24 changes: 12 additions & 12 deletions src/coreclr/src/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6188,7 +6188,6 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac)
tree->SetOper(GT_IND);
tree->gtOp.gtOp1 = addr;

tree->gtFlags &= (~GTF_EXCEPT | addr->gtFlags);
tree->SetIndirExceptionFlags(this);

if (addExplicitNullCheck)
Expand Down Expand Up @@ -8859,7 +8858,6 @@ GenTree* Compiler::fgMorphOneAsgBlockOp(GenTree* tree)
tree->gtFlags |= GTF_GLOB_REF;
}

dest->gtFlags &= (~GTF_EXCEPT | dest->AsIndir()->Addr()->gtFlags);
dest->SetIndirExceptionFlags(this);
tree->gtFlags |= (dest->gtFlags & GTF_EXCEPT);
}
Expand Down Expand Up @@ -8906,7 +8904,6 @@ GenTree* Compiler::fgMorphOneAsgBlockOp(GenTree* tree)
src->gtFlags |= (GTF_GLOB_REF | GTF_IND_TGTANYWHERE);
}

src->gtFlags &= (~GTF_EXCEPT | src->AsIndir()->Addr()->gtFlags);
src->SetIndirExceptionFlags(this);
}
}
Expand Down Expand Up @@ -11756,21 +11753,24 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)

DONE_MORPHING_CHILDREN:

if (tree->OperMayThrow(this))
if (tree->OperIsIndirOrArrLength())
{
// Mark the tree node as potentially throwing an exception
tree->gtFlags |= GTF_EXCEPT;
tree->SetIndirExceptionFlags(this);
}
else
{
if (tree->OperIsIndirOrArrLength())
if (tree->OperMayThrow(this))
{
tree->gtFlags |= GTF_IND_NONFAULTING;
// Mark the tree node as potentially throwing an exception
tree->gtFlags |= GTF_EXCEPT;
}
if (((op1 == nullptr) || ((op1->gtFlags & GTF_EXCEPT) == 0)) &&
((op2 == nullptr) || ((op2->gtFlags & GTF_EXCEPT) == 0)))
else
{
tree->gtFlags &= ~GTF_EXCEPT;
if (((op1 == nullptr) || ((op1->gtFlags & GTF_EXCEPT) == 0)) &&
((op2 == nullptr) || ((op2->gtFlags & GTF_EXCEPT) == 0)))
{
tree->gtFlags &= ~GTF_EXCEPT;
}
}
}

Expand Down Expand Up @@ -14649,7 +14649,7 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac)
tree->gtDynBlk.Addr() = fgMorphTree(tree->gtDynBlk.Addr());
tree->gtDynBlk.gtDynamicSize = fgMorphTree(tree->gtDynBlk.gtDynamicSize);

tree->gtFlags &= (~GTF_EXCEPT & ~GTF_CALL);
tree->gtFlags &= ~GTF_CALL;
tree->SetIndirExceptionFlags(this);

if (tree->OperGet() == GT_STORE_DYN_BLK)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.

using System;
using System.Runtime.CompilerServices;

public struct S
{
public int i;
public int j;
}

public class Test
{
public S s;

public static int Main()
{
// Test that the correct exception is thrown from Run.
// The bug was that the exceptions were reordered and DivideByZeroException
// was thrown instead of NullReferenceException.
try {
Run(null, 0);
}
catch (System.NullReferenceException)
{
return 100;
}

return -1;
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static int Run(Test test, int j)
{
int k = test.s.i + 1/j;
return k;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<CLRTestPriority>1</CLRTestPriority>
</PropertyGroup>
<PropertyGroup>
<DebugType />
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>

0 comments on commit 45ca544

Please sign in to comment.