From 04215ebcfaf0807fc7e7bddee25b7ea89db5013f Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 4 Sep 2017 22:55:53 +0200 Subject: [PATCH] [async] Add copy propagation so that state machine field accesses can be reliably detected. --- .../IL/ControlFlow/AsyncAwaitDecompiler.cs | 16 +++++----- .../IL/Instructions/Await.cs | 29 ++++++++++++++----- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index 1b0f3799e..0f9a5531b 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -80,6 +80,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } InlineBodyOfMoveNext(function); + + // Copy-propagate temporaries holding a copy of 'this'. + foreach (var stloc in function.Descendants.OfType().Where(s => s.Variable.IsSingleDefinition && s.Value.MatchLdThis()).ToList()) { + CopyPropagation.Propagate(stloc, context); + } + AnalyzeStateMachine(function); DetectAwaitPattern(function); @@ -696,15 +702,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow pos++; } - // stloc S_27(ldloc this) // stloc S_28(ldc.i4 -1) // stloc cachedStateVar(ldloc S_28) - // stfld <>1__state(ldloc S_27, ldloc S_28) - ILVariable thisVar = null; - if (block.Instructions[pos] is StLoc stlocThis && stlocThis.Value.MatchLdThis() && stlocThis.Variable.Kind == VariableKind.StackSlot) { - thisVar = stlocThis.Variable; - pos++; - } + // stfld <>1__state(ldloc this, ldloc S_28) ILVariable m1Var = null; if (block.Instructions[pos] is StLoc stlocM1 && stlocM1.Value.MatchLdcI4(initialState) && stlocM1.Variable.Kind == VariableKind.StackSlot) { m1Var = stlocM1.Variable; @@ -717,7 +717,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } if (block.Instructions[pos].MatchStFld(out target, out field, out value)) { - if (!(target.MatchLdThis() || target.MatchLdLoc(thisVar))) + if (!target.MatchLdThis()) return false; if (field.MemberDefinition != stateField) return false; diff --git a/ICSharpCode.Decompiler/IL/Instructions/Await.cs b/ICSharpCode.Decompiler/IL/Instructions/Await.cs index 0872e6ae7..211df8b01 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Await.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Await.cs @@ -1,14 +1,27 @@ -using ICSharpCode.Decompiler.TypeSystem; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +// Copyright (c) 2017 Daniel Grunwald +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL { - partial class Await - { + partial class Await + { public IMethod GetAwaiterMethod; public IMethod GetResultMethod; }