|
|
|
@ -236,40 +236,26 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -236,40 +236,26 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
} while(modified); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsStloc(ILBasicBlock bb, ref ILVariable locVar, ref ILExpression val, ref ILLabel fallLabel) |
|
|
|
|
{ |
|
|
|
|
if (bb.Body.Count == 1) { |
|
|
|
|
ILExpression expr; |
|
|
|
|
if (bb.Body[0].Match(ILCode.Stloc, out expr)) { |
|
|
|
|
locVar = (ILVariable)expr.Operand; |
|
|
|
|
val = expr.Arguments[0]; |
|
|
|
|
fallLabel = (ILLabel)bb.FallthoughGoto.Operand; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// scope is modified if successful
|
|
|
|
|
bool TrySimplifyTernaryOperator(List<ILNode> scope, ILBasicBlock head) |
|
|
|
|
{ |
|
|
|
|
Debug.Assert(scope.Contains(head)); |
|
|
|
|
|
|
|
|
|
ILExpression condExpr = null; |
|
|
|
|
ILLabel trueLabel = null; |
|
|
|
|
ILLabel falseLabel = null; |
|
|
|
|
ILVariable trueLocVar = null; |
|
|
|
|
ILExpression trueExpr = null; |
|
|
|
|
ILLabel trueFall = null; |
|
|
|
|
ILVariable falseLocVar = null; |
|
|
|
|
ILExpression falseExpr = null; |
|
|
|
|
ILLabel falseFall = null; |
|
|
|
|
|
|
|
|
|
if(head.MatchBrTure(out condExpr, out trueLabel, out falseLabel) && |
|
|
|
|
ILExpression condExpr; |
|
|
|
|
ILLabel trueLabel; |
|
|
|
|
ILLabel falseLabel; |
|
|
|
|
ILVariable trueLocVar; |
|
|
|
|
ILExpression trueExpr; |
|
|
|
|
ILLabel trueFall; |
|
|
|
|
ILVariable falseLocVar; |
|
|
|
|
ILExpression falseExpr; |
|
|
|
|
ILLabel falseFall; |
|
|
|
|
|
|
|
|
|
if(head.Match(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) && |
|
|
|
|
labelGlobalRefCount[trueLabel] == 1 && |
|
|
|
|
labelGlobalRefCount[falseLabel] == 1 && |
|
|
|
|
IsStloc(labelToBasicBlock[trueLabel], ref trueLocVar, ref trueExpr, ref trueFall) && |
|
|
|
|
IsStloc(labelToBasicBlock[falseLabel], ref falseLocVar, ref falseExpr, ref falseFall) && |
|
|
|
|
labelToBasicBlock[trueLabel].Match(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) && |
|
|
|
|
labelToBasicBlock[falseLabel].Match(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) && |
|
|
|
|
trueLocVar == falseLocVar && |
|
|
|
|
trueFall == falseFall) |
|
|
|
|
{ |
|
|
|
@ -298,7 +284,7 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -298,7 +284,7 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
ILExpression condExpr; |
|
|
|
|
ILLabel trueLabel; |
|
|
|
|
ILLabel falseLabel; |
|
|
|
|
if(head.MatchBrTure(out condExpr, out trueLabel, out falseLabel)) { |
|
|
|
|
if(head.Match(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel)) { |
|
|
|
|
for (int pass = 0; pass < 2; pass++) { |
|
|
|
|
|
|
|
|
|
// On the second pass, swap labels and negate expression of the first branch
|
|
|
|
@ -314,7 +300,7 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -314,7 +300,7 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
if (scope.Contains(nextBasicBlock) && |
|
|
|
|
nextBasicBlock != head && |
|
|
|
|
labelGlobalRefCount[nextBasicBlock.EntryLabel] == 1 && |
|
|
|
|
nextBasicBlock.MatchBrTure(out nextCondExpr, out nextTrueLablel, out nextFalseLabel) && |
|
|
|
|
nextBasicBlock.Match(ILCode.Brtrue, out nextTrueLablel, out nextCondExpr, out nextFalseLabel) && |
|
|
|
|
(otherLablel == nextFalseLabel || otherLablel == nextTrueLablel)) |
|
|
|
|
{ |
|
|
|
|
// Create short cicuit branch
|
|
|
|
@ -355,9 +341,7 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -355,9 +341,7 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) { |
|
|
|
|
for (int i = 0; i < block.Body.Count; i++) { |
|
|
|
|
ILLabel targetLabel; |
|
|
|
|
if (block.Body[i].Match(ILCode.Br, out targetLabel) || |
|
|
|
|
block.Body[i].Match(ILCode.Leave, out targetLabel)) |
|
|
|
|
{ |
|
|
|
|
if (block.Body[i].Match(ILCode.Br, out targetLabel) || block.Body[i].Match(ILCode.Leave, out targetLabel)) { |
|
|
|
|
// Skip extra labels
|
|
|
|
|
while(nextSibling.ContainsKey(targetLabel) && nextSibling[targetLabel] is ILLabel) { |
|
|
|
|
targetLabel = (ILLabel)nextSibling[targetLabel]; |
|
|
|
@ -365,17 +349,17 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -365,17 +349,17 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
|
|
|
|
|
// Inline return statement
|
|
|
|
|
ILNode target; |
|
|
|
|
ILExpression retExpr; |
|
|
|
|
List<ILExpression> retArgs; |
|
|
|
|
if (nextSibling.TryGetValue(targetLabel, out target) && |
|
|
|
|
target.Match(ILCode.Ret, out retExpr)) |
|
|
|
|
target.Match(ILCode.Ret, out retArgs)) |
|
|
|
|
{ |
|
|
|
|
ILVariable locVar; |
|
|
|
|
object constValue; |
|
|
|
|
if (retExpr.Arguments.Count == 0) { |
|
|
|
|
if (retArgs.Count == 0) { |
|
|
|
|
block.Body[i] = new ILExpression(ILCode.Ret, null); |
|
|
|
|
} else if (retExpr.Arguments.Single().Match(ILCode.Ldloc, out locVar)) { |
|
|
|
|
} else if (retArgs.Single().Match(ILCode.Ldloc, out locVar)) { |
|
|
|
|
block.Body[i] = new ILExpression(ILCode.Ret, null, new ILExpression(ILCode.Ldloc, locVar)); |
|
|
|
|
} else if (retExpr.Arguments.Single().Match(ILCode.Ldc_I4, out constValue)) { |
|
|
|
|
} else if (retArgs.Single().Match(ILCode.Ldc_I4, out constValue)) { |
|
|
|
|
block.Body[i] = new ILExpression(ILCode.Ret, null, new ILExpression(ILCode.Ldc_I4, constValue)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -467,7 +451,7 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -467,7 +451,7 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
ILExpression condExpr; |
|
|
|
|
ILLabel trueLabel; |
|
|
|
|
ILLabel falseLabel; |
|
|
|
|
if(basicBlock.MatchBrTure(out condExpr, out trueLabel, out falseLabel)) |
|
|
|
|
if(basicBlock.Match(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel)) |
|
|
|
|
{ |
|
|
|
|
ControlFlowNode trueTarget; |
|
|
|
|
labelToCfNode.TryGetValue(trueLabel, out trueTarget); |
|
|
|
@ -581,9 +565,10 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -581,9 +565,10 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
|
|
|
|
|
// Switch
|
|
|
|
|
ILLabel[] caseLabels; |
|
|
|
|
if (condBranch.Match(ILCode.Switch, out caseLabels)) { |
|
|
|
|
List<ILExpression> switchArgs; |
|
|
|
|
if (condBranch.Match(ILCode.Switch, out caseLabels, out switchArgs)) { |
|
|
|
|
|
|
|
|
|
ILSwitch ilSwitch = new ILSwitch() { Condition = condBranch.Arguments.Single() }; |
|
|
|
|
ILSwitch ilSwitch = new ILSwitch() { Condition = switchArgs.Single() }; |
|
|
|
|
ILBasicBlock newBB = new ILBasicBlock() { |
|
|
|
|
EntryLabel = block.EntryLabel, // Keep the entry label
|
|
|
|
|
Body = { ilSwitch }, |
|
|
|
@ -662,7 +647,7 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -662,7 +647,7 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
ILExpression condExpr; |
|
|
|
|
ILLabel trueLabel; |
|
|
|
|
ILLabel falseLabel; |
|
|
|
|
if(block.MatchBrTure(out condExpr, out trueLabel, out falseLabel)) { |
|
|
|
|
if(block.Match(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel)) { |
|
|
|
|
|
|
|
|
|
// Swap bodies since that seems to be the usual C# order
|
|
|
|
|
ILLabel temp = trueLabel; |
|
|
|
@ -852,17 +837,12 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -852,17 +837,12 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
return expr != null && expr.Prefixes == null && expr.Code == code; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool Match(this ILNode node, ILCode code, out ILExpression expr) |
|
|
|
|
{ |
|
|
|
|
expr = node as ILExpression; |
|
|
|
|
return expr != null && expr.Prefixes == null && expr.Code == code; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool Match<T>(this ILNode node, ILCode code, out T operand) |
|
|
|
|
{ |
|
|
|
|
ILExpression expr = node as ILExpression; |
|
|
|
|
if (expr != null && expr.Prefixes == null && expr.Code == code) { |
|
|
|
|
operand = (T)expr.Operand; |
|
|
|
|
Debug.Assert(expr.Arguments.Count == 0); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
operand = default(T); |
|
|
|
@ -873,6 +853,7 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -873,6 +853,7 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
{ |
|
|
|
|
ILExpression expr = node as ILExpression; |
|
|
|
|
if (expr != null && expr.Prefixes == null && expr.Code == code) { |
|
|
|
|
Debug.Assert(expr.Operand == null); |
|
|
|
|
args = expr.Arguments; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -880,18 +861,41 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -880,18 +861,41 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool MatchBrTure(this ILBasicBlock bb, out ILExpression condition, out ILLabel trueLabel, out ILLabel falseLabel) |
|
|
|
|
public static bool Match<T>(this ILNode node, ILCode code, out T operand, out List<ILExpression> args) |
|
|
|
|
{ |
|
|
|
|
ILExpression expr = node as ILExpression; |
|
|
|
|
if (expr != null && expr.Prefixes == null && expr.Code == code) { |
|
|
|
|
operand = (T)expr.Operand; |
|
|
|
|
args = expr.Arguments; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
operand = default(T); |
|
|
|
|
args = null; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool Match<T>(this ILNode node, ILCode code, out T operand, out ILExpression arg) |
|
|
|
|
{ |
|
|
|
|
List<ILExpression> args; |
|
|
|
|
if (node.Match(code, out operand, out args)) { |
|
|
|
|
arg = args.Single(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
arg = null; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool Match<T>(this ILBasicBlock bb, ILCode code, out T operand, out ILExpression arg, out ILLabel fallLabel) |
|
|
|
|
{ |
|
|
|
|
if (bb.Body.Count == 1) { |
|
|
|
|
if (bb.Body[0].Match(ILCode.Brtrue, out trueLabel)) { |
|
|
|
|
condition = ((ILExpression)bb.Body[0]).Arguments.Single(); |
|
|
|
|
falseLabel = (ILLabel)((ILExpression)bb.FallthoughGoto).Operand; |
|
|
|
|
if (bb.Body[0].Match(code, out operand, out arg)) { |
|
|
|
|
fallLabel = (ILLabel)bb.FallthoughGoto.Operand; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
condition = null; |
|
|
|
|
trueLabel = null; |
|
|
|
|
falseLabel = null; |
|
|
|
|
operand = default(T); |
|
|
|
|
arg = null; |
|
|
|
|
fallLabel = null; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|