From eac0e2257e98129d4b1d1fdeb375d110f513a52f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 26 Jul 2020 19:22:14 +0200 Subject: [PATCH] Support MatchInstruction in DataFlowVisitor --- .../FlowAnalysis/DataFlowVisitor.cs | 41 +++++++++++++++++++ .../FlowAnalysis/DefiniteAssignmentVisitor.cs | 7 +++- .../ReachingDefinitionsVisitor.cs | 7 +++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs b/ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs index a43ac19e6..ed5d01918 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs @@ -646,6 +646,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis } else { return (state, bottomState.Clone()); } + } else if (inst is MatchInstruction match) { + return EvaluateMatch(match); } else { // other kind of condition inst.AcceptVisitor(this); @@ -653,6 +655,45 @@ namespace ICSharpCode.Decompiler.FlowAnalysis } } + protected internal override void VisitMatchInstruction(MatchInstruction inst) + { + var (onTrue, onFalse) = EvaluateMatch(inst); + state = onTrue; + state.JoinWith(onFalse); + } + + /// + /// Evaluates a match instruction. + /// + /// + /// A pair of: + /// * The state after the pattern matches + /// * The state after the pattern fails to match + /// + /// + /// this.state is invalid after this function was called, and must be overwritten + /// with one of the return values. + /// + (State OnTrue, State OnFalse) EvaluateMatch(MatchInstruction inst) + { + DebugStartPoint(inst); + inst.TestedOperand.AcceptVisitor(this); + State onFalse = state.Clone(); + if (!inst.CheckNotNull && !inst.CheckType) { + onFalse.ReplaceWithBottom(); + } + HandleMatchStore(inst); + foreach (var subPattern in inst.SubPatterns) { + var (subTrue, subFalse) = EvaluateCondition(subPattern); + onFalse.JoinWith(subFalse); + state = subTrue; + } + DebugEndPoint(inst); + return (state, onFalse); + } + + protected abstract void HandleMatchStore(MatchInstruction inst); + protected internal override void VisitNullCoalescingInstruction(NullCoalescingInstruction inst) { HandleBinaryWithOptionalEvaluation(inst, inst.ValueInst, inst.FallbackInst); diff --git a/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs b/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs index 5b465b735..726cef1f7 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs @@ -168,7 +168,12 @@ namespace ICSharpCode.Decompiler.FlowAnalysis inst.Value.AcceptVisitor(this); HandleStore(inst.Variable); } - + + protected override void HandleMatchStore(MatchInstruction inst) + { + HandleStore(inst.Variable); + } + protected override void BeginTryCatchHandler(TryCatchHandler inst) { HandleStore(inst.Variable); diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs b/ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs index 8b6d22a24..08bf2e4f2 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs @@ -380,7 +380,12 @@ namespace ICSharpCode.Decompiler.FlowAnalysis inst.Value.AcceptVisitor(this); HandleStore(inst, inst.Variable); } - + + protected override void HandleMatchStore(MatchInstruction inst) + { + HandleStore(inst, inst.Variable); + } + protected override void BeginTryCatchHandler(TryCatchHandler inst) { base.BeginTryCatchHandler(inst);