Browse Source

make pattern for custom short circuit operator invocations more restrictive

pull/143/merge
Siegfried Pammer 14 years ago
parent
commit
2b366fbb97
  1. 39
      ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs

39
ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs

@ -258,6 +258,10 @@ namespace ICSharpCode.Decompiler.ILAst @@ -258,6 +258,10 @@ namespace ICSharpCode.Decompiler.ILAst
if (!head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out targetVar, out targetVarInitExpr))
return false;
ILVariable leftVar;
if (!targetVarInitExpr.Match(ILCode.Ldloc, out leftVar))
return false;
// looking for:
// brtrue(exitLabel, call(op_False, leftVar)
// br(followingBlock)
@ -267,12 +271,19 @@ namespace ICSharpCode.Decompiler.ILAst @@ -267,12 +271,19 @@ namespace ICSharpCode.Decompiler.ILAst
if(!head.MatchLastAndBr(ILCode.Brtrue, out exitLabel, out callExpr, out followingBlock))
return false;
MethodDefinition opFalse;
ILExpression leftVar;
if (!callExpr.Match(ILCode.Call, out opFalse, out leftVar))
if (labelGlobalRefCount[followingBlock] > 1)
return false;
MethodReference opFalse;
ILExpression opFalseArg;
if (!callExpr.Match(ILCode.Call, out opFalse, out opFalseArg))
return false;
// ignore operators other than op_False and op_True
if (opFalse.Name != "op_False" && opFalse.Name != "op_True")
return false;
if (!leftVar.MatchLdloc(targetVarInitExpr.Operand as ILVariable))
if (!opFalseArg.MatchLdloc(leftVar))
return false;
ILBasicBlock followingBasicBlock = labelToBasicBlock[followingBlock];
@ -286,22 +297,34 @@ namespace ICSharpCode.Decompiler.ILAst @@ -286,22 +297,34 @@ namespace ICSharpCode.Decompiler.ILAst
if (!followingBasicBlock.MatchSingleAndBr(ILCode.Stloc, out _targetVar, out opBitwiseCallExpr, out _exitLabel))
return false;
if (_targetVar != targetVar)
if (_targetVar != targetVar || exitLabel != _exitLabel)
return false;
MethodDefinition opBitwise;
MethodReference opBitwise;
ILExpression leftVarExpression;
ILExpression rightExpression;
if (!opBitwiseCallExpr.Match(ILCode.Call, out opBitwise, out leftVarExpression, out rightExpression))
return false;
if (!leftVar.MatchLdloc(leftVarExpression.Operand as ILVariable))
if (!opFalseArg.MatchLdloc(leftVarExpression.Operand as ILVariable))
return false;
// ignore operators other than op_BitwiseAnd and op_BitwiseOr
if (opBitwise.Name != "op_BitwiseAnd" && opBitwise.Name != "op_BitwiseOr")
return false;
// insert:
// stloc(targetVar, LogicAnd(C::op_BitwiseAnd, leftVar, rightExpression)
// br(exitLabel)
ILExpression shortCircuitExpr = MakeLeftAssociativeShortCircuit(opBitwise.Name == "op_BitwiseAnd" ? ILCode.LogicAnd : ILCode.LogicOr, leftVar, rightExpression);
ILCode op = opBitwise.Name == "op_BitwiseAnd" ? ILCode.LogicAnd : ILCode.LogicOr;
if (op == ILCode.LogicAnd && opFalse.Name != "op_False")
return false;
if (op == ILCode.LogicOr && opFalse.Name != "op_True")
return false;
ILExpression shortCircuitExpr = MakeLeftAssociativeShortCircuit(op, opFalseArg, rightExpression);
shortCircuitExpr.Operand = opBitwise;
head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br);

Loading…
Cancel
Save