diff --git a/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs b/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs index 6fb4acf8e..9a31e8595 100644 --- a/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs +++ b/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs @@ -65,8 +65,9 @@ namespace ICSharpCode.Decompiler.ILAst int count = ilCase.Body.Count; if (count >= 2) { - if (!ilCase.Body[count - 2].CanFallThough() && - ilCase.Body[count - 1].Match(ILCode.LoopOrSwitchBreak)) { + if (ilCase.Body[count - 2].IsUnconditionalControlFlow() && + ilCase.Body[count - 1].Match(ILCode.LoopOrSwitchBreak)) + { ilCase.Body.RemoveAt(count - 1); } } diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index 552d60a67..3d4a20cd4 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -309,7 +309,7 @@ namespace ICSharpCode.Decompiler.ILAst // Find all successors List branchTargets = new List(); - if (byteCode.Code.CanFallThough()) { + if (!byteCode.Code.IsUnconditionalControlFlow()) { branchTargets.Add(byteCode.Next); } if (byteCode.Operand is Instruction[]) { diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index d0b873516..6e9587d8e 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -309,15 +309,16 @@ namespace ICSharpCode.Decompiler.ILAst // Start a new basic block if necessary if (currNode is ILLabel || - lastNode is ILTryCatchBlock || currNode is ILTryCatchBlock || - (lastNode is ILExpression && ((ILExpression)lastNode).IsBranch())) + lastNode is ILTryCatchBlock || + lastNode.IsConditionalControlFlow() || + lastNode.IsUnconditionalControlFlow()) { // Try to reuse the label ILLabel label = currNode is ILLabel ? ((ILLabel)currNode) : new ILLabel() { Name = "Block_" + (nextLabelIndex++) }; // Terminate the last block - if (lastNode.CanFallThough()) { + if (!lastNode.IsUnconditionalControlFlow()) { // Explicit branch from one block to other basicBlock.FallthoughGoto = new ILExpression(ILCode.Br, label); } else if (lastNode.Match(ILCode.Br)) { @@ -432,8 +433,8 @@ namespace ICSharpCode.Decompiler.ILAst for (int i = 0; i < block.Body.Count; i++) { ILCondition cond = block.Body[i] as ILCondition; if (cond != null) { - bool trueExits = cond.TrueBlock.Body.Count > 0 && !cond.TrueBlock.Body.Last().CanFallThough(); - bool falseExits = cond.FalseBlock.Body.Count > 0 && !cond.FalseBlock.Body.Last().CanFallThough(); + bool trueExits = cond.TrueBlock.Body.LastOrDefault().IsUnconditionalControlFlow(); + bool falseExits = cond.FalseBlock.Body.LastOrDefault().IsUnconditionalControlFlow(); if (trueExits) { // Move the false block after the condition @@ -504,13 +505,16 @@ namespace ICSharpCode.Decompiler.ILAst return modified; } - public static bool CanFallThough(this ILNode node) + public static bool IsConditionalControlFlow(this ILNode node) { ILExpression expr = node as ILExpression; - if (expr != null) { - return expr.Code.CanFallThough(); - } - return true; + return expr != null && expr.Code.IsConditionalControlFlow(); + } + + public static bool IsUnconditionalControlFlow(this ILNode node) + { + ILExpression expr = node as ILExpression; + return expr != null && expr.Code.IsUnconditionalControlFlow(); } /// diff --git a/ICSharpCode.Decompiler/ILAst/ILCodes.cs b/ICSharpCode.Decompiler/ILAst/ILCodes.cs index ea0569582..7ab0ec9db 100644 --- a/ICSharpCode.Decompiler/ILAst/ILCodes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILCodes.cs @@ -280,7 +280,41 @@ namespace ICSharpCode.Decompiler.ILAst return code.ToString().ToLowerInvariant().TrimStart('_').Replace('_','.'); } - public static bool CanFallThough(this ILCode code) + public static bool IsConditionalControlFlow(this ILCode code) + { + switch(code) { + case ILCode.__Brfalse_S: + case ILCode.__Brtrue_S: + case ILCode.__Beq_S: + case ILCode.__Bge_S: + case ILCode.__Bgt_S: + case ILCode.__Ble_S: + case ILCode.__Blt_S: + case ILCode.__Bne_Un_S: + case ILCode.__Bge_Un_S: + case ILCode.__Bgt_Un_S: + case ILCode.__Ble_Un_S: + case ILCode.__Blt_Un_S: + case ILCode.__Brfalse: + case ILCode.Brtrue: + case ILCode.__Beq: + case ILCode.__Bge: + case ILCode.__Bgt: + case ILCode.__Ble: + case ILCode.__Blt: + case ILCode.__Bne_Un: + case ILCode.__Bge_Un: + case ILCode.__Bgt_Un: + case ILCode.__Ble_Un: + case ILCode.__Blt_Un: + case ILCode.Switch: + return true; + default: + return false; + } + } + + public static bool IsUnconditionalControlFlow(this ILCode code) { switch(code) { case ILCode.Br: @@ -295,9 +329,9 @@ namespace ICSharpCode.Decompiler.ILAst case ILCode.LoopContinue: case ILCode.LoopOrSwitchBreak: case ILCode.YieldBreak: - return false; - default: return true; + default: + return false; } }