Browse Source

Include blocks jumping outside the parent not as being conditionals

pull/1/head^2
David Srbecký 18 years ago
parent
commit
27d8b0107d
  1. 1
      src/AstBuilder.cs
  2. 39
      src/ControlFlow/Node-Optimize.cs
  3. 2
      src/ControlFlow/NodeCollection.cs
  4. 20
      src/Transforms/Ast/RestoreLoop.cs

1
src/AstBuilder.cs

@ -29,7 +29,6 @@ namespace Decompiler
} }
if (Options.ReduceAstLoops) { if (Options.ReduceAstLoops) {
astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
} }
if (Options.ReduceAstOther) { if (Options.ReduceAstOther) {
astCompileUnit.AcceptVisitor(new Transforms.Ast.SimplifyTypeReferences(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.SimplifyTypeReferences(), null);

39
src/ControlFlow/Node-Optimize.cs

@ -13,7 +13,7 @@ namespace Decompiler.ControlFlow
OptimizeLoops(); OptimizeLoops();
} }
if (Options.ReduceConditonals) { if (Options.ReduceConditonals) {
OptimizeIf(); OptimizeConditions();
} }
} }
@ -43,33 +43,38 @@ namespace Decompiler.ControlFlow
} }
} }
NodeCollection GetReachableNodes(Node exclude) NodeCollection GetReachableNodes()
{ {
NodeCollection reachableNodes = new NodeCollection(); NodeCollection reachableNodes = new NodeCollection();
reachableNodes.Add(this); reachableNodes.Add(this);
for(int i = 0; i < reachableNodes.Count; i++) { for(int i = 0; i < reachableNodes.Count; i++) {
reachableNodes.AddRange(reachableNodes[i].Successors); foreach(Node alsoReachable in reachableNodes[i].Successors) {
reachableNodes.Remove(exclude); // Do not go though the head child
if (alsoReachable != this.Parent.HeadChild) {
reachableNodes.Add(alsoReachable);
}
}
} }
return reachableNodes; return reachableNodes;
} }
public void OptimizeIf() public void OptimizeConditions()
{ {
foreach(Node child in this.Childs) { foreach(Node child in this.Childs) {
if (child is Loop) { if (child is Loop) {
child.OptimizeIf(); child.OptimizeConditions();
} }
} }
Node conditionNode = this.HeadChild; Node conditionNode = this.HeadChild;
// Find conditionNode (the start)
while(conditionNode != null) { while(conditionNode != null) {
if (conditionNode is BasicBlock && conditionNode.Successors.Count == 2) { // Keep looking for some conditional block
// Found if start if (conditionNode is BasicBlock && ((BasicBlock)conditionNode).IsConditionalBranch) {
// Found start of conditional
OptimizeIf((BasicBlock)conditionNode); OptimizeIf((BasicBlock)conditionNode);
// Restart
conditionNode = this.HeadChild; conditionNode = this.HeadChild;
continue; // Restart continue;
} else if (conditionNode.Successors.Count > 0) { } else if (conditionNode.Successors.Count > 0) {
// Keep looking down // Keep looking down
conditionNode = conditionNode.Successors[0]; conditionNode = conditionNode.Successors[0];
@ -87,12 +92,9 @@ namespace Decompiler.ControlFlow
{ {
Node trueStart = condition.FloatUpToNeighbours(condition.FallThroughBasicBlock); Node trueStart = condition.FloatUpToNeighbours(condition.FallThroughBasicBlock);
Node falseStart = condition.FloatUpToNeighbours(condition.BranchBasicBlock); Node falseStart = condition.FloatUpToNeighbours(condition.BranchBasicBlock);
Debug.Assert(trueStart != null);
Debug.Assert(falseStart != null);
Debug.Assert(trueStart != falseStart);
NodeCollection trueReachable = trueStart.GetReachableNodes(condition); NodeCollection trueReachable = trueStart != null ? trueStart.GetReachableNodes() : NodeCollection.Empty;
NodeCollection falseReachable = falseStart.GetReachableNodes(condition); NodeCollection falseReachable = falseStart != null ? falseStart.GetReachableNodes() : NodeCollection.Empty;
NodeCollection commonReachable = NodeCollection.Intersect(trueReachable, falseReachable); NodeCollection commonReachable = NodeCollection.Intersect(trueReachable, falseReachable);
NodeCollection trueNodes = trueReachable.Clone(); NodeCollection trueNodes = trueReachable.Clone();
@ -111,11 +113,14 @@ namespace Decompiler.ControlFlow
trueNodes.MoveTo(conditionalNode.TrueBody); trueNodes.MoveTo(conditionalNode.TrueBody);
if (Options.ReduceGraph-- <= 0) return; if (Options.ReduceGraph-- <= 0) return;
// We can exit the 'true' part of Loop or MethodBody conviently using 'break' or 'return'
if (commonReachable.Count > 0 && (conditionalNode.Parent is Loop || conditionalNode.Parent is MethodBodyGraph)) {
falseNodes.MoveTo(conditionalNode.FalseBody); falseNodes.MoveTo(conditionalNode.FalseBody);
}
// Optimize the created subtrees // Optimize the created subtrees
conditionalNode.TrueBody.OptimizeIf(); conditionalNode.TrueBody.OptimizeConditions();
conditionalNode.FalseBody.OptimizeIf(); conditionalNode.FalseBody.OptimizeConditions();
} }
} }
} }

2
src/ControlFlow/NodeCollection.cs

@ -19,6 +19,8 @@ namespace Decompiler.ControlFlow
public class NodeCollection: System.Collections.ObjectModel.Collection<Node> public class NodeCollection: System.Collections.ObjectModel.Collection<Node>
{ {
public static NodeCollection Empty = new NodeCollection();
public event EventHandler<NodeEventArgs> Added; public event EventHandler<NodeEventArgs> Added;
public event EventHandler<NodeEventArgs> Removed; public event EventHandler<NodeEventArgs> Removed;

20
src/Transforms/Ast/RestoreLoop.cs

@ -40,6 +40,26 @@ namespace Decompiler.Transforms.Ast
} }
} }
// Restore loop condition (version 2)
if (forStatement.Condition.IsNull) {
IfElseStatement condition = forStatement.EmbeddedStatement.Children.First as IfElseStatement;
if (condition != null &&
condition.TrueStatement[0] is BlockStatement &&
condition.TrueStatement[0].Children.Count == 1 &&
condition.TrueStatement[0].Children.First is BreakStatement &&
condition.FalseStatement[0] is BlockStatement &&
condition.FalseStatement[0].Children.Count == 0)
{
UnaryOperatorExpression negExpr = condition.Condition as UnaryOperatorExpression;
if (negExpr != null &&
negExpr.Op == UnaryOperatorType.Not) {
condition.Remove();
forStatement.Condition = negExpr.Expression;
}
}
}
// Restore loop iterator // Restore loop iterator
if (forStatement.EmbeddedStatement.Children.Count > 0 && if (forStatement.EmbeddedStatement.Children.Count > 0 &&
forStatement.Iterator.Count == 0) forStatement.Iterator.Count == 0)

Loading…
Cancel
Save