Browse Source

Ensure that pattern locals get distinct variable names.

pull/2461/head
Siegfried Pammer 4 years ago
parent
commit
55f1125f94
  1. 4
      ICSharpCode.Decompiler/IL/ILVariable.cs
  2. 1
      ICSharpCode.Decompiler/IL/Transforms/IntroduceNativeIntTypeOnLocals.cs
  3. 23
      ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs

4
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -101,6 +101,7 @@ namespace ICSharpCode.Decompiler.IL
case VariableKind.ExceptionLocal: case VariableKind.ExceptionLocal:
case VariableKind.ForeachLocal: case VariableKind.ForeachLocal:
case VariableKind.UsingLocal: case VariableKind.UsingLocal:
case VariableKind.PatternLocal:
case VariableKind.PinnedLocal: case VariableKind.PinnedLocal:
case VariableKind.PinnedRegionLocal: case VariableKind.PinnedRegionLocal:
case VariableKind.DisplayClassLocal: case VariableKind.DisplayClassLocal:
@ -173,6 +174,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
case VariableKind.Local: case VariableKind.Local:
case VariableKind.ForeachLocal: case VariableKind.ForeachLocal:
case VariableKind.PatternLocal:
case VariableKind.PinnedLocal: case VariableKind.PinnedLocal:
case VariableKind.PinnedRegionLocal: case VariableKind.PinnedRegionLocal:
case VariableKind.UsingLocal: case VariableKind.UsingLocal:
@ -541,6 +543,8 @@ namespace ICSharpCode.Decompiler.IL
return false; return false;
if (x.Kind == VariableKind.StackSlot || y.Kind == VariableKind.StackSlot) if (x.Kind == VariableKind.StackSlot || y.Kind == VariableKind.StackSlot)
return false; return false;
if (x.Kind == VariableKind.PatternLocal || y.Kind == VariableKind.PatternLocal)
return false;
if (!(x.Function == y.Function && x.Kind == y.Kind)) if (!(x.Function == y.Function && x.Kind == y.Kind))
return false; return false;
if (x.Index != null) if (x.Index != null)

1
ICSharpCode.Decompiler/IL/Transforms/IntroduceNativeIntTypeOnLocals.cs

@ -36,6 +36,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
if (variable.Kind != VariableKind.Local && if (variable.Kind != VariableKind.Local &&
variable.Kind != VariableKind.StackSlot && variable.Kind != VariableKind.StackSlot &&
variable.Kind != VariableKind.PatternLocal &&
variable.Kind != VariableKind.ForeachLocal && variable.Kind != VariableKind.ForeachLocal &&
variable.Kind != VariableKind.UsingLocal) variable.Kind != VariableKind.UsingLocal)
{ {

23
ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs

@ -19,20 +19,14 @@
#nullable enable #nullable enable
using System; using System;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading;
using System.Xml.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.IL.ControlFlow; using ICSharpCode.Decompiler.IL.ControlFlow;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using static ICSharpCode.Decompiler.TypeSystem.ReflectionHelper;
namespace ICSharpCode.Decompiler.IL.Transforms namespace ICSharpCode.Decompiler.IL.Transforms
{ {
class PatternMatchingTransform : IILTransform class PatternMatchingTransform : IILTransform
@ -110,11 +104,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false; return false;
pos--; pos--;
} }
if (condition.MatchCompEqualsNull(out var arg)) if (condition.MatchCompEqualsNull(out var loadInNullCheck))
{ {
ExtensionMethods.Swap(ref trueInst, ref falseInst); ExtensionMethods.Swap(ref trueInst, ref falseInst);
} }
else if (condition.MatchCompNotEqualsNull(out arg)) else if (condition.MatchCompNotEqualsNull(out loadInNullCheck))
{ {
// do nothing // do nothing
} }
@ -122,7 +116,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
return false; return false;
} }
if (!arg.MatchLdLoc(out var s)) if (!loadInNullCheck.MatchLdLoc(out var s))
return false; return false;
if (!s.IsSingleDefinition) if (!s.IsSingleDefinition)
return false; return false;
@ -140,8 +134,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
pos--; pos--;
if (!block.Instructions[pos].MatchStLoc(s, out value)) if (!block.Instructions[pos].MatchStLoc(s, out value))
return false; return false;
if (!v.IsSingleDefinition)
return false;
if (v.Kind is not (VariableKind.Local or VariableKind.StackSlot)) if (v.Kind is not (VariableKind.Local or VariableKind.StackSlot))
return false; return false;
if (s.LoadCount != 2) if (s.LoadCount != 2)
@ -172,7 +164,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!v.Type.Equals(type)) if (!v.Type.Equals(type))
return false; return false;
if (!CheckAllUsesDominatedBy(v, container, trueInst, storeToV, context, ref cfg)) if (!CheckAllUsesDominatedBy(v, container, trueInst, storeToV, loadInNullCheck, context, ref cfg))
return false; return false;
context.Step($"Type pattern matching {v.Name}", block); context.Step($"Type pattern matching {v.Name}", block);
// if (match.type[T].notnull(V = testedOperand)) br trueBlock // if (match.type[T].notnull(V = testedOperand)) br trueBlock
@ -191,7 +183,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
private bool CheckAllUsesDominatedBy(ILVariable v, BlockContainer container, ILInstruction trueInst, private bool CheckAllUsesDominatedBy(ILVariable v, BlockContainer container, ILInstruction trueInst,
ILInstruction storeToV, ILTransformContext context, ref ControlFlowGraph? cfg) ILInstruction storeToV, ILInstruction? loadInNullCheck, ILTransformContext context, ref ControlFlowGraph? cfg)
{ {
var targetBlock = trueInst as Block; var targetBlock = trueInst as Block;
if (targetBlock == null && !trueInst.MatchBranch(out targetBlock)) if (targetBlock == null && !trueInst.MatchBranch(out targetBlock))
@ -203,12 +195,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false; return false;
cfg ??= new ControlFlowGraph(container, context.CancellationToken); cfg ??= new ControlFlowGraph(container, context.CancellationToken);
var targetBlockNode = cfg.GetNode(targetBlock); var targetBlockNode = cfg.GetNode(targetBlock);
Debug.Assert(v.StoreInstructions.Count == 1);
var uses = v.LoadInstructions.Concat<ILInstruction>(v.AddressInstructions) var uses = v.LoadInstructions.Concat<ILInstruction>(v.AddressInstructions)
.Concat(v.StoreInstructions.Cast<ILInstruction>()); .Concat(v.StoreInstructions.Cast<ILInstruction>());
foreach (var use in uses) foreach (var use in uses)
{ {
if (use == storeToV) if (use == storeToV || use == loadInNullCheck)
continue; continue;
Block? found = null; Block? found = null;
for (ILInstruction? current = use; current != null; current = current.Parent) for (ILInstruction? current = use; current != null; current = current.Parent)
@ -274,7 +265,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
return false; return false;
} }
if (!CheckAllUsesDominatedBy(v, container, unboxBlock, storeToV, context, ref cfg)) if (!CheckAllUsesDominatedBy(v, container, unboxBlock, storeToV, null, context, ref cfg))
return false; return false;
context.Step($"PatternMatching with {v.Name}", block); context.Step($"PatternMatching with {v.Name}", block);
var ifInst = (IfInstruction)block.Instructions.SecondToLastOrDefault()!; var ifInst = (IfInstruction)block.Instructions.SecondToLastOrDefault()!;

Loading…
Cancel
Save