From 11bb3060a7e5dca473eeab932236852b9d710db1 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 21 Nov 2016 15:41:25 +0100 Subject: [PATCH] Try a bit harder to find an exitInst for switch-case. --- .../IL/ControlFlow/ConditionDetection.cs | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs index c1bc6ff05..0b1caa4e2 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs @@ -198,6 +198,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private void HandleSwitchInstruction(ControlFlowNode cfgNode, Block block, SwitchInstruction sw, ref ILInstruction exitInst) { Debug.Assert(sw.DefaultBody is Nop); + // First, move blocks into the switch section foreach (var section in sw.Sections) { if (IsUsableBranchToChild(cfgNode, section.Body)) { // case ...: goto targetBlock; @@ -205,12 +206,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow section.Body = targetBlock; } } + // Move the code following the switch into the default section if (IsUsableBranchToChild(cfgNode, exitInst)) { // switch(...){} goto targetBlock; // ---> switch(..) { default: { targetBlock } } var targetBlock = ((Branch)exitInst).TargetBlock; sw.DefaultBody = targetBlock; - if (targetBlock.Instructions.Last().OpCode == OpCode.Branch || targetBlock.Instructions.Last().OpCode == OpCode.Leave) { + if (IsBranchOrLeave(targetBlock.Instructions.Last())) { exitInst = block.Instructions[block.Instructions.Count - 1] = targetBlock.Instructions.Last(); targetBlock.Instructions.RemoveAt(targetBlock.Instructions.Count - 1); } else { @@ -221,11 +223,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Remove compatible exitInsts from switch sections: foreach (var section in sw.Sections) { Block sectionBlock = section.Body as Block; - if (sectionBlock != null && CompatibleExitInstruction(exitInst, sectionBlock.Instructions.Last())) { + if (sectionBlock != null && exitInst == null && IsBranchOrLeave(sectionBlock.Instructions.Last())) { + exitInst = sectionBlock.Instructions.Last(); + sectionBlock.Instructions.RemoveAt(sectionBlock.Instructions.Count - 1); + block.Instructions.Add(exitInst); + } else if (sectionBlock != null && CompatibleExitInstruction(exitInst, sectionBlock.Instructions.Last())) { sectionBlock.Instructions.RemoveAt(sectionBlock.Instructions.Count - 1); } } sw.Sections.ReplaceList(sw.Sections.OrderBy(s => s.Body.ILRange.Start)); } + + private bool IsBranchOrLeave(ILInstruction inst) + { + switch (inst.OpCode) { + case OpCode.Branch: + case OpCode.Leave: + return true; + default: + return false; + } + } } }