Browse Source

Merge #166 Fix split local variable post-increment recognition

pull/170/merge
Daniel Grunwald 14 years ago
parent
commit
0cae9b4983
  1. 61
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  2. 6
      ICSharpCode.Decompiler/Tests/IncrementDecrement.cs

61
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -440,6 +440,7 @@ namespace ICSharpCode.Decompiler.ILAst
#endregion #endregion
#region IntroducePostIncrement #region IntroducePostIncrement
bool IntroducePostIncrement(List<ILNode> body, ILExpression expr, int pos) bool IntroducePostIncrement(List<ILNode> body, ILExpression expr, int pos)
{ {
bool modified = IntroducePostIncrementForVariables(body, expr, pos); bool modified = IntroducePostIncrementForVariables(body, expr, pos);
@ -452,6 +453,13 @@ 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)
{ {
@ -465,19 +473,40 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression exprInit; ILExpression exprInit;
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;
if (!(exprInit.Code == ILCode.Ldloc || exprInit.Code == ILCode.Ldsfld || (exprInit.Code == ILCode.CallGetter && exprInit.Arguments.Count == 0)))
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; return false;
//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;
if (exprInit.Code == ILCode.CallGetter) { ILCode storeInstruction = nextExpr.Code;
if (!(nextExpr.Code == ILCode.CallSetter && IsGetterSetterPair(exprInit.Operand, nextExpr.Operand))) //Must be a matching store type
return false; if (_postIncrementPairs[loadInstruction] != storeInstruction)
} else { return false;
if (!(nextExpr.Code == (exprInit.Code == ILCode.Ldloc ? ILCode.Stloc : ILCode.Stsfld) && nextExpr.Operand == exprInit.Operand))
object nextExprOperand = nextExpr.Operand;
object exprInitOperand = exprInit.Operand;
if (loadInstruction == ILCode.CallGetter)
if (!IsGetterSetterPair(exprInitOperand, nextExprOperand))
return false; return false;
}
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;
ILExpression addExpr = nextExpr.Arguments[0]; ILExpression addExpr = nextExpr.Arguments[0];
int incrementAmount; int incrementAmount;
@ -485,12 +514,18 @@ namespace ICSharpCode.Decompiler.ILAst
if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar))) if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar)))
return false; return false;
if (exprInit.Code == ILCode.Ldloc) switch (loadInstruction)
exprInit.Code = ILCode.Ldloca; {
else if (exprInit.Code == ILCode.CallGetter) case ILCode.Ldloc:
exprInit = new ILExpression(ILCode.AddressOf, null, exprInit); exprInit.Code = ILCode.Ldloca;
else break;
exprInit.Code = ILCode.Ldsflda; case ILCode.Ldsfld:
exprInit.Code = ILCode.Ldsflda;
break;
case ILCode.CallGetter:
exprInit = new ILExpression(ILCode.AddressOf, null, exprInit);
break;
}
expr.Arguments[0] = new ILExpression(incrementCode, incrementAmount, exprInit); expr.Arguments[0] = new ILExpression(incrementCode, incrementAmount, exprInit);
body.RemoveAt(pos + 1); // TODO ILRanges body.RemoveAt(pos + 1); // TODO ILRanges
return true; return true;

6
ICSharpCode.Decompiler/Tests/IncrementDecrement.cs

@ -176,6 +176,12 @@ public class IncrementDecrement
return i++ + j; return i++ + j;
} }
public void PostIncrementInlineLocalVariable(Func<int, int> f)
{
int num = 0;
f(num++);
}
public int PostIncrementArrayElement(int[] array, int pos) public int PostIncrementArrayElement(int[] array, int pos)
{ {
return array[pos]--; return array[pos]--;

Loading…
Cancel
Save