Browse Source

Add step messages to all block transforms.

pull/728/merge
Daniel Grunwald 9 years ago
parent
commit
760e02a511
  1. 3
      ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
  2. 30
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
  3. 2
      ICSharpCode.Decompiler/IL/Transforms/InlineCompilerGeneratedVariables.cs
  4. 4
      ICSharpCode.Decompiler/IL/Transforms/LoopingTransform.cs
  5. 11
      ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs
  6. 27
      ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

3
ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs

@ -38,6 +38,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -38,6 +38,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILInstruction copiedExpr;
if (block.Instructions[i].MatchStLoc(out v, out copiedExpr)) {
if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr)) {
context.Step($"Copy propagate {v.Name}", copiedExpr);
// un-inline the arguments of the ldArg instruction
ILVariable[] uninlinedArgs = new ILVariable[copiedExpr.Children.Count];
for (int j = 0; j < uninlinedArgs.Length; j++) {
@ -60,7 +61,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -60,7 +61,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
block.Instructions.RemoveAt(i);
int c = new ILInlining().InlineInto(block, i, aggressive: false);
int c = ILInlining.InlineInto(block, i, aggressive: false, context: context);
i -= c + 1;
}
}

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

@ -31,8 +31,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -31,8 +31,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
public class ILInlining : IILTransform, IBlockTransform
{
ILTransformContext context;
public void Run(ILFunction function, ILTransformContext context)
{
this.context = context;
foreach (var block in function.Descendants.OfType<Block>()) {
InlineAllInBlock(block);
}
@ -41,6 +44,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -41,6 +44,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
public void Run(Block block, BlockTransformContext context)
{
this.context = context;
InlineAllInBlock(block);
}
@ -49,7 +53,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -49,7 +53,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
bool modified = false;
int i = 0;
while (i < block.Instructions.Count) {
if (InlineOneIfPossible(block, i, aggressive: false)) {
if (InlineOneIfPossible(block, i, aggressive: false, context: context)) {
modified = true;
i = Math.Max(0, i - 1);
// Go back one step
@ -64,13 +68,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -64,13 +68,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Inlines instructions before pos into block.Instructions[pos].
/// </summary>
/// <returns>The number of instructions that were inlined.</returns>
public int InlineInto(Block block, int pos, bool aggressive)
public static int InlineInto(Block block, int pos, bool aggressive, ILTransformContext context)
{
if (pos >= block.Instructions.Count)
return 0;
int count = 0;
while (--pos >= 0) {
if (InlineOneIfPossible(block, pos, aggressive))
if (InlineOneIfPossible(block, pos, aggressive, context))
count++;
else
break;
@ -85,10 +89,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -85,10 +89,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <remarks>
/// After the operation, pos will point to the new combined instruction.
/// </remarks>
public bool InlineIfPossible(Block block, ref int pos)
public static bool InlineIfPossible(Block block, ref int pos, ILTransformContext context)
{
if (InlineOneIfPossible(block, pos, true)) {
pos -= InlineInto(block, pos, false);
if (InlineOneIfPossible(block, pos, true, context)) {
pos -= InlineInto(block, pos, false, context);
return true;
}
return false;
@ -97,8 +101,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -97,8 +101,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary>
/// Inlines the stloc instruction at block.Instructions[pos] into the next instruction, if possible.
/// </summary>
public bool InlineOneIfPossible(Block block, int pos, bool aggressive)
public static bool InlineOneIfPossible(Block block, int pos, bool aggressive, ILTransformContext context)
{
context.CancellationToken.ThrowIfCancellationRequested();
StLoc stloc = block.Instructions[pos] as StLoc;
if (stloc == null || stloc.Variable.Kind == VariableKind.PinnedLocal)
return false;
@ -108,7 +113,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -108,7 +113,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (v.LoadCount > 1 || v.LoadCount + v.AddressCount != 1)
return false;
return InlineOne(stloc, aggressive);
return InlineOne(stloc, aggressive, context);
}
/// <summary>
@ -117,12 +122,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -117,12 +122,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Note that this method does not check whether 'v' has only one use;
/// the caller is expected to validate whether inlining 'v' has any effects on other uses of 'v'.
/// </summary>
public static bool InlineOne(StLoc stloc, bool aggressive)
public static bool InlineOne(StLoc stloc, bool aggressive, ILTransformContext context)
{
ILVariable v = stloc.Variable;
Block block = (Block)stloc.Parent;
int pos = stloc.ChildIndex;
if (DoInline(v, stloc.Value, block.Instructions.ElementAtOrDefault(pos + 1), aggressive)) {
if (DoInline(v, stloc.Value, block.Instructions.ElementAtOrDefault(pos + 1), aggressive, context)) {
// Assign the ranges of the stloc instruction:
stloc.Value.AddILRange(stloc.ILRange);
// Remove the stloc instruction:
@ -134,9 +139,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -134,9 +139,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (SemanticHelper.IsPure(stloc.Value.Flags)) {
// Remove completely if the instruction has no effects
// (except for reading locals)
context.Step("Remove dead store without side effects", stloc);
block.Instructions.RemoveAt(pos);
return true;
} else if (v.Kind == VariableKind.StackSlot) {
context.Step("Remove dead store, but keep expression", stloc);
// Assign the ranges of the stloc instruction:
stloc.Value.AddILRange(stloc.ILRange);
// Remove the stloc, but keep the inner expression
@ -153,7 +160,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -153,7 +160,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Note that this method does not check whether 'v' has only one use;
/// the caller is expected to validate whether inlining 'v' has any effects on other uses of 'v'.
/// </summary>
static bool DoInline(ILVariable v, ILInstruction inlinedExpression, ILInstruction next, bool aggressive)
static bool DoInline(ILVariable v, ILInstruction inlinedExpression, ILInstruction next, bool aggressive, ILTransformContext context)
{
ILInstruction loadInst;
if (FindLoadInNext(next, v, inlinedExpression, out loadInst) == true) {
@ -166,6 +173,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -166,6 +173,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
}
context.Step($"Inline variable '{v.Name}'", inlinedExpression);
// Assign the ranges of the ldloc instruction:
inlinedExpression.AddILRange(loadInst.ILRange);

2
ICSharpCode.Decompiler/IL/Transforms/InlineCompilerGeneratedVariables.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
deadStores.Clear();
if (CanInlineVariable(g.Key, g, storesToInline, deadStores)) {
foreach (var stloc in storesToInline) {
ILInlining.InlineOne(stloc, aggressive: false);
ILInlining.InlineOne(stloc, aggressive: false, context: context);
}
foreach (var stloc in deadStores) {
if (SemanticHelper.IsPure(stloc.Flags)) {

4
ICSharpCode.Decompiler/IL/Transforms/LoopingTransform.cs

@ -40,6 +40,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -40,6 +40,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
do {
function.ResetDirty();
function.RunTransforms(children, context);
if (function.IsDirty)
context.Step("Function is dirty; running another loop iteration.", function);
} while (function.IsDirty);
}
@ -66,6 +68,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -66,6 +68,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
do {
block.ResetDirty();
block.RunTransforms(children, context);
if (block.IsDirty)
context.Step("Block is dirty; running another loop iteration.", block);
} while (block.IsDirty);
}

11
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

@ -54,17 +54,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -54,17 +54,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILInstruction[] values;
int initArrayPos;
if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, elementType, arrayLength, out values, out initArrayPos)) {
context.Step($"ForwardScanInitializeArrayRuntimeHelper", inst);
var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type);
var block = BlockFromInitializer(tempStore, elementType, arrayLength, values);
body.Instructions[pos].ReplaceWith(new StLoc(v, block));
body.Instructions.RemoveAt(initArrayPos);
new ILInlining().InlineIfPossible(body, ref pos);
ILInlining.InlineIfPossible(body, ref pos, context);
return true;
}
if (arrayLength.Length == 1) {
ILVariable finalStore;
int instructionsToRemove;
if (HandleSimpleArrayInitializer(body, pos + 1, v, arrayLength[0], out finalStore, out values, out instructionsToRemove)) {
context.Step($"HandleSimpleArrayInitializer", inst);
var block = new Block(BlockType.ArrayInitializer);
var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type);
block.Instructions.Add(new StLoc(tempStore, new NewArr(elementType, arrayLength.Select(l => new LdcI4(l)).ToArray())));
@ -79,10 +81,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -79,10 +81,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
body.Instructions[pos].ReplaceWith(new StLoc(finalStore ?? v, block));
RemoveInstructions(body, pos + 1, instructionsToRemove);
//body.Instructions.RemoveRange(pos + 1, values.Length + 1);
new ILInlining().InlineIfPossible(body, ref pos);
ILInlining.InlineIfPossible(body, ref pos, context);
return true;
}
if (HandleJaggedArrayInitializer(body, pos + 1, v, arrayLength[0], out finalStore, out values, out instructionsToRemove)) {
context.Step($"HandleJaggedArrayInitializer", inst);
var block = new Block(BlockType.ArrayInitializer);
var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type);
block.Instructions.Add(new StLoc(tempStore, new NewArr(elementType, arrayLength.Select(l => new LdcI4(l)).ToArray())));
@ -90,7 +93,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -90,7 +93,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
block.FinalInstruction = new LdLoc(tempStore);
body.Instructions[pos].ReplaceWith(new StLoc(finalStore, block));
RemoveInstructions(body, pos + 1, instructionsToRemove);
new ILInlining().InlineIfPossible(body, ref pos);
ILInlining.InlineIfPossible(body, ref pos, context);
return true;
}
}
@ -265,7 +268,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -265,7 +268,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var block = BlockFromInitializer(v, arrayType, length, values);
body.Instructions[pos].ReplaceWith(new StLoc(v, block));
body.Instructions.RemoveAt(initArrayPos);
new ILInlining().InlineIfPossible(body, ref pos);
ILInlining.InlineIfPossible(body, ref pos, context);
return true;
}
}

27
ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -->
/// stloc s(stobj (..., value))
/// </code>
static bool TransformInlineAssignmentStObj(Block block, int i)
bool TransformInlineAssignmentStObj(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
// in some cases it can be a compiler-generated local
@ -92,15 +92,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -92,15 +92,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms
TransformInlineAssignmentLocal(block, i);
return false;
}
context.Step("Inline assignment to instance field", fieldStore);
local = localStore.Variable;
block.Instructions.RemoveAt(i + 1);
} else if (nextInst is StObj) { // static fields
fieldStore = (StObj)nextInst;
if (!fieldStore.Value.MatchLdLoc(inst.Variable))
return false;
context.Step("Inline assignment to static field", fieldStore);
local = inst.Variable;
replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type);
} else return false;
} else {
return false;
}
block.Instructions.RemoveAt(i + 1);
inst.ReplaceWith(new StLoc(local, replacement));
return true;
@ -121,7 +125,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -121,7 +125,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -->
/// ... compound.op.new(callvirt(getter), value) ...
/// </code>
static bool TransformInlineAssignmentCall(Block block, int i)
bool TransformInlineAssignmentCall(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
// in some cases it can be a compiler-generated local
@ -150,6 +154,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -150,6 +154,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var usages = next.Descendants.Where(d => d.MatchLdLoc(localVariable)).ToArray();
if (usages.Length != 1)
return false;
context.Step($"Compound assignment to '{owner.Name}'", setterCall);
block.Instructions.RemoveAt(i + 1);
block.Instructions.RemoveAt(i);
usages[0].ReplaceWith(new CompoundAssignmentInstruction(binary.Operator, getterCall, binary.Right,
@ -163,7 +168,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -163,7 +168,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -->
/// stloc s(stloc l(value))
/// </code>
static void TransformInlineAssignmentLocal(Block block, int i)
void TransformInlineAssignmentLocal(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
@ -171,6 +176,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -171,6 +176,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return;
if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable))
return;
context.Step("Inline assignment to local variable", inst);
var value = inst.Value;
var var = nextInst.Variable;
var stackVar = inst.Variable;
@ -185,7 +191,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -185,7 +191,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -->
/// use ldaddress instead of ldloc s
/// </code>
static bool InlineLdAddressUsages(Block block, int i)
bool InlineLdAddressUsages(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
if (inst == null || inst.Variable.Kind != VariableKind.StackSlot || !(inst.Value is LdElema || inst.Value is LdFlda || inst.Value is LdsFlda))
@ -201,6 +207,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -201,6 +207,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
.Cast<ILInstruction>().ToArray();
if (affectedUsages.Length == 0 || affectedUsages.Any(ins => !(ins.Parent is StObj || ins.Parent is LdObj)))
return false;
context.Step($"InlineLdAddressUsage", inst);
foreach (var usage in affectedUsages) {
usage.ReplaceWith(valueToCopy.Clone());
}
@ -228,6 +235,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -228,6 +235,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if ((binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub) || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1))
return false;
context.Step($"TransformPostIncDecOperator", inst);
var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, inst.Variable.Type);
var assignment = new Block(BlockType.CompoundOperator);
assignment.Instructions.Add(new StLoc(tempStore, new LdLoc(nextInst.Variable)));
@ -245,7 +253,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -245,7 +253,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -->
/// stloc l(compound.op.old(ldobj(ldaddress), ldc.i4 1))
/// </code>
static bool TransformPostIncDecOperatorOnAddress(Block block, int i)
bool TransformPostIncDecOperatorOnAddress(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
@ -264,6 +272,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -264,6 +272,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (binary == null || !binary.Left.MatchLdLoc(nextInst.Variable) || !binary.Right.MatchLdcI4(1)
|| (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub))
return false;
context.Step($"TransformPostIncDecOperator", inst);
var assignment = new CompoundAssignmentInstruction(binary.Operator, new LdObj(inst.Value, targetType), binary.Right, targetType, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToOldValue);
stobj.ReplaceWith(new StLoc(nextInst.Variable, assignment));
block.Instructions.RemoveAt(i + 1);
@ -278,7 +287,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -278,7 +287,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -->
/// stloc l(compound.op.old(ldobj(ldflda(ldflda)), ldc.i4 1))
/// </code>
static bool TransformCSharp4PostIncDecOperatorOnAddress(Block block, int i)
bool TransformCSharp4PostIncDecOperatorOnAddress(Block block, int i)
{
var baseFieldAddress = block.Instructions[i] as StLoc;
var fieldValue = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
@ -313,6 +322,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -313,6 +322,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (binary == null || !binary.Left.MatchLdLoc(fieldValue.Variable) || !binary.Right.MatchLdcI4(1)
|| (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub))
return false;
context.Step($"TransformCSharp4PostIncDecOperatorOnAddress", baseFieldAddress);
var assignment = new CompoundAssignmentInstruction(binary.Operator, new LdObj(baseAddress, t), binary.Right, t, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToOldValue);
stobj.ReplaceWith(new StLoc(fieldValueCopyToLocal.Variable, assignment));
block.Instructions.RemoveAt(i + 2);
@ -326,7 +336,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -326,7 +336,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -->
/// stloc s(compound.op.old(ldobj(ldsflda), ldc.i4 1))
/// </code>
static bool TransformPostIncDecOnStaticField(Block block, int i)
bool TransformPostIncDecOnStaticField(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
var stobj = block.Instructions.ElementAtOrDefault(i + 1) as StObj;
@ -342,6 +352,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -342,6 +352,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var binary = stobj.Value as BinaryNumericInstruction;
if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1))
return false;
context.Step($"TransformPostIncDecOnStaticField", inst);
var assignment = new CompoundAssignmentInstruction(binary.Operator, inst.Value, binary.Right, type, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToOldValue);
stobj.ReplaceWith(new StLoc(inst.Variable, assignment));
return true;

Loading…
Cancel
Save