Browse Source

Don't use named arguments when IL stack is empty after the stloc.

An empty stack indicates the statement is complete, so the code
is usually more readable if we keep the local variable.
pull/1167/head
Daniel Grunwald 8 years ago
parent
commit
ca09f09222
  1. 4
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 7
      ICSharpCode.Decompiler/IL/Instructions/StLoc.cs
  3. 5
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

4
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1147,7 +1147,9 @@ namespace ICSharpCode.Decompiler.IL @@ -1147,7 +1147,9 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction Stloc(int v)
{
return new StLoc(localVariables[v], Pop(localVariables[v].StackType));
return new StLoc(localVariables[v], Pop(localVariables[v].StackType)) {
ILStackWasEmpty = currentStack.IsEmpty
};
}
private ILInstruction LdElem(IType type)

7
ICSharpCode.Decompiler/IL/Instructions/StLoc.cs

@ -27,6 +27,13 @@ namespace ICSharpCode.Decompiler.IL @@ -27,6 +27,13 @@ namespace ICSharpCode.Decompiler.IL
/// This field is only used in ILReader and BlockBuilder, and should be ignored by ILAst transforms.
/// </summary>
internal bool IsStackAdjustment;
/// <summary>
/// Gets whether the IL stack was empty after this store.
/// Only set for store instructions from the IL; not for stores to the stack
/// or other stores generated by transforms.
/// </summary>
internal bool ILStackWasEmpty;
internal override void CheckInvariant(ILPhase phase)
{

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

@ -235,6 +235,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -235,6 +235,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
} else if (r == FindResult.NamedArgument && (options & InliningOptions.IntroduceNamedArguments) != 0) {
Debug.Assert(loadInst.OpCode == OpCode.LdLoc);
StLoc originalStore = (StLoc)inlinedExpression.Parent;
if ((options & InliningOptions.Aggressive) == 0 && originalStore.ILStackWasEmpty)
return false;
context.Step($"Introduce named argument '{v.Name}'", inlinedExpression);
var call = (CallInstruction)loadInst.Parent;
if (!(call.Parent is Block namedArgBlock) || namedArgBlock.Kind != BlockKind.CallWithNamedArgs) {
@ -254,7 +257,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -254,7 +257,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
v.Kind = VariableKind.NamedArgument;
namedArgBlock.Instructions.Insert(call.IsInstanceCall ? 1 : 0, new StLoc(v, inlinedExpression));
namedArgBlock.Instructions.Insert(call.IsInstanceCall ? 1 : 0, originalStore);
return true;
}
return false;

Loading…
Cancel
Save