From bcdd34a9d015798c1385921b3f945ece154d7d64 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 29 Aug 2017 23:58:59 +0200 Subject: [PATCH] More aggressively duplicate return blocks in MoveNext() methods. This fixes 'yield return' decompilation of debug builds using legacy csc. --- ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs | 6 ++++-- .../IL/ControlFlow/ControlFlowSimplification.cs | 7 +++++-- .../IL/ControlFlow/YieldReturnDecompiler.cs | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index d1f2370ec..5adef4112 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -51,10 +51,12 @@ namespace ICSharpCode.Decompiler.CSharp /// /// Pre-yield/await transforms. /// - internal static List EarlyILTransforms() + internal static List EarlyILTransforms(bool aggressivelyDuplicateReturnBlocks = false) { return new List { - new ControlFlowSimplification(), + new ControlFlowSimplification { + aggressivelyDuplicateReturnBlocks = aggressivelyDuplicateReturnBlocks + }, new SplitVariables(), new ILInlining(), }; diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs index 04c988279..90e91a817 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs @@ -36,6 +36,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// public class ControlFlowSimplification : IILTransform { + internal bool aggressivelyDuplicateReturnBlocks; + public void Run(ILFunction function, ILTransformContext context) { foreach (var block in function.Descendants.OfType()) { @@ -129,12 +131,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } - static bool ShouldSimplifyBranchToReturnBlock(Branch branch) + bool ShouldSimplifyBranchToReturnBlock(Branch branch) { var targetBlock = branch.TargetBlock; if (targetBlock.Instructions.Count != 1 || targetBlock.FinalInstruction.OpCode != OpCode.Nop) return false; - if (targetBlock.Parent == branch.Ancestors.OfType().FirstOrDefault()) { + if (targetBlock.Parent == branch.Ancestors.OfType().FirstOrDefault() + && !aggressivelyDuplicateReturnBlocks) { // only simplify when jumping out of a try-finally return false; } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs index be044f531..1a72335f8 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs @@ -311,7 +311,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow ); } var il = new ILReader(typeSystem).ReadIL(method.Body, context.CancellationToken); - il.RunTransforms(CSharpDecompiler.EarlyILTransforms(), new ILTransformContext { + il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true), new ILTransformContext { Settings = context.Settings, CancellationToken = context.CancellationToken, TypeSystem = context.TypeSystem