Browse Source

Label is not reference counted object anymore, it is just a string. During transform we in two passes - find all live labels - remove all dead ones (the rest).

pull/1/head^2
David Srbecký 18 years ago
parent
commit
35f06e0a4b
  1. 3
      Decompiler.csproj
  2. 27
      src/AstMetodBodyBuilder.cs
  3. 26
      src/ControlFlow/Node-Structure.cs
  4. 40
      src/MyAst/MyGotoStatement.cs
  5. 21
      src/MyAst/MyLabelStatement.cs
  6. 27
      src/Transforms/Ast/RemoveDeadLabels.cs
  7. 11
      src/Transforms/Ast/RemoveGotos.cs
  8. 7
      src/Transforms/Ast/RestoreLoop.cs

3
Decompiler.csproj

@ -44,7 +44,6 @@ @@ -44,7 +44,6 @@
<ItemGroup>
<Folder Include="src" />
<Folder Include="src\ControlFlow" />
<Folder Include="src\MyAst" />
<Folder Include="src\Transforms" />
<Folder Include="src\Transforms\Ast" />
<Compile Include="src\AssemblyInfo.cs" />
@ -62,8 +61,6 @@ @@ -62,8 +61,6 @@
<Compile Include="src\ControlFlow\Node-Structure.cs" />
<Compile Include="src\MainForm.cs" />
<Compile Include="src\MainForm.Designer.cs" />
<Compile Include="src\MyAst\MyGotoStatement.cs" />
<Compile Include="src\MyAst\MyLabelStatement.cs" />
<Compile Include="src\Options.cs" />
<Compile Include="src\Program.cs" />
<Compile Include="src\ByteCode.StackAnalysis.cs" />

27
src/AstMetodBodyBuilder.cs

