diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index a69b91d8d..7a2f2e7e9 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -47,6 +47,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms continue; if (TransformRoslynCompoundAssignmentCall(block, i)) continue; + if (TransformRoslynPostIncDecOperatorOnAddress(block, i)) + continue; } } @@ -299,12 +301,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool TransformPostIncDecOperatorOnAddress(Block block, int i) { var inst = block.Instructions[i] as StLoc; - if (!inst.Variable.IsSingleDefinition || inst.Variable.LoadCount != 2) - return false; var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; var stobj = block.Instructions.ElementAtOrDefault(i + 2) as StObj; if (inst == null || nextInst == null || stobj == null) return false; + if (!inst.Variable.IsSingleDefinition || inst.Variable.LoadCount != 2) + return false; if (!(inst.Value is LdElema || inst.Value is LdFlda || inst.Value is LdsFlda)) return false; ILInstruction target; @@ -323,7 +325,35 @@ namespace ICSharpCode.Decompiler.IL.Transforms block.Instructions.RemoveAt(i + 1); return true; } - + + /// + /// stloc l(ldobj(ldflda(target))) + /// stobj(ldflda(target), binary.op(ldloc l, ldc.i4 1)) + /// --> + /// compound.op.old(ldobj(ldflda(target)), ldc.i4 1) + /// + bool TransformRoslynPostIncDecOperatorOnAddress(Block block, int i) + { + var inst = block.Instructions[i] as StLoc; + var stobj = block.Instructions.ElementAtOrDefault(i + 1) as StObj; + if (inst == null || stobj == null) + return false; + if (!inst.Value.MatchLdObj(out var loadTarget, out var loadType) || !loadTarget.MatchLdFlda(out var fieldTarget, out var field)) + return false; + if (!stobj.Target.MatchLdFlda(out var fieldTarget2, out var field2)) + return false; + if (!fieldTarget.Match(fieldTarget2).Success || !field.Equals(field2)) + return false; + var binary = stobj.Value as BinaryNumericInstruction; + if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1) + || (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub)) + return false; + context.Step($"TransformRoslynPostIncDecOperator", inst); + stobj.ReplaceWith(new CompoundAssignmentInstruction(binary, inst.Value, binary.Right, loadType, CompoundAssignmentType.EvaluatesToOldValue)); + block.Instructions.RemoveAt(i); + return true; + } + /// /// stloc s(ldflda) /// stloc s2(ldobj(ldflda(ldloc s)))