Browse Source

Working on graph reduction algorithm. (Graph creation and presentation is still missing)

pull/1/head^2
David Srbecký 18 years ago
parent
commit
faff1bf5a9
  1. 4
      src/AstMetodBodyBuilder.cs
  2. 226
      src/ControlFlow.cs

4
src/AstMetodBodyBuilder.cs

@ -37,8 +37,8 @@ namespace Decompiler
// astBlock.Children.Add(astLocalVar); // astBlock.Children.Add(astLocalVar);
} }
for(int b = 0; b < basicBlockSet.Elements.Count; b++) { for(int b = 0; b < basicBlockSet.Childs.Count; b++) {
BasicBlock basicBlock = (BasicBlock)basicBlockSet.Elements[b]; BasicBlock basicBlock = (BasicBlock)basicBlockSet.Childs[b];
astBlock.Children.Add(MakeComment(basicBlock.ToString())); astBlock.Children.Add(MakeComment(basicBlock.ToString()));
for(int i = 0; i < basicBlock.Body.Count; i++) { for(int i = 0; i < basicBlock.Body.Count; i++) {
StackExpression expr = basicBlock.Body[i]; StackExpression expr = basicBlock.Body[i];

226
src/ControlFlow.cs

@ -4,65 +4,79 @@ using System.Collections.Generic;
namespace Decompiler namespace Decompiler
{ {
public class Set<T>: List<T> public class Set<T>: System.Collections.ObjectModel.Collection<T>
{ {
public void AddRange(IEnumerable<T> items)
{
foreach(T item in items) {
this.Add(item);
}
} }
protected override void InsertItem(int index, T item)
{
if (!this.Contains(item)) {
base.InsertItem(index, item);
}
}
}
public class BasicBlock public abstract class Node
{ {
int id; Node parent;
BasicBlockSet owner; Node headChild;
Set<BasicBlock> predecessors; Set<Node> childs = new Set<Node>();
public Set<BasicBlock> successors; Set<Node> predecessors = new Set<Node>();
BasicBlock fallThroughSuccessor; Set<Node> successors = new Set<Node>();
BasicBlock branchSuccessor;
List<StackExpression> body = new List<StackExpression>();
#region Peoperties public Node Parent {
get { return parent; }
}
public int Id { public Node HeadChild {
get { return id; } get { return headChild; }
set { id = value; } protected set { headChild = value; }
} }
public BasicBlockSet Owner { public Set<Node> Childs {
get { return owner; } get { return childs; }
set { owner = value; }
} }
public Set<BasicBlock> Predecessors { public Set<Node> Predecessors {
get { return predecessors; } get { return predecessors; }
set { predecessors = value; }
} }
public Set<BasicBlock> Successors { public Set<Node> Successors {
get { return successors; } get { return successors; }
set { successors = value; }
} }
public BasicBlock FallThroughSuccessor { public Node(Node parent)
get { return fallThroughSuccessor; } {
set { fallThroughSuccessor = value; } this.parent = parent;
}
} }
public BasicBlock BranchSuccessor { public class BasicBlock: Node
get { return branchSuccessor; } {
set { branchSuccessor = value; } int id;
List<StackExpression> body = new List<StackExpression>();
public int Id {
get { return id; }
} }
public List<StackExpression> Body { public List<StackExpression> Body {
get { return body; } get { return body; }
set { body = value; }
} }
#endregion public BasicBlock(Node parent, int id): base(parent)
{
this.id = id;
}
public override string ToString() public override string ToString()
{ {
//return string.Format("BackBlock {0} ({1} expressions)", id, body.Count); return string.Format("BasicBlock {0}", id, body.Count);
return string.Format("BackBlock {0}", id, body.Count);
} }
} }
@ -72,116 +86,140 @@ namespace Decompiler
Loop, Loop,
} }
public class BasicBlockSet // TODO: Split into two classes?
public class BasicBlockSet: Node
{ {
BasicBlockSet owner;
BasicBlockSetType type; BasicBlockSetType type;
object head; public BasicBlockSetType Type {
Set<object> elements = new Set<object>(); get { return type; }
}
Set<BasicBlock> BasicBlockSuccessors; BasicBlockSet(Node parent): base(parent)
{
BasicBlock headBasicBlock {
get {
return null;
}
} }
public BasicBlockSet Owner { // TODO: Add links between the generated BasicBlocks
get { return owner; } public BasicBlockSet(StackExpressionCollection exprs): base(null)
} {
if (exprs.Count == 0) throw new ArgumentException("Count == 0", "exprs");
public BasicBlockSetType Type { this.type = BasicBlockSetType.MethodBody;
get { return type; }
}
public object Head { BasicBlock basicBlock = null;
get { return head; } int basicBlockId = 1;
for(int i = 0; i < exprs.Count; i++) {
// Start new basic block if
// - this is first expression
// - last expression was branch
// - this expression is branch target
if (i == 0 || exprs[i - 1].BranchTarget != null || exprs[i].BranchesHere.Count > 0){
basicBlock = new BasicBlock(this, basicBlockId++);
this.Childs.Add(basicBlock);
} }
basicBlock.Body.Add(exprs[i]);
public Set<object> Elements {
get { return elements; }
} }
this.HeadChild = this.Childs[0];
}
BasicBlockSet() public void Optimize()
{ {
bool optimized;
do {
optimized = false;
foreach(Node child in this.Childs) {
if (child.Predecessors.Count == 1) {
Node predecessor = child.Predecessors[0];
MergeNodes(predecessor, child);
optimized = true;
break; // Collection was modified; restart
}
}
} while (optimized);
} }
public BasicBlockSet(object head, object tail) static void MergeNodes(Node head, Node tail)
{ {
if (head == null) throw new ArgumentNullException("head"); if (head == null) throw new ArgumentNullException("head");
if (tail == null) throw new ArgumentNullException("tail"); if (tail == null) throw new ArgumentNullException("tail");
if (head.Parent != tail.Parent) throw new ArgumentException("different parents");
Node container = head.Parent;
BasicBlockSet mergedNode = new BasicBlockSet(container);
// Get type
if (tail.Successors.Contains(head)) {
mergedNode.type = BasicBlockSetType.Loop;
} else {
mergedNode.type = BasicBlockSetType.Acyclic;
}
BasicBlockSet headAsSet = head as BasicBlockSet; BasicBlockSet headAsSet = head as BasicBlockSet;
BasicBlockSet tailAsSet = tail as BasicBlockSet; BasicBlockSet tailAsSet = tail as BasicBlockSet;
// Add head // Add head
if (head is BasicBlock) { if (head is BasicBlock) {
this.head = head; mergedNode.HeadChild = head;
this.elements.Add(head); mergedNode.Childs.Add(head);
} else if (headAsSet != null && headAsSet.type == BasicBlockSetType.Acyclic) { } else if (headAsSet != null && headAsSet.type == BasicBlockSetType.Acyclic) {
this.head = headAsSet.head; mergedNode.HeadChild = headAsSet.HeadChild;
this.elements.AddRange(headAsSet.elements); mergedNode.Childs.AddRange(headAsSet.Childs);
} else if (headAsSet != null && headAsSet.type == BasicBlockSetType.Loop) { } else if (headAsSet != null && headAsSet.type == BasicBlockSetType.Loop) {
this.head = headAsSet; mergedNode.HeadChild = headAsSet;
this.elements.Add(headAsSet); mergedNode.Childs.Add(headAsSet);
} else { } else {
throw new Exception("Invalid head"); throw new Exception("Invalid head");
} }
// Add tail // Add tail
if (tail is BasicBlock) { if (tail is BasicBlock) {
this.elements.Add(tail); mergedNode.Childs.Add(tail);
} else if (tailAsSet != null && tailAsSet.type == BasicBlockSetType.Acyclic) { } else if (tailAsSet != null && tailAsSet.type == BasicBlockSetType.Acyclic) {
this.elements.AddRange(tailAsSet.elements); mergedNode.Childs.AddRange(tailAsSet.Childs);
} else if (tailAsSet != null && tailAsSet.type == BasicBlockSetType.Loop) { } else if (tailAsSet != null && tailAsSet.type == BasicBlockSetType.Loop) {
this.elements.Add(tailAsSet); mergedNode.Childs.Add(tailAsSet);
} else { } else {
throw new Exception("Invalid tail"); throw new Exception("Invalid tail");
} }
// Get type // Remove links between the head and tail
if (tail is BasicBlock) { if (head.Successors.Contains(tail)) {
if (((BasicBlock)tail).successors.Contains(this.headBasicBlock)) { head.Successors.Remove(tail);
this.type = BasicBlockSetType.Loop; tail.Predecessors.Remove(head);
} else {
this.type = BasicBlockSetType.Acyclic;
}
} else if (tailAsSet != null) {
if (tailAsSet.BasicBlockSuccessors.Contains(this.headBasicBlock)) {
}
} else {
throw new Exception("Invalid tail");
} }
if (tail.Successors.Contains(head)) {
tail.Successors.Remove(head);
head.Predecessors.Remove(tail);
} }
public BasicBlockSet(StackExpressionCollection exprs) Relink(head, mergedNode);
{ Relink(tail, mergedNode);
if (exprs.Count == 0) throw new ArgumentException("Count == 0", "exprs");
this.owner = null; // Remove the old nodes and add the merged node
this.type = BasicBlockSetType.MethodBody; container.Childs.Remove(head);
container.Childs.Remove(tail);
container.Childs.Add(mergedNode);
}
BasicBlock basicBlock = null; static void Relink(Node node, Node target)
int basicBlockId = 1; {
for(int i = 0; i < exprs.Count; i++) { // Relink all neighbours to the target node
// Start new basic block if foreach(Node predecessor in node.Predecessors) {
// - this is first expression predecessor.Successors.Remove(node);
// - last expression was branch predecessor.Successors.Add(target);
// - this expression is branch target
if (i == 0 || exprs[i - 1].BranchTarget != null || exprs[i].BranchesHere.Count > 0){
basicBlock = new BasicBlock();
this.elements.Add(basicBlock);
basicBlock.Id = basicBlockId++;
} }
basicBlock.Body.Add(exprs[i]); foreach(Node successor in node.Successors) {
successor.Predecessors.Remove(node);
successor.Predecessors.Add(target);
} }
this.head = this.elements[0]; // Move our pointers to the target node
target.Predecessors.AddRange(node.Predecessors);
target.Successors.AddRange(node.Successors);
node.Predecessors.Clear();
node.Successors.Clear();
} }
} }
} }

Loading…
Cancel
Save