Browse Source

Add support for old roslyn pattern matching pattern.

pull/2461/head
Siegfried Pammer 4 years ago
parent
commit
357d55d2ad
  1. 42
      ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs

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

@ -28,29 +28,55 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// call Use(..., comp.o(ldloc V != ldnull)) /// call Use(..., comp.o(ldloc V != ldnull))
/// => /// =>
/// call Use(..., match.type[T](V = testedOperand)) /// call Use(..., match.type[T](V = testedOperand))
///
/// - or -
///
/// stloc S(isinst T(testedOperand))
/// stloc V(ldloc S)
/// call Use(..., comp.o(ldloc S != ldnull))
/// =>
/// call Use(..., match.type[T](V = testedOperand))
/// </summary> /// </summary>
void IStatementTransform.Run(Block block, int pos, StatementTransformContext context) void IStatementTransform.Run(Block block, int pos, StatementTransformContext context)
{ {
if (!context.Settings.PatternMatching) if (!context.Settings.PatternMatching)
return; return;
if (pos + 1 >= block.Instructions.Count) int startPos = pos;
return;
if (block.Instructions[pos] is not StLoc if (block.Instructions[pos] is not StLoc
{ {
Variable: var v, Variable: var s,
Value: IsInst { Argument: var testedOperand, Type: var type } Value: IsInst { Argument: var testedOperand, Type: var type }
}) })
{ {
return; return;
} }
if (!v.IsSingleDefinition) if (!s.IsSingleDefinition)
return; return;
if (v.Kind is not (VariableKind.Local or VariableKind.StackSlot)) if (s.Kind is not (VariableKind.Local or VariableKind.StackSlot))
return; return;
pos++;
ILVariable v;
if (block.Instructions.ElementAtOrDefault(pos) is StLoc stloc && stloc.Value.MatchLdLoc(s))
{
v = stloc.Variable;
pos++;
if (!v.IsSingleDefinition)
return;
if (v.Kind is not (VariableKind.Local or VariableKind.StackSlot))
return;
if (s.LoadCount != 2)
return;
}
else
{
v = s;
}
if (!v.Type.Equals(type)) if (!v.Type.Equals(type))
return; return;
if (pos >= block.Instructions.Count)
var result = ILInlining.FindLoadInNext(block.Instructions[pos + 1], v, testedOperand, InliningOptions.None); return;
var result = ILInlining.FindLoadInNext(block.Instructions[pos], s, testedOperand, InliningOptions.None);
if (result.Type != ILInlining.FindResultType.Found) if (result.Type != ILInlining.FindResultType.Found)
return; return;
if (result.LoadInst is not LdLoc) if (result.LoadInst is not LdLoc)
@ -83,7 +109,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
matchInstruction = Comp.LogicNot(matchInstruction); matchInstruction = Comp.LogicNot(matchInstruction);
} }
target.ReplaceWith(matchInstruction.WithILRange(target)); target.ReplaceWith(matchInstruction.WithILRange(target));
block.Instructions.RemoveAt(pos); block.Instructions.RemoveRange(startPos, pos - startPos);
v.Kind = VariableKind.PatternLocal; v.Kind = VariableKind.PatternLocal;
} }
} }

Loading…
Cancel
Save