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. 234
      src/ControlFlow.cs

4
src/AstMetodBodyBuilder.cs

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

234
src/ControlFlow.cs

@ -4,65 +4,79 @@ using System.Collections.Generic; @@ -4,65 +4,79 @@ using System.Collections.Generic;
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;
BasicBlockSet owner;
Set<BasicBlock> predecessors;
public Set<BasicBlock> successors;
BasicBlock fallThroughSuccessor;
BasicBlock branchSuccessor;
List<StackExpression> body = new List<StackExpression>();
Node parent;
Node headChild;
Set<Node> childs = new Set<Node>();
Set<Node> predecessors = new Set<Node>();
Set<Node> successors = new Set<Node>();
#region Peoperties
public Node Parent {
get { return parent; }
}
public int Id {
get { return id; }
set { id = value; }
public Node HeadChild {
get { return headChild; }
protected set { headChild = value; }
}
public BasicBlockSet Owner {
get { return owner; }
set { owner = value; }
public Set<Node> Childs {
get { return childs; }
}
public Set<BasicBlock> Predecessors {
public Set<Node> Predecessors {
get { return predecessors; }
set { predecessors = value; }
}
public Set<BasicBlock> Successors {
public Set<Node> Successors {
get { return successors; }
set { successors = value; }
}
public BasicBlock FallThroughSuccessor {
get { return fallThroughSuccessor; }
set { fallThroughSuccessor = value; }
public Node(Node parent)
{
this.parent = parent;
}
}
public class BasicBlock: Node
{
int id;
List<StackExpression> body = new List<StackExpression>();
public BasicBlock BranchSuccessor {
get { return branchSuccessor; }
set { branchSuccessor = value; }
public int Id {
get { return id; }
}
public List<StackExpression> Body {
get { return body; }
set { body = value; }
}
#endregion
public BasicBlock(Node parent, int id): base(parent)
{
this.id = id;
}
public override string ToString()
{
//return string.Format("BackBlock {0} ({1} expressions)", id, body.Count);
return string.Format("BackBlock {0}", id, body.Count);
return string.Format("BasicBlock {0}", id, body.Count);
}
}
@ -72,116 +86,140 @@ namespace Decompiler @@ -72,116 +86,140 @@ namespace Decompiler
Loop,
}
public class BasicBlockSet
// TODO: Split into two classes?
public class BasicBlockSet: Node
{
BasicBlockSet owner;
BasicBlockSetType type;
object head;
Set<object> elements = new Set<object>();
Set<BasicBlock> BasicBlockSuccessors;
BasicBlock headBasicBlock {
get {
return null;
}
}
public BasicBlockSet Owner {
get { return owner; }
}
public BasicBlockSetType Type {
get { return type; }
}
public object Head {
get { return head; }
BasicBlockSet(Node parent): base(parent)
{
}
public Set<object> Elements {
get { return elements; }
// TODO: Add links between the generated BasicBlocks
public BasicBlockSet(StackExpressionCollection exprs): base(null)
{
if (exprs.Count == 0) throw new ArgumentException("Count == 0", "exprs");
this.type = BasicBlockSetType.MethodBody;
BasicBlock basicBlock = null;
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]);
}
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 (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 tailAsSet = tail as BasicBlockSet;
// Add head
if (head is BasicBlock) {
this.head = head;
this.elements.Add(head);
mergedNode.HeadChild = head;
mergedNode.Childs.Add(head);
} else if (headAsSet != null && headAsSet.type == BasicBlockSetType.Acyclic) {
this.head = headAsSet.head;
this.elements.AddRange(headAsSet.elements);
mergedNode.HeadChild = headAsSet.HeadChild;
mergedNode.Childs.AddRange(headAsSet.Childs);
} else if (headAsSet != null && headAsSet.type == BasicBlockSetType.Loop) {
this.head = headAsSet;
this.elements.Add(headAsSet);
mergedNode.HeadChild = headAsSet;
mergedNode.Childs.Add(headAsSet);
} else {
throw new Exception("Invalid head");
}
// Add tail
if (tail is BasicBlock) {
this.elements.Add(tail);
mergedNode.Childs.Add(tail);
} 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) {
this.elements.Add(tailAsSet);
mergedNode.Childs.Add(tailAsSet);
} else {
throw new Exception("Invalid tail");
}
// Get type
if (tail is BasicBlock) {
if (((BasicBlock)tail).successors.Contains(this.headBasicBlock)) {
this.type = BasicBlockSetType.Loop;
} else {
this.type = BasicBlockSetType.Acyclic;
}
} else if (tailAsSet != null) {
if (tailAsSet.BasicBlockSuccessors.Contains(this.headBasicBlock)) {
}
} else {
throw new Exception("Invalid tail");
// Remove links between the head and tail
if (head.Successors.Contains(tail)) {
head.Successors.Remove(tail);
tail.Predecessors.Remove(head);
}
if (tail.Successors.Contains(head)) {
tail.Successors.Remove(head);
head.Predecessors.Remove(tail);
}
Relink(head, mergedNode);
Relink(tail, mergedNode);
// Remove the old nodes and add the merged node
container.Childs.Remove(head);
container.Childs.Remove(tail);
container.Childs.Add(mergedNode);
}
public BasicBlockSet(StackExpressionCollection exprs)
static void Relink(Node node, Node target)
{
if (exprs.Count == 0) throw new ArgumentException("Count == 0", "exprs");
this.owner = null;
this.type = BasicBlockSetType.MethodBody;
BasicBlock basicBlock = null;
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.elements.Add(basicBlock);
basicBlock.Id = basicBlockId++;
}
basicBlock.Body.Add(exprs[i]);
// Relink all neighbours to the target node
foreach(Node predecessor in node.Predecessors) {
predecessor.Successors.Remove(node);
predecessor.Successors.Add(target);
}
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