|
|
@ -454,13 +454,6 @@ namespace ICSharpCode.Decompiler.ILAst |
|
|
|
return modified; |
|
|
|
return modified; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static IDictionary<ILCode, ILCode> _postIncrementPairs = new Dictionary<ILCode, ILCode> |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
{ILCode.Ldloc, ILCode.Stloc}, |
|
|
|
|
|
|
|
{ILCode.Ldsfld, ILCode.Stsfld}, |
|
|
|
|
|
|
|
{ILCode.CallGetter, ILCode.CallSetter} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool IntroducePostIncrementForVariables(List<ILNode> body, ILExpression expr, int pos) |
|
|
|
bool IntroducePostIncrementForVariables(List<ILNode> body, ILExpression expr, int pos) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Works for variables and static fields/properties
|
|
|
|
// Works for variables and static fields/properties
|
|
|
@ -474,38 +467,48 @@ namespace ICSharpCode.Decompiler.ILAst |
|
|
|
if (!(expr.Match(ILCode.Stloc, out exprVar, out exprInit) && exprVar.IsGenerated)) |
|
|
|
if (!(expr.Match(ILCode.Stloc, out exprVar, out exprInit) && exprVar.IsGenerated)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
ILCode loadInstruction = exprInit.Code; |
|
|
|
|
|
|
|
//We only recognise local variables, fields & getters with no arguments
|
|
|
|
|
|
|
|
if (!_postIncrementPairs.ContainsKey(loadInstruction)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (loadInstruction == ILCode.CallGetter && exprInit.Arguments.Count != 0) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//The next expression
|
|
|
|
//The next expression
|
|
|
|
ILExpression nextExpr = body.ElementAtOrDefault(pos + 1) as ILExpression; |
|
|
|
ILExpression nextExpr = body.ElementAtOrDefault(pos + 1) as ILExpression; |
|
|
|
if (nextExpr == null) |
|
|
|
if (nextExpr == null) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ILCode loadInstruction = exprInit.Code; |
|
|
|
ILCode storeInstruction = nextExpr.Code; |
|
|
|
ILCode storeInstruction = nextExpr.Code; |
|
|
|
//Must be a matching store type
|
|
|
|
bool recombineVariable = false; |
|
|
|
if (_postIncrementPairs[loadInstruction] != storeInstruction) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
object nextExprOperand = nextExpr.Operand; |
|
|
|
// We only recognise local variables, static fields, and static getters with no arguments
|
|
|
|
object exprInitOperand = exprInit.Operand; |
|
|
|
switch (loadInstruction) { |
|
|
|
if (loadInstruction == ILCode.CallGetter) |
|
|
|
case ILCode.Ldloc: |
|
|
|
if (!IsGetterSetterPair(exprInitOperand, nextExprOperand)) |
|
|
|
//Must be a matching store type
|
|
|
|
return false; |
|
|
|
if (storeInstruction != ILCode.Stloc) |
|
|
|
|
|
|
|
|
|
|
|
if (loadInstruction == ILCode.Ldloc) |
|
|
|
|
|
|
|
if ((nextExprOperand != exprInitOperand)) |
|
|
|
|
|
|
|
if (((ILVariable) nextExprOperand).OriginalVariable == ((ILVariable) exprInitOperand).OriginalVariable) |
|
|
|
|
|
|
|
//Spit local variable, unsplit these two instances
|
|
|
|
|
|
|
|
foreach (var ilExpression in body.SelectMany( |
|
|
|
|
|
|
|
node => node.GetSelfAndChildrenRecursive<ILExpression>( |
|
|
|
|
|
|
|
expression => expression.Operand == nextExprOperand))) |
|
|
|
|
|
|
|
ilExpression.Operand = exprInitOperand; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
ILVariable loadVar = (ILVariable)exprInit.Operand; |
|
|
|
|
|
|
|
ILVariable storeVar = (ILVariable)nextExpr.Operand; |
|
|
|
|
|
|
|
if (loadVar != storeVar) { |
|
|
|
|
|
|
|
if (loadVar.OriginalVariable != null && loadVar.OriginalVariable == storeVar.OriginalVariable) |
|
|
|
|
|
|
|
recombineVariable = true; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case ILCode.Ldsfld: |
|
|
|
|
|
|
|
if (storeInstruction != ILCode.Stsfld) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (exprInit.Operand != nextExpr.Operand) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case ILCode.CallGetter: |
|
|
|
|
|
|
|
// non-static getters would have the 'this' argument
|
|
|
|
|
|
|
|
if (exprInit.Arguments.Count != 0) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (storeInstruction != ILCode.CallSetter) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (!IsGetterSetterPair(exprInit.Operand, nextExpr.Operand)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ILExpression addExpr = nextExpr.Arguments[0]; |
|
|
|
ILExpression addExpr = nextExpr.Arguments[0]; |
|
|
|
|
|
|
|
|
|
|
@ -514,8 +517,13 @@ namespace ICSharpCode.Decompiler.ILAst |
|
|
|
if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar))) |
|
|
|
if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar))) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
switch (loadInstruction) |
|
|
|
if (recombineVariable) { |
|
|
|
{ |
|
|
|
// Split local variable, unsplit these two instances
|
|
|
|
|
|
|
|
foreach (var ilExpression in method.GetSelfAndChildrenRecursive<ILExpression>(expression => expression.Operand == nextExpr.Operand)) |
|
|
|
|
|
|
|
ilExpression.Operand = exprInit.Operand; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (loadInstruction) { |
|
|
|
case ILCode.Ldloc: |
|
|
|
case ILCode.Ldloc: |
|
|
|
exprInit.Code = ILCode.Ldloca; |
|
|
|
exprInit.Code = ILCode.Ldloca; |
|
|
|
break; |
|
|
|
break; |
|
|
|