Browse Source

Generate the initial graph.

Output the graph as nested blocks.
pull/1/head^2
David Srbecký 18 years ago
parent
commit
693bb16488
  1. 76
      src/AstMetodBodyBuilder.cs
  2. 22
      src/ControlFlow/Node.cs
  3. 31
      src/ControlFlow/Nodes.cs
  4. 11
      src/StackExpression.cs

76
src/AstMetodBodyBuilder.cs

@ -8,14 +8,24 @@ using Cecil = Mono.Cecil;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using Decompiler.ControlFlow;
namespace Decompiler namespace Decompiler
{ {
public class AstMetodBodyBuilder public class AstMetodBodyBuilder
{ {
MethodDefinition methodDef;
static Dictionary<string, Cecil.TypeReference> localVarTypes = new Dictionary<string, Cecil.TypeReference>(); static Dictionary<string, Cecil.TypeReference> localVarTypes = new Dictionary<string, Cecil.TypeReference>();
static Dictionary<string, bool> localVarDefined = new Dictionary<string, bool>(); static Dictionary<string, bool> localVarDefined = new Dictionary<string, bool>();
public static BlockStatement CreateMetodBody(MethodDefinition methodDef) public static BlockStatement CreateMetodBody(MethodDefinition methodDef)
{
AstMetodBodyBuilder builder = new AstMetodBodyBuilder();
builder.methodDef = methodDef;
return builder.CreateMetodBody();
}
public BlockStatement CreateMetodBody()
{ {
Ast.BlockStatement astBlock = new Ast.BlockStatement(); Ast.BlockStatement astBlock = new Ast.BlockStatement();
@ -25,7 +35,7 @@ namespace Decompiler
StackExpressionCollection exprCollection = new StackExpressionCollection(body); StackExpressionCollection exprCollection = new StackExpressionCollection(body);
exprCollection.Optimize(); exprCollection.Optimize();
ControlFlow.MethodBodyGraph bodyGraph = new ControlFlow.MethodBodyGraph(exprCollection); MethodBodyGraph bodyGraph = new MethodBodyGraph(exprCollection);
foreach(VariableDefinition varDef in methodDef.Body.Variables) { foreach(VariableDefinition varDef in methodDef.Body.Variables) {
localVarTypes[varDef.Name] = varDef.VariableType; localVarTypes[varDef.Name] = varDef.VariableType;
@ -37,11 +47,49 @@ namespace Decompiler
// astBlock.Children.Add(astLocalVar); // astBlock.Children.Add(astLocalVar);
} }
for(int b = 0; b < bodyGraph.Childs.Count; b++) { astBlock.Children.AddRange(TransformNodes(bodyGraph.Childs));
ControlFlow.BasicBlock node = (ControlFlow.BasicBlock)bodyGraph.Childs[b];
astBlock.Children.Add(MakeComment(node.ToString())); return astBlock;
for(int i = 0; i < node.Body.Count; i++) { }
StackExpression expr = node.Body[i];
IEnumerable<Ast.INode> TransformNodes(IEnumerable<Node> nodes)
{
foreach(Node node in nodes) {
foreach(Ast.Statement stmt in TransformNode(node)) {
yield return stmt;
}
}
}
IEnumerable<Ast.INode> TransformNode(Node node)
{
yield return MakeComment(node.ToString());
if (node is BasicBlock) {
yield return new Ast.LabelStatement(string.Format("BasicBlock_{0}", ((BasicBlock)node).Id));
foreach(StackExpression expr in ((BasicBlock)node).Body) {
yield return TransformExpression(expr);
}
} else if (node is AcyclicGraph) {
Ast.BlockStatement blockStatement = new Ast.BlockStatement();
blockStatement.Children.AddRange(TransformNodes(node.Childs));
yield return blockStatement;
} else if (node is Loop) {
Ast.BlockStatement blockStatement = new Ast.BlockStatement();
blockStatement.Children.AddRange(TransformNodes(node.Childs));
yield return new Ast.DoLoopStatement(
new Ast.PrimitiveExpression(true, true.ToString()),
blockStatement,
ConditionType.While,
ConditionPosition.Start
);
} else {
throw new Exception("Bad node type");
}
}
Ast.Statement TransformExpression(StackExpression expr)
{
Ast.Statement astStatement = null; Ast.Statement astStatement = null;
try { try {
List<Ast.Expression> args = new List<Ast.Expression>(); List<Ast.Expression> args = new List<Ast.Expression>();
@ -66,21 +114,7 @@ namespace Decompiler
} catch (NotImplementedException) { } catch (NotImplementedException) {
astStatement = MakeComment(expr.LastByteCode.Description); astStatement = MakeComment(expr.LastByteCode.Description);
} }
if (expr.IsBranchTarget) { return astStatement;
astBlock.Children.Add(new Ast.LabelStatement(string.Format("IL_{0:X2}", expr.FirstByteCode.Offset)));
}
// Skip last return statement
// if (i == exprCol.Count - 1 &&
// expr.LastByteCode.OpCode.Code == Code.Ret &&
// expr.LastByteCode.PopCount == 0 &&
// !expr.IsBranchTarget) {
// continue;
// }
astBlock.Children.Add(astStatement);
}
}
return astBlock;
} }
static Ast.ExpressionStatement MakeComment(string text) static Ast.ExpressionStatement MakeComment(string text)

22
src/ControlFlow/Node.cs

@ -57,18 +57,15 @@ namespace Decompiler.ControlFlow
public void Optimize() public void Optimize()
{ {
bool optimized; for(int i = 0; i < this.Childs.Count;) {
do { Node child = childs[i];
optimized = false;
foreach(Node child in this.Childs) {
if (child.Predecessors.Count == 1) { if (child.Predecessors.Count == 1) {
Node predecessor = child.Predecessors[0]; MergeChilds(child.Predecessors[0], child);
MergeChilds(predecessor, child); i = 0; // Restart
optimized = true; } else {
break; // Collection was modified; restart i++; // Next
} }
} }
} while (optimized);
} }
static void MergeChilds(Node head, Node tail) static void MergeChilds(Node head, Node tail)
@ -124,10 +121,11 @@ namespace Decompiler.ControlFlow
Relink(head, mergedNode); Relink(head, mergedNode);
Relink(tail, mergedNode); Relink(tail, mergedNode);
// Remove the old nodes and add the merged node // Remove the old nodes and add the merged node - replace head with the merged node
container.Childs.Remove(head);
container.Childs.Remove(tail); container.Childs.Remove(tail);
container.Childs.Add(mergedNode); int headIndex = container.Childs.IndexOf(head);
container.Childs.Remove(head);
container.Childs.Insert(headIndex, mergedNode);
} }
static void Relink(Node node, Node target) static void Relink(Node node, Node target)

31
src/ControlFlow/Nodes.cs

@ -22,6 +22,27 @@ namespace Decompiler.ControlFlow
this.Childs.Add(basicBlock); this.Childs.Add(basicBlock);
} }
basicBlock.Body.Add(exprs[i]); basicBlock.Body.Add(exprs[i]);
exprs[i].BasicBlock = basicBlock;
}
// Add fall-though links
for(int i = 0; i < exprs.Count - 1; i++) {
BasicBlock node = exprs[i].BasicBlock;
BasicBlock target = exprs[i + 1].BasicBlock;
if (node != target) {
node.Successors.Add(target);
target.Predecessors.Add(node);
}
}
// Add branch links
for(int i = 0; i < exprs.Count; i++) {
if (exprs[i].BranchTarget != null) {
BasicBlock node = exprs[i].BasicBlock;
BasicBlock target = exprs[i].BranchTarget.BasicBlock;
node.Successors.Add(target);
target.Predecessors.Add(node);
}
} }
this.HeadChild = this.Childs[0]; this.HeadChild = this.Childs[0];
@ -33,6 +54,11 @@ namespace Decompiler.ControlFlow
public AcyclicGraph(Node parent): base(parent){ public AcyclicGraph(Node parent): base(parent){
} }
public override string ToString()
{
return "AcyclicGraph";
}
} }
public class Loop: Node public class Loop: Node
@ -40,6 +66,11 @@ namespace Decompiler.ControlFlow
public Loop(Node parent): base(parent){ public Loop(Node parent): base(parent){
} }
public override string ToString()
{
return "Loop";
}
} }
public class BasicBlock: Node public class BasicBlock: Node

11
src/StackExpression.cs

@ -9,10 +9,21 @@ namespace Decompiler
{ {
public class StackExpression public class StackExpression
{ {
ControlFlow.BasicBlock basicBlock;
StackExpressionCollection owner; StackExpressionCollection owner;
ByteCode lastByteCode; ByteCode lastByteCode;
List<StackExpression> lastArguments = new List<StackExpression>(); List<StackExpression> lastArguments = new List<StackExpression>();
public Decompiler.ControlFlow.BasicBlock BasicBlock {
get { return basicBlock; }
set {
basicBlock = value;
foreach (StackExpression lastArgument in lastArguments) {
lastArgument.BasicBlock = value;
}
}
}
public StackExpressionCollection Owner { public StackExpressionCollection Owner {
get { return owner; } get { return owner; }
} }

Loading…
Cancel
Save