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

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

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

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

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

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

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

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

@ -54,17 +54,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILInstruction[] values; ILInstruction[] values;
int initArrayPos; int initArrayPos;
if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, elementType, arrayLength, out values, out 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 tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type);
var block = BlockFromInitializer(tempStore, elementType, arrayLength, values); var block = BlockFromInitializer(tempStore, elementType, arrayLength, values);
body.Instructions[pos].ReplaceWith(new StLoc(v, block)); body.Instructions[pos].ReplaceWith(new StLoc(v, block));
body.Instructions.RemoveAt(initArrayPos); body.Instructions.RemoveAt(initArrayPos);
new ILInlining().InlineIfPossible(body, ref pos); ILInlining.InlineIfPossible(body, ref pos, context);
return true; return true;
} }
if (arrayLength.Length == 1) { if (arrayLength.Length == 1) {
ILVariable finalStore; ILVariable finalStore;
int instructionsToRemove; int instructionsToRemove;
if (HandleSimpleArrayInitializer(body, pos + 1, v, arrayLength[0], out finalStore, out values, out 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 block = new Block(BlockType.ArrayInitializer);
var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type); 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()))); 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
body.Instructions[pos].ReplaceWith(new StLoc(finalStore ?? v, block)); body.Instructions[pos].ReplaceWith(new StLoc(finalStore ?? v, block));
RemoveInstructions(body, pos + 1, instructionsToRemove); RemoveInstructions(body, pos + 1, instructionsToRemove);
//body.Instructions.RemoveRange(pos + 1, values.Length + 1); //body.Instructions.RemoveRange(pos + 1, values.Length + 1);
new ILInlining().InlineIfPossible(body, ref pos); ILInlining.InlineIfPossible(body, ref pos, context);
return true; return true;
} }
if (HandleJaggedArrayInitializer(body, pos + 1, v, arrayLength[0], out finalStore, out values, out instructionsToRemove)) { 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 block = new Block(BlockType.ArrayInitializer);
var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type); 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()))); 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
block.FinalInstruction = new LdLoc(tempStore); block.FinalInstruction = new LdLoc(tempStore);
body.Instructions[pos].ReplaceWith(new StLoc(finalStore, block)); body.Instructions[pos].ReplaceWith(new StLoc(finalStore, block));
RemoveInstructions(body, pos + 1, instructionsToRemove); RemoveInstructions(body, pos + 1, instructionsToRemove);
new ILInlining().InlineIfPossible(body, ref pos); ILInlining.InlineIfPossible(body, ref pos, context);
return true; return true;
} }
} }
@ -265,7 +268,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var block = BlockFromInitializer(v, arrayType, length, values); var block = BlockFromInitializer(v, arrayType, length, values);
body.Instructions[pos].ReplaceWith(new StLoc(v, block)); body.Instructions[pos].ReplaceWith(new StLoc(v, block));
body.Instructions.RemoveAt(initArrayPos); body.Instructions.RemoveAt(initArrayPos);
new ILInlining().InlineIfPossible(body, ref pos); ILInlining.InlineIfPossible(body, ref pos, context);
return true; return true;
} }
} }

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

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

Loading…
Cancel
Save