Skip to content

Commit

Permalink
Prevent the early ILInlining pass from creating addressof instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
dgrunwald authored and siegfriedpammer committed Aug 25, 2022
1 parent f36f317 commit dec5c4c
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 9 deletions.
2 changes: 1 addition & 1 deletion ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public static List<IILTransform> GetILTransforms()
// 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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ private void CleanUpBodyOfMoveNext(ILFunction function)
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
Expand Down
18 changes: 11 additions & 7 deletions ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,33 @@ public enum InliningOptions
IntroduceNamedArguments = 2,
FindDeconstruction = 4,
AllowChangingOrderOfEvaluationForExceptions = 8,
AllowInliningOfLdloca = 0x10
}

/// <summary>
/// Performs inlining transformations.
/// </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)
Expand Down Expand Up @@ -94,17 +97,14 @@ static bool PreferExpressionsOverStatements(ILFunction function)
}
}

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;
for (int i = instructions.Count - 1; i >= 0; i--)
{
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;
Expand Down Expand Up @@ -288,6 +288,10 @@ static bool DoInline(ILVariable v, ILInstruction inlinedExpression, ILInstructio
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.
Expand Down

0 comments on commit dec5c4c

Please sign in to comment.