Browse Source

DetectPinnedRegions: Support special case where pinned pointer is unused and the compiler optimized out the StopGCTracking-conversion.

pull/2642/head
Siegfried Pammer 3 years ago
parent
commit
f98012ec16
  1. 21
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  2. 9
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  3. 72
      ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

21
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -419,13 +419,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -419,13 +419,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
UsePointer(ptr);
}
}
#endif
#if CS73
//public unsafe void FixedCustomReferenceType(CustomPinnable mem)
//{
// fixed (int* ptr = mem) {
// fixed (int* ptr = mem)
// {
// UsePointer(ptr);
// }
//}
public unsafe void FixedCustomReferenceTypeNoPointerUse(CustomPinnable mem)
{
fixed (int* ptr = mem)
{
Console.WriteLine("Hello World!");
}
}
public unsafe void FixedCustomReferenceTypeExplicitGetPinnableReference(CustomPinnable mem)
{
fixed (int* ptr = &mem.GetPinnableReference())
{
UsePointer(ptr);
}
}
#endif
public unsafe string StackAlloc(int count)

9
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -1168,7 +1168,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -1168,7 +1168,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
#endregion
#region C# 7.3 pattern based fixed
#region C# 7.3 pattern based fixed (for value types)
// reference types are handled by DetectPinnedRegions.IsCustomRefPinPattern
static readonly Expression addressOfPinnableReference = new UnaryOperatorExpression {
Operator = UnaryOperatorType.AddressOf,
Expression = new InvocationExpression {
@ -1186,7 +1187,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -1186,7 +1187,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var m = addressOfPinnableReference.Match(v.Initializer);
if (m.Success)
{
v.Initializer = m.Get<Expression>("target").Single().Detach();
Expression target = m.Get<Expression>("target").Single();
if (target.GetResolveResult().Type.IsReferenceType == false)
{
v.Initializer = target.Detach();
}
}
}
}

72
ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

@ -192,7 +192,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -192,7 +192,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
block.Instructions[block.Instructions.Count - 2] = new StLoc(v, gpr)
.WithILRange(block.Instructions[block.Instructions.Count - 2]);
block.Instructions.Insert(block.Instructions.Count - 1, stlocPtr);
if (stlocPtr != null)
{
block.Instructions.Insert(block.Instructions.Count - 1, stlocPtr);
}
((Branch)block.Instructions.Last()).TargetBlock = targetBlock;
modified = true;
}
@ -235,7 +238,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -235,7 +238,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (!block.MatchIfAtEndOfBlock(out var ifCondition, out var trueInst, out var falseInst))
return false;
if (!ifCondition.MatchCompNotEqualsNull(out ldlocMem))
return false;
{
if (ifCondition.MatchCompEqualsNull(out ldlocMem))
{
(trueInst, falseInst) = (falseInst, trueInst);
}
else
{
return false;
}
}
if (!SemanticHelper.IsPure(ldlocMem.Flags))
return false;
if (!trueInst.MatchBranch(out Block notNullBlock) || notNullBlock.Parent != block.Parent)
@ -243,21 +255,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -243,21 +255,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (!falseInst.MatchBranch(out Block nullBlock) || nullBlock.Parent != block.Parent)
return false;
// Block nullBlock (incoming: 1) {
// stloc ptr(conv i4->u <zero extend>(ldc.i4 0))
// br targetBlock
// }
if (nullBlock.IncomingEdgeCount != 1)
return false;
if (nullBlock.Instructions.Count != 2)
return false;
if (!nullBlock.Instructions[0].MatchStLoc(out var ptr, out var nullPointerInst))
return false;
if (!nullPointerInst.MatchLdcI(0))
return false;
if (!nullBlock.Instructions[1].MatchBranch(out targetBlock))
return false;
// Block notNullBlock (incoming: 1) {
// stloc V_1(call GetPinnableReference(ldloc mem))
// stloc ptr(conv ref->u (ldloc V_1))
@ -265,7 +262,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -265,7 +262,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// }
if (notNullBlock.IncomingEdgeCount != 1)
return false;
if (notNullBlock.Instructions.Count != 3)
if (notNullBlock.Instructions.Count < 2)
return false;
// stloc V_1(call GetPinnableReference(ldloc mem))
if (!notNullBlock.Instructions[0].MatchStLoc(out v, out var value))
@ -281,13 +278,38 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -281,13 +278,38 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return false;
// stloc ptr(conv ref->u (ldloc V_1))
ptrAssign = notNullBlock.Instructions[1] as StLoc;
if (ptrAssign == null || ptrAssign.Variable != ptr)
return false;
if (!ptrAssign.Value.UnwrapConv(ConversionKind.StopGCTracking).MatchLdLoc(v))
return false;
// br targetBlock
if (!notNullBlock.Instructions[2].MatchBranch(targetBlock))
return false;
if (ptrAssign != null)
{
if (!ptrAssign.Value.UnwrapConv(ConversionKind.StopGCTracking).MatchLdLoc(v))
return false;
// br targetBlock
if (!notNullBlock.Instructions[2].MatchBranch(out targetBlock))
return false;
// Block nullBlock (incoming: 1) {
// stloc ptr(conv i4->u <zero extend>(ldc.i4 0))
// br targetBlock
// }
if (nullBlock.IncomingEdgeCount != 1)
return false;
if (nullBlock.Instructions.Count != 2)
return false;
if (!nullBlock.Instructions[0].MatchStLoc(ptrAssign.Variable, out var nullPointerInst))
return false;
if (!nullPointerInst.MatchLdcI(0))
return false;
if (!nullBlock.Instructions[1].MatchBranch(targetBlock))
return false;
}
else
{
// br targetBlock
if (!notNullBlock.Instructions[1].MatchBranch(out targetBlock))
return false;
if (targetBlock != nullBlock)
return false;
}
return true;
}

Loading…
Cancel
Save