Browse Source

Added custom Ast classes for Goto and Label statements that track the reference count of a label.

Added an Ast transform to remove dead labels.  (first Ast transform in program, I expect many more to come.  Some stuff should be rewritten to use these explicit transforms)
pull/1/head^2
David Srbecký 18 years ago
parent
commit
ecad71d802
  1. 6
      Decompiler.csproj
  2. 29
      src/AstMetodBodyBuilder.cs
  3. 32
      src/ControlFlow/Node-Structure.cs
  4. 40
      src/MyAst/MyGotoStatement.cs
  5. 21
      src/MyAst/MyLabelStatement.cs
  6. 19
      src/Transforms/Ast/RemoveDeadLabels.cs

6
Decompiler.csproj

@ -37,6 +37,9 @@ @@ -37,6 +37,9 @@
<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" />
<Compile Include="src\AstBuilder.cs" />
<Compile Include="src\AstMetodBodyBuilder.cs" />
@ -52,11 +55,14 @@ @@ -52,11 +55,14 @@
<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" />
<Compile Include="src\StackExpression.cs" />
<Compile Include="src\StackExpressionCollection.cs" />
<Compile Include="src\Transforms\Ast\RemoveDeadLabels.cs" />
<Compile Include="src\Util.cs" />
<EmbeddedResource Include="src\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>

29
src/AstMetodBodyBuilder.cs

@ -50,6 +50,8 @@ namespace Decompiler @@ -50,6 +50,8 @@ namespace Decompiler
astBlock.Children.AddRange(TransformNodes(bodyGraph.Childs));
astBlock.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
return astBlock;
}
@ -68,7 +70,7 @@ namespace Decompiler @@ -68,7 +70,7 @@ namespace Decompiler
yield return MakeComment("// " + node.Description);
}
yield return new Ast.LabelStatement(node.Label);
yield return new Ast.MyLabelStatement(node.Label);
if (node is BasicBlock) {
foreach(StackExpression expr in ((BasicBlock)node).Body) {
@ -77,7 +79,7 @@ namespace Decompiler @@ -77,7 +79,7 @@ namespace Decompiler
Node fallThroughNode = ((BasicBlock)node).FallThroughBasicBlock;
// If there is default branch and it is not the following node
if (fallThroughNode != null && fallThroughNode != node.NextNode) {
yield return MakeBranchCommand(node, fallThroughNode);
yield return Ast.MyGotoStatement.Create(node, fallThroughNode);
}
} else if (node is AcyclicGraph) {
Ast.BlockStatement blockStatement = new Ast.BlockStatement();
@ -98,7 +100,7 @@ namespace Decompiler @@ -98,7 +100,7 @@ namespace Decompiler
}
} else if (node is ConditionalNode) {
ConditionalNode conditionalNode = (ConditionalNode)node;
yield return new Ast.LabelStatement(conditionalNode.Condition.Label);
yield return new Ast.MyLabelStatement(conditionalNode.Condition.Label);
Ast.Statement lastStatement = null;
foreach(StackExpression expr in conditionalNode.Condition.Body) {
lastStatement = TransformExpression(expr);
@ -112,7 +114,7 @@ namespace Decompiler @@ -112,7 +114,7 @@ namespace Decompiler
Ast.BlockStatement trueBlock = new Ast.BlockStatement();
// The block entry code
trueBlock.Children.Add(MakeBranchCommand(node, conditionalNode.Condition.FallThroughBasicBlock));
trueBlock.Children.Add(Ast.MyGotoStatement.Create(node, conditionalNode.Condition.FallThroughBasicBlock));
// Sugested content
trueBlock.Children.AddRange(TransformNode(conditionalNode.TrueBody));
ifElseStmt.TrueStatement.Add(trueBlock);
@ -184,23 +186,6 @@ namespace Decompiler @@ -184,23 +186,6 @@ namespace Decompiler
return MakeCodeDomExpression(methodDef, expr.LastByteCode, allArgs.ToArray());
}
static Ast.Statement MakeBranchCommand(Node node, 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 (node.Parent is Loop && targetNode == node.Parent) {
return new Ast.ContinueStatement();
}
// If branches outside the encapsulating loop
if (node.Parent is Loop && targetNode == node.Parent.NextNode) {
return new Ast.BreakStatement();
}
return new Ast.GotoStatement(targetNode.Label);
}
static object MakeCodeDomExpression(MethodDefinition methodDef, ByteCode byteCode, params Ast.Expression[] args)
{
OpCode opCode = byteCode.OpCode;
@ -213,7 +198,7 @@ namespace Decompiler @@ -213,7 +198,7 @@ namespace Decompiler
Ast.Statement branchCommand = null;
if (operand is ByteCode) {
branchCommand = MakeBranchCommand(byteCode.Expression.BasicBlock, ((ByteCode)operand).Expression.BasicBlock);
branchCommand = Ast.MyGotoStatement.Create(byteCode.Expression.BasicBlock, ((ByteCode)operand).Expression.BasicBlock);
}
switch(opCode.Code) {

32
src/ControlFlow/Node-Structure.cs

@ -9,6 +9,7 @@ namespace Decompiler.ControlFlow @@ -9,6 +9,7 @@ namespace Decompiler.ControlFlow
public static int NextNodeID = 1;
int id;
NodeLabel label;
Node parent;
NodeCollection childs = new NodeCollection();
@ -21,6 +22,10 @@ namespace Decompiler.ControlFlow @@ -21,6 +22,10 @@ namespace Decompiler.ControlFlow
get { return id; }
}
public NodeLabel Label {
get { return label; }
}
public Node Parent {
get { return parent; }
}
@ -137,12 +142,6 @@ namespace Decompiler.ControlFlow @@ -137,12 +142,6 @@ namespace Decompiler.ControlFlow
}
}
public string Label {
get {
return this.GetType().Name + "_" + ID;
}
}
public string Description {
get {
return ToString();
@ -152,6 +151,7 @@ namespace Decompiler.ControlFlow @@ -152,6 +151,7 @@ namespace Decompiler.ControlFlow
protected Node()
{
this.id = NextNodeID++;
this.label = new NodeLabel(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,4 +230,24 @@ namespace Decompiler.ControlFlow @@ -230,4 +230,24 @@ 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

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
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

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
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;
}
}
}

19
src/Transforms/Ast/RemoveDeadLabels.cs

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
using System;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast
{
public class RemoveDeadLabels: AbstractAstTransformer
{
public override object VisitLabelStatement(LabelStatement labelStatement, object data)
{
MyLabelStatement myLabel = (MyLabelStatement)labelStatement;
if (myLabel.NodeLabel.ReferenceCount == 0) {
RemoveCurrentNode();
}
return null;
}
}
}
Loading…
Cancel
Save