diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index e080d317e..929ac7419 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -58,6 +58,8 @@ namespace ICSharpCode.Decompiler.CSharp new SplitVariables(), new ILInlining(), new DetectPinnedRegions(), // must run after inlining but before non-critical control flow transforms + new BlockILTransform(new ExpressionTransforms()), // for RemoveDeadVariableInit + new RemoveDeadVariableInit(), // must run after ExpressionTransforms because it does not handle stobj(ldloca V, ...) new SwitchDetection(), new LoopDetection(), new IntroduceExitPoints(), @@ -76,9 +78,6 @@ namespace ICSharpCode.Decompiler.CSharp new ILInlining() ) ), - //new InlineCompilerGeneratedVariables(), - // -- isn't InlineCompilerGeneratedVariables redundant now that we have variable splitting? - new RemoveDeadVariableInit(), // must run after ExpressionTransforms because it does not handle stobj(ldloca V, ...) new DelegateConstruction(), }; } diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index e962a6467..81c7f7e00 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -138,7 +138,6 @@ - diff --git a/ICSharpCode.Decompiler/IL/Transforms/InlineCompilerGeneratedVariables.cs b/ICSharpCode.Decompiler/IL/Transforms/InlineCompilerGeneratedVariables.cs deleted file mode 100644 index 14fb5d10d..000000000 --- a/ICSharpCode.Decompiler/IL/Transforms/InlineCompilerGeneratedVariables.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2014 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 System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; - -namespace ICSharpCode.Decompiler.IL.Transforms -{ - /// - /// Inline compiler-generated variables. - /// Unlike normal inlining that acts on stack variables which have only one use, - /// this transform will also perform inlining if the variables are re-used. - /// - /// - /// Should run after ControlFlowSimplification duplicates the return blocks. - /// Should run after a regular round of inlining, so that stack variables - /// don't prevent us from determining whether a variable is likely to be compiler-generated. - /// - public class InlineCompilerGeneratedVariables : IILTransform - { - public void Run(ILFunction function, ILTransformContext context) - { - List storesToInline = new List(); - List deadStores = new List(); - foreach (var g in function.Descendants.OfType().GroupBy(inst => inst.Variable)) { - storesToInline.Clear(); - deadStores.Clear(); - if (CanInlineVariable(g.Key, g, storesToInline, deadStores)) { - foreach (var stloc in storesToInline) { - ILInlining.InlineOne(stloc, aggressive: false, context: context); - } - foreach (var stloc in deadStores) { - if (SemanticHelper.IsPure(stloc.Flags)) { - ((Block)stloc.Parent).Instructions.RemoveAt(stloc.ChildIndex); - } - } - } - } - } - - bool CanInlineVariable(ILVariable v, IEnumerable stores, /*out*/ List storesToInline, /*out*/ List deadStores) - { - if (v.Kind != VariableKind.Local) { - return false; - } - if (v.HasInitialValue) { - return false; // cannot handle variables that are implicitly initialized at the beginning of the function - } - Debug.Assert(v.StoreCount == stores.Count()); - // We expect there to be one store for every load, - // and potentially also some dead stores. - if (v.StoreCount < v.LoadCount || v.AddressCount != 0) - return false; - int loadsAccountedFor = 0; - foreach (var stloc in stores) { - Block block = stloc.Parent as Block; - if (block == null) - return false; - ILInstruction next = block.Instructions.ElementAtOrDefault(stloc.ChildIndex + 1); - // NB: next==null is considerd as a dead store - if (ILInlining.CanInlineInto(next, v, stloc.Value)) { - loadsAccountedFor++; - storesToInline.Add(stloc); - } else { - // a dead store (but only if this method returns true) - deadStores.Add(stloc); - } - } - return v.LoadCount == loadsAccountedFor; - } - } -}