Browse Source

Prevent the early ILInlining pass from creating `addressof` instructions

pull/2766/head
Daniel Grunwald 3 years ago committed by Siegfried Pammer
parent
commit
503048b314
  1. 2
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 2
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
  3. 18
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

2
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -136,7 +136,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -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(),

2
ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs

@ -189,7 +189,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -189,7 +189,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
foreach (var block in function.Descendants.OfType<Block>())
{
// 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

18
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -34,6 +34,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -34,6 +34,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
IntroduceNamedArguments = 2,
FindDeconstruction = 4,
AllowChangingOrderOfEvaluationForExceptions = 8,
AllowInliningOfLdloca = 0x10
}
/// <summary>
@ -41,23 +42,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -41,23 +42,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
public class ILInlining : IILTransform, IBlockTransform, IStatementTransform
{
internal InliningOptions options;
public void Run(ILFunction function, ILTransformContext context)
{
foreach (var block in function.Descendants.OfType<Block>())
{
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 @@ -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 @@ -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 @@ -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.

Loading…
Cancel
Save