@ -77,7 +77,7 @@ namespace Decompiler @@ -77,7 +77,7 @@ namespace Decompiler
yield return MakeComment("// " + node.Description);
}
yield return new Ast.MyLabelStatement(node.Label);
yield return new Ast.LabelStatement(node.Label);
if (node is BasicBlock) {
foreach(StackExpression expr in ((BasicBlock)node).Body) {
@ -86,7 +86,7 @@ namespace Decompiler @@ -86,7 +86,7 @@ namespace Decompiler
Node fallThroughNode = ((BasicBlock)node).FallThroughBasicBlock;
// If there is default branch and it is not the following node
if (fallThroughNode != null) {
yield return Ast.MyGotoStatement.Create(node, fallThroughNode);
yield return MakeBranchCommand(node, fallThroughNode);
}
} else if (node is AcyclicGraph) {
Ast.BlockStatement blockStatement = new Ast.BlockStatement();
@ -107,7 +107,7 @@ namespace Decompiler @@ -107,7 +107,7 @@ namespace Decompiler
}
} else if (node is ConditionalNode) {
ConditionalNode conditionalNode = (ConditionalNode)node;
yield return new Ast.MyLabelStatement(conditionalNode.Condition.Label);
yield return new Ast.LabelStatement(conditionalNode.Condition.Label);
Ast.Statement lastStatement = null;
foreach(StackExpression expr in conditionalNode.Condition.Body) {
lastStatement = TransformExpression(expr);
@ -121,7 +121,7 @@ namespace Decompiler @@ -121,7 +121,7 @@ namespace Decompiler
Ast.BlockStatement trueBlock = new Ast.BlockStatement();
// The block entry code
trueBlock.Children.Add(Ast.MyGotoStatement.Create(node, conditionalNode.Condition.FallThroughBasicBlock));
trueBlock.Children.Add(MakeBranchCommand(node, conditionalNode.Condition.FallThroughBasicBlock));
// Sugested content
trueBlock.Children.AddRange(TransformNode(conditionalNode.TrueBody));
ifElseStmt.TrueStatement.Add(trueBlock);
@ -178,6 +178,23 @@ namespace Decompiler @@ -178,6 +178,23 @@ namespace Decompiler
return new Ast.ExpressionStatement(new PrimitiveExpression(text, text));
}
public static Ast.Statement MakeBranchCommand(Node contextNode, Node targetNode)
{
// Propagate target up to the top most scope
while (targetNode.Parent != null && targetNode.Parent.HeadChild == targetNode) {
targetNode = targetNode.Parent;
}
// If branches to the start of encapsulating loop
if (contextNode.Parent is Loop && targetNode == contextNode.Parent) {
return new Ast.ContinueStatement();
}
// If branches outside the encapsulating loop
if (contextNode.Parent is Loop && targetNode == contextNode.Parent.NextNode) {
return new Ast.BreakStatement();
}
return new Ast.GotoStatement(targetNode.Label);
}
static object MakeCodeDomExpression(MethodDefinition methodDef, StackExpression expr, params Ast.Expression[] args)
{
List<Ast.Expression> allArgs = new List<Ast.Expression>();
@ -207,7 +224,7 @@ namespace Decompiler @@ -207,7 +224,7 @@ namespace Decompiler
Ast.Statement branchCommand = null;
if (operand is ByteCode) {
branchCommand = Ast.MyGotoStatement.Create(byteCode.Expression.BasicBlock, ((ByteCode)operand).Expression.BasicBlock);
branchCommand = MakeBranchCommand(byteCode.Expression.BasicBlock, ((ByteCode)operand).Expression.BasicBlock);
}
switch(opCode.Code) {

26
src/ControlFlow/Node-Structure.cs

@ -9,7 +9,7 @@ namespace Decompiler.ControlFlow @@ -9,7 +9,7 @@ namespace Decompiler.ControlFlow
public static int NextNodeID = 1;
int id;
NodeLabel label;
string label;
Node parent;
NodeCollection childs = new NodeCollection();
@ -22,7 +22,7 @@ namespace Decompiler.ControlFlow @@ -22,7 +22,7 @@ namespace Decompiler.ControlFlow
get { return id; }
}
public NodeLabel Label {
public string Label {
get { return label; }
}
@ -151,7 +151,7 @@ namespace Decompiler.ControlFlow @@ -151,7 +151,7 @@ namespace Decompiler.ControlFlow
protected Node()
{
this.id = NextNodeID++;
this.label = new NodeLabel(this.GetType().Name + "_" + ID);
this.label = this.GetType().Name + "_" + ID;
this.Childs.Added += delegate(object sender, NodeEventArgs e) {
if (e.Node.Parent != null) {
throw new Exception("Node is already assigned to other parent");
@ -230,24 +230,4 @@ namespace Decompiler.ControlFlow @@ -230,24 +230,4 @@ namespace Decompiler.ControlFlow
return sb.ToString();
}
}
public class NodeLabel
{
string label;
int referenceCount = 0;
public string Label {
get { return label; }
}
public int ReferenceCount {
get { return referenceCount; }
set { referenceCount = value; }
}
public NodeLabel(string label)
{
this.label = label;
}
}
}

40
src/MyAst/MyGotoStatement.cs

@ -1,40 +0,0 @@ @@ -1,40 +0,0 @@
using System;
using Ast = ICSharpCode.NRefactory.Ast;
using Decompiler.ControlFlow;
namespace ICSharpCode.NRefactory.Ast
{
public class MyGotoStatement: Ast.GotoStatement
{
NodeLabel nodeLabel;
public NodeLabel NodeLabel {
get { return nodeLabel; }
}
public MyGotoStatement(NodeLabel nodeLabel): base(nodeLabel.Label)
{
this.nodeLabel = nodeLabel;
this.nodeLabel.ReferenceCount++;
}
public static Ast.Statement Create(Node contextNode, Node targetNode)
{
// Propagate target up to the top most scope
while (targetNode.Parent != null && targetNode.Parent.HeadChild == targetNode) {
targetNode = targetNode.Parent;
}
// If branches to the start of encapsulating loop
if (contextNode.Parent is Loop && targetNode == contextNode.Parent) {
return new Ast.ContinueStatement();
}
// If branches outside the encapsulating loop
if (contextNode.Parent is Loop && targetNode == contextNode.Parent.NextNode) {
return new Ast.BreakStatement();
}
return new Ast.MyGotoStatement(targetNode.Label);
}
}
}

21
src/MyAst/MyLabelStatement.cs

@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
using System;
using Ast = ICSharpCode.NRefactory.Ast;
using Decompiler.ControlFlow;
namespace ICSharpCode.NRefactory.Ast
{
public class MyLabelStatement: Ast.LabelStatement
{
NodeLabel nodeLabel;
public NodeLabel NodeLabel {
get { return nodeLabel; }
}
public MyLabelStatement(NodeLabel nodeLabel): base(nodeLabel.Label)
{
this.nodeLabel = nodeLabel;
}
}
}

27
src/Transforms/Ast/RemoveDeadLabels.cs

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
using System;
using System.Collections.Generic;
using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors;
@ -8,12 +8,33 @@ namespace Decompiler.Transforms.Ast @@ -8,12 +8,33 @@ namespace Decompiler.Transforms.Ast
{
public class RemoveDeadLabels: AbstractAstTransformer
{
List<string> usedLabels = new List<string>();
bool collectingUsedLabels;
public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
{
collectingUsedLabels = true;
base.VisitMethodDeclaration(methodDeclaration, data);
collectingUsedLabels = false;
base.VisitMethodDeclaration(methodDeclaration, data);
return null;
}
public override object VisitGotoStatement(GotoStatement gotoStatement, object data)
{
if (collectingUsedLabels) {
usedLabels.Add(gotoStatement.Label);
}
return null;
}
public override object VisitLabelStatement(LabelStatement labelStatement, object data)
{
MyLabelStatement myLabel = (MyLabelStatement)labelStatement;
if (myLabel.NodeLabel.ReferenceCount == 0) {
if (!collectingUsedLabels) {
if (!usedLabels.Contains(labelStatement.Label)) {
RemoveCurrentNode();
}
}
return null;
}
}

11
src/Transforms/Ast/RemoveGotos.cs

@ -39,10 +39,9 @@ namespace Decompiler.Transforms.Ast @@ -39,10 +39,9 @@ namespace Decompiler.Transforms.Ast
if (lastStmt is GotoStatement &&
blockStatement.Parent is IfElseStatement)
{
MyLabelStatement nextNodeAsLabel = blockStatement.Parent.Next() as MyLabelStatement;
LabelStatement nextNodeAsLabel = blockStatement.Parent.Next() as LabelStatement;
if (nextNodeAsLabel != null) {
if (nextNodeAsLabel.NodeLabel == ((MyGotoStatement)lastStmt).NodeLabel) {
((MyGotoStatement)lastStmt).NodeLabel.ReferenceCount--;
if (nextNodeAsLabel.Label == ((GotoStatement)lastStmt).Label) {
lastStmt.Remove();
return null;
}
@ -54,10 +53,8 @@ namespace Decompiler.Transforms.Ast @@ -54,10 +53,8 @@ namespace Decompiler.Transforms.Ast
public override object VisitGotoStatement(GotoStatement gotoStatement, object data)
{
MyGotoStatement myGoto = (MyGotoStatement)gotoStatement;
MyLabelStatement followingLabel = myGoto.Next() as MyLabelStatement;
if (followingLabel != null && followingLabel.NodeLabel == myGoto.NodeLabel) {
myGoto.NodeLabel.ReferenceCount--;
LabelStatement followingLabel = gotoStatement.Next() as LabelStatement;
if (followingLabel != null && followingLabel.Label == gotoStatement.Label) {
RemoveCurrentNode();
}
return null;

7
src/Transforms/Ast/RestoreLoop.cs

@ -27,15 +27,14 @@ namespace Decompiler.Transforms.Ast @@ -27,15 +27,14 @@ namespace Decompiler.Transforms.Ast
{
IfElseStatement condition = forStatement.EmbeddedStatement.Children[0] as IfElseStatement;
BreakStatement breakStmt = forStatement.EmbeddedStatement.Children[1] as BreakStatement;
MyLabelStatement label = forStatement.EmbeddedStatement.Children[2] as MyLabelStatement;
LabelStatement label = forStatement.EmbeddedStatement.Children[2] as LabelStatement;
if (condition != null && breakStmt != null && label != null &&
condition.TrueStatement.Count == 1)
{
MyGotoStatement gotoStmt = condition.TrueStatement[0] as MyGotoStatement;
if (gotoStmt != null && gotoStmt.NodeLabel == label.NodeLabel) {
GotoStatement gotoStmt = condition.TrueStatement[0] as GotoStatement;
if (gotoStmt != null && gotoStmt.Label == label.Label) {
condition.Remove();
breakStmt.Remove();
gotoStmt.NodeLabel.ReferenceCount--;
forStatement.Condition = condition.Condition;
}
}

Loading…
Cancel
Save