From 503048b314a73bc222372c925feaa385d6832256 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 23 Jul 2022 21:33:47 +0200 Subject: [PATCH] Prevent the early ILInlining pass from creating `addressof` instructions --- .../CSharp/CSharpDecompiler.cs | 2 +- .../IL/ControlFlow/AsyncAwaitDecompiler.cs | 2 +- .../IL/Transforms/ILInlining.cs | 18 +++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 15cc274c7..c14b83010 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -136,7 +136,7 @@ namespace ICSharpCode.Decompiler.CSharp // run interleaved (statement by statement). // Pretty much all transforms that open up new expression inlining // opportunities belong in this category. - new ILInlining(), + new ILInlining() { options = InliningOptions.AllowInliningOfLdloca }, // Inlining must be first, because it doesn't trigger re-runs. // Any other transform that opens up new inlining opportunities should call RequestRerun(). new ExpressionTransforms(), diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index c6b54ad44..67b687362 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -189,7 +189,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow foreach (var block in function.Descendants.OfType()) { // Run inlining, but don't remove dead variables (they might get revived by TranslateFieldsToLocalAccess) - ILInlining.InlineAllInBlock(function, block, context); + ILInlining.InlineAllInBlock(function, block, InliningOptions.None, context); if (IsAsyncEnumerator) { // Remove lone 'ldc.i4', those are sometimes left over after C# compiler diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index ecdb7d2b4..c7b262c88 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -34,6 +34,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms IntroduceNamedArguments = 2, FindDeconstruction = 4, AllowChangingOrderOfEvaluationForExceptions = 8, + AllowInliningOfLdloca = 0x10 } /// @@ -41,23 +42,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// public class ILInlining : IILTransform, IBlockTransform, IStatementTransform { + internal InliningOptions options; + public void Run(ILFunction function, ILTransformContext context) { foreach (var block in function.Descendants.OfType()) { - InlineAllInBlock(function, block, context); + InlineAllInBlock(function, block, this.options, context); } function.Variables.RemoveDead(); } public void Run(Block block, BlockTransformContext context) { - InlineAllInBlock(context.Function, block, context); + InlineAllInBlock(context.Function, block, this.options, context); } public void Run(Block block, int pos, StatementTransformContext context) { - InlineOneIfPossible(block, pos, OptionsForBlock(block, pos, context), context: context); + InlineOneIfPossible(block, pos, this.options | OptionsForBlock(block, pos, context), context: context); } internal static InliningOptions OptionsForBlock(Block block, int pos, ILTransformContext context) @@ -94,7 +97,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } - public static bool InlineAllInBlock(ILFunction function, Block block, ILTransformContext context) + public static bool InlineAllInBlock(ILFunction function, Block block, InliningOptions options, ILTransformContext context) { bool modified = false; var instructions = block.Instructions; @@ -102,9 +105,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (instructions[i] is StLoc inst) { - InliningOptions options = InliningOptions.None; - if (context.Settings.AggressiveInlining || IsCatchWhenBlock(block) || IsInConstructorInitializer(function, inst)) - options = InliningOptions.Aggressive; if (InlineOneIfPossible(block, i, options, context)) { modified = true; @@ -288,6 +288,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool IsGeneratedValueTypeTemporary(LdLoca loadInst, ILVariable v, ILInstruction inlinedExpression, InliningOptions options) { Debug.Assert(loadInst.Variable == v); + if (!options.HasFlag(InliningOptions.AllowInliningOfLdloca)) + { + return false; // inlining of ldloca is not allowed in the early inlining stage + } // Inlining a value type variable is allowed only if the resulting code will maintain the semantics // that the method is operating on a copy. // Thus, we have to ensure we're operating on an r-value.