From f4613de2ba20078b44284474bc276089626abded Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 7 Oct 2018 15:38:44 +0200 Subject: [PATCH] Don't match sub.ovf in SwitchAnalysis. --- .../IL/ControlFlow/SwitchAnalysis.cs | 24 ++++++-------- .../Util/CollectionExtensions.cs | 31 ++++++++++--------- ICSharpCode.Decompiler/Util/LongSet.cs | 3 ++ 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs index 1dae02436..ab264e3da 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs @@ -233,21 +233,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow bool MatchSwitchVar(ILInstruction inst, out long sub) { - if (inst.MatchBinaryNumericInstruction(BinaryNumericOperator.Sub, out var left, out var right) && right.MatchLdcI(out sub)) - return MatchSwitchVar(left); + if (inst is BinaryNumericInstruction bn + && bn.Operator == BinaryNumericOperator.Sub + && !bn.CheckForOverflow && !bn.IsLifted + && bn.Right.MatchLdcI(out sub)) + { + return MatchSwitchVar(bn.Left); + } sub = 0; return MatchSwitchVar(inst); } - /// - /// Shifts a LongInterval, treating long.MinValue and long.MaxValue like float.Positive/NegativeInfinity - /// - LongInterval ShiftInterval(LongInterval interval, long offset) - { - return new LongInterval( - interval.Start == long.MinValue ? long.MinValue : interval.Start + offset, - interval.End == long.MinValue ? long.MinValue : interval.End + offset); - } /// /// Analyzes the boolean condition, returning the set of values of the interesting @@ -256,11 +252,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private bool AnalyzeCondition(ILInstruction condition, out LongSet trueValues) { if (condition is Comp comp && MatchSwitchVar(comp.Left, out var sub) && comp.Right.MatchLdcI(out long val)) { - // if (comp(V OP val)) + // if (comp((V - sub) OP val)) trueValues = MakeSetWhereComparisonIsTrue(comp.Kind, val, comp.Sign); - if (sub != 0) - trueValues = new LongSet(trueValues.Intervals.Select(i => ShiftInterval(i, sub))); - + trueValues = trueValues.AddOffset(sub); return true; } else if (MatchSwitchVar(condition)) { // if (ldloc V) --> branch for all values except 0 diff --git a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs index 590f8027a..4c01285df 100644 --- a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs +++ b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs @@ -200,27 +200,28 @@ namespace ICSharpCode.Decompiler.Util /// public static IEnumerable Merge(this IEnumerable input1, IEnumerable input2, Comparison comparison) { - var enumA = input1.GetEnumerator(); - var enumB = input2.GetEnumerator(); - bool moreA = enumA.MoveNext(); - bool moreB = enumB.MoveNext(); - while (moreA && moreB) { - if (comparison(enumA.Current, enumB.Current) <= 0) { + using (var enumA = input1.GetEnumerator()) + using (var enumB = input2.GetEnumerator()) { + bool moreA = enumA.MoveNext(); + bool moreB = enumB.MoveNext(); + while (moreA && moreB) { + if (comparison(enumA.Current, enumB.Current) <= 0) { + yield return enumA.Current; + moreA = enumA.MoveNext(); + } else { + yield return enumB.Current; + moreB = enumB.MoveNext(); + } + } + while (moreA) { yield return enumA.Current; moreA = enumA.MoveNext(); - } else { + } + while (moreB) { yield return enumB.Current; moreB = enumB.MoveNext(); } } - while (moreA) { - yield return enumA.Current; - moreA = enumA.MoveNext(); - } - while (moreB) { - yield return enumB.Current; - moreB = enumB.MoveNext(); - } } /// diff --git a/ICSharpCode.Decompiler/Util/LongSet.cs b/ICSharpCode.Decompiler/Util/LongSet.cs index 17790360e..118701218 100644 --- a/ICSharpCode.Decompiler/Util/LongSet.cs +++ b/ICSharpCode.Decompiler/Util/LongSet.cs @@ -203,6 +203,9 @@ namespace ICSharpCode.Decompiler.Util /// public LongSet AddOffset(long val) { + if (val == 0) { + return this; + } var newIntervals = new List(Intervals.Length + 1); foreach (var element in Intervals) { long newStart = unchecked(element.Start + val);