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
// run interleaved (statement by statement). // run interleaved (statement by statement).
// Pretty much all transforms that open up new expression inlining // Pretty much all transforms that open up new expression inlining
// opportunities belong in this category. // opportunities belong in this category.
new ILInlining(), new ILInlining() { options = InliningOptions.AllowInliningOfLdloca },
// Inlining must be first, because it doesn't trigger re-runs. // Inlining must be first, because it doesn't trigger re-runs.
// Any other transform that opens up new inlining opportunities should call RequestRerun(). // Any other transform that opens up new inlining opportunities should call RequestRerun().
new ExpressionTransforms(), new ExpressionTransforms(),

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

@ -189,7 +189,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
foreach (var block in function.Descendants.OfType<Block>()) foreach (var block in function.Descendants.OfType<Block>())
{ {
// Run inlining, but don't remove dead variables (they might get revived by TranslateFieldsToLocalAccess) // 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) if (IsAsyncEnumerator)
{ {
// Remove lone 'ldc.i4', those are sometimes left over after C# compiler // 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
IntroduceNamedArguments = 2, IntroduceNamedArguments = 2,
FindDeconstruction = 4, FindDeconstruction = 4,
AllowChangingOrderOfEvaluationForExceptions = 8, AllowChangingOrderOfEvaluationForExceptions = 8,
AllowInliningOfLdloca = 0x10
} }
/// <summary> /// <summary>
@ -41,23 +42,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary> /// </summary>
public class ILInlining : IILTransform, IBlockTransform, IStatementTransform public class ILInlining : IILTransform, IBlockTransform, IStatementTransform
{ {
internal InliningOptions options;
public void Run(ILFunction function, ILTransformContext context) public void Run(ILFunction function, ILTransformContext context)
{ {
foreach (var block in function.Descendants.OfType<Block>()) foreach (var block in function.Descendants.OfType<Block>())
{ {
InlineAllInBlock(function, block, context); InlineAllInBlock(function, block, this.options, context);
} }
function.Variables.RemoveDead(); function.Variables.RemoveDead();
} }
public void Run(Block block, BlockTransformContext context) 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) 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) 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; bool modified = false;
var instructions = block.Instructions; var instructions = block.Instructions;
@ -102,9 +105,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
if (instructions[i] is StLoc inst) 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)) if (InlineOneIfPossible(block, i, options, context))
{ {
modified = true; modified = true;
@ -288,6 +288,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
static bool IsGeneratedValueTypeTemporary(LdLoca loadInst, ILVariable v, ILInstruction inlinedExpression, InliningOptions options) static bool IsGeneratedValueTypeTemporary(LdLoca loadInst, ILVariable v, ILInstruction inlinedExpression, InliningOptions options)
{ {
Debug.Assert(loadInst.Variable == v); 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 // Inlining a value type variable is allowed only if the resulting code will maintain the semantics
// that the method is operating on a copy. // that the method is operating on a copy.
// Thus, we have to ensure we're operating on an r-value. // Thus, we have to ensure we're operating on an r-value.

Loading…
Cancel
Save