diff --git a/Decompiler.csproj b/Decompiler.csproj
index dec6cf25a..bba26f581 100644
--- a/Decompiler.csproj
+++ b/Decompiler.csproj
@@ -49,6 +49,7 @@
+
diff --git a/src/AstBuilder.cs b/src/AstBuilder.cs
index d6027e55d..a1da9ac62 100644
--- a/src/AstBuilder.cs
+++ b/src/AstBuilder.cs
@@ -32,7 +32,7 @@ namespace Decompiler
code = code.Replace(":\r\n\t", ": ");
code = code.Replace(": }", ":\r\n\t}");
code = code.Replace("\t", " ");
- code = code.Replace("\"/*", "//");
+ code = code.Replace("\"/*", "");
code = code.Replace("*/\";", "");
// Post processing commands
diff --git a/src/AstMetodBodyBuilder.cs b/src/AstMetodBodyBuilder.cs
index d46ff2278..61a488cac 100644
--- a/src/AstMetodBodyBuilder.cs
+++ b/src/AstMetodBodyBuilder.cs
@@ -36,6 +36,7 @@ namespace Decompiler
exprCollection.Optimize();
MethodBodyGraph bodyGraph = new MethodBodyGraph(exprCollection);
+ bodyGraph.Optimize();
foreach(VariableDefinition varDef in methodDef.Body.Variables) {
localVarTypes[varDef.Name] = varDef.VariableType;
@@ -63,10 +64,10 @@ namespace Decompiler
IEnumerable TransformNode(Node node)
{
- yield return MakeComment(node.ToString());
+ yield return MakeComment("// " + node.ToString());
if (node is BasicBlock) {
- yield return new Ast.LabelStatement(string.Format("BasicBlock_{0}", ((BasicBlock)node).Id));
+ yield return new Ast.LabelStatement(((BasicBlock)node).Label);
foreach(StackExpression expr in ((BasicBlock)node).Body) {
yield return TransformExpression(expr);
}
@@ -86,6 +87,8 @@ namespace Decompiler
} else {
throw new Exception("Bad node type");
}
+
+ yield return MakeComment("");
}
Ast.Statement TransformExpression(StackExpression expr)
@@ -119,7 +122,7 @@ namespace Decompiler
static Ast.ExpressionStatement MakeComment(string text)
{
- text = "/* " + text + "*/";
+ text = "/*" + text + "*/";
return new Ast.ExpressionStatement(new PrimitiveExpression(text, text));
}
@@ -146,7 +149,7 @@ namespace Decompiler
object operand = byteCode.Operand;
Ast.TypeReference operandAsTypeRef = operand is Cecil.TypeReference ? new Ast.TypeReference(((Cecil.TypeReference)operand).FullName) : null;
ByteCode operandAsByteCode = operand as ByteCode;
- string operandAsByteCodeLabel = operand is ByteCode ? String.Format("IL_{0:X2}", ((ByteCode)operand).Offset) : null;
+ string operandAsByteCodeLabel = operand is ByteCode ? ((ByteCode)operand).Expression.BasicBlock.Label : null;
Ast.Expression arg1 = args.Length >= 1 ? args[0] : null;
Ast.Expression arg2 = args.Length >= 2 ? args[1] : null;
Ast.Expression arg3 = args.Length >= 3 ? args[2] : null;
diff --git a/src/ByteCode.cs b/src/ByteCode.cs
index c73e7908a..77ac28e89 100644
--- a/src/ByteCode.cs
+++ b/src/ByteCode.cs
@@ -9,7 +9,7 @@ namespace Decompiler
{
public partial class ByteCode
{
- StackExpression owner;
+ StackExpression expression;
ByteCode previous;
ByteCode next;
@@ -18,9 +18,9 @@ namespace Decompiler
OpCode opCode;
object operand;
- public StackExpression Owner {
- get { return owner; }
- set { owner = value; }
+ public StackExpression Expression {
+ get { return expression; }
+ set { expression = value; }
}
public ByteCode Previous {
diff --git a/src/ControlFlow/Node.cs b/src/ControlFlow/Node.cs
index d7e2dbe1d..61a24c54e 100644
--- a/src/ControlFlow/Node.cs
+++ b/src/ControlFlow/Node.cs
@@ -23,12 +23,19 @@ namespace Decompiler.ControlFlow
public abstract class Node
{
+ public static int NextNodeID = 1;
+
+ int id;
Node parent;
Node headChild;
Set childs = new Set();
Set predecessors = new Set();
Set successors = new Set();
+ public int ID {
+ get { return id; }
+ }
+
public Node Parent {
get { return parent; }
}
@@ -53,6 +60,7 @@ namespace Decompiler.ControlFlow
public Node(Node parent)
{
this.parent = parent;
+ this.id = NextNodeID++;
}
public void Optimize()
@@ -60,6 +68,7 @@ namespace Decompiler.ControlFlow
for(int i = 0; i < this.Childs.Count;) {
Node child = childs[i];
if (child.Predecessors.Count == 1) {
+ if (Options.ReduceGraph-- <= 0) return;
MergeChilds(child.Predecessors[0], child);
i = 0; // Restart
} else {
@@ -146,5 +155,49 @@ namespace Decompiler.ControlFlow
node.Predecessors.Clear();
node.Successors.Clear();
}
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+ sb.Append(this.GetType().Name);
+ sb.Append(" ");
+ sb.Append(ID);
+ sb.Append(" ");
+
+ if (this.Predecessors.Count > 0 || this.Successors.Count > 0) {
+ sb.Append("(");
+ if (this.Predecessors.Count > 0) {
+ sb.Append("Predecessors:");
+ bool isFirst = true;
+ foreach(Node predecessor in this.Predecessors) {
+ if (isFirst) {
+ isFirst = false;
+ } else {
+ sb.Append(",");
+ }
+ sb.Append(predecessor.ID);
+ }
+ }
+
+ if (this.Predecessors.Count > 0 && this.Successors.Count > 0) {
+ sb.Append(" ");
+ }
+
+ if (this.Successors.Count > 0) {
+ sb.Append("Successors:");
+ bool isFirst = true;
+ foreach(Node successor in this.Successors) {
+ if (isFirst) {
+ isFirst = false;
+ } else {
+ sb.Append(",");
+ }
+ sb.Append(successor.ID);
+ }
+ }
+ sb.Append(")");
+ }
+ return sb.ToString();
+ }
}
}
diff --git a/src/ControlFlow/Nodes.cs b/src/ControlFlow/Nodes.cs
index f4445d042..c72c92031 100644
--- a/src/ControlFlow/Nodes.cs
+++ b/src/ControlFlow/Nodes.cs
@@ -11,14 +11,13 @@ namespace Decompiler.ControlFlow
if (exprs.Count == 0) throw new ArgumentException("Count == 0", "exprs");
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++);
+ basicBlock = new BasicBlock(this);
this.Childs.Add(basicBlock);
}
basicBlock.Body.Add(exprs[i]);
@@ -54,11 +53,6 @@ namespace Decompiler.ControlFlow
public AcyclicGraph(Node parent): base(parent){
}
-
- public override string ToString()
- {
- return "AcyclicGraph";
- }
}
public class Loop: Node
@@ -66,34 +60,24 @@ namespace Decompiler.ControlFlow
public Loop(Node parent): base(parent){
}
-
- public override string ToString()
- {
- return "Loop";
- }
}
public class BasicBlock: Node
{
- int id;
List body = new List();
- public int Id {
- get { return id; }
+ public string Label {
+ get {
+ return "BasicBlock_" + ID;
+ }
}
public List Body {
get { return body; }
}
- public BasicBlock(Node parent, int id): base(parent)
- {
- this.id = id;
- }
-
- public override string ToString()
+ public BasicBlock(Node parent): base(parent)
{
- return string.Format("BasicBlock {0}", id, body.Count);
}
}
}
diff --git a/src/MainForm.Designer.cs b/src/MainForm.Designer.cs
index 70fe75762..9fd25b039 100644
--- a/src/MainForm.Designer.cs
+++ b/src/MainForm.Designer.cs
@@ -32,34 +32,119 @@ namespace Decompiler
///
private void InitializeComponent()
{
- this.sourceCode = new System.Windows.Forms.TextBox();
+ this.collapseCount = new System.Windows.Forms.NumericUpDown();
+ this.reduceCount = new System.Windows.Forms.NumericUpDown();
+ this.collapseBtn = new System.Windows.Forms.Button();
+ this.reduceBtn = new System.Windows.Forms.Button();
+ this.decompileBtn = new System.Windows.Forms.Button();
+ this.sourceCodeBox = new System.Windows.Forms.RichTextBox();
+ ((System.ComponentModel.ISupportInitialize)(this.collapseCount)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.reduceCount)).BeginInit();
this.SuspendLayout();
//
- // sourceCode
+ // collapseCount
//
- this.sourceCode.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ this.collapseCount.Location = new System.Drawing.Point(12, 12);
+ this.collapseCount.Maximum = new decimal(new int[] {
+ 100000,
+ 0,
+ 0,
+ 0});
+ this.collapseCount.Name = "collapseCount";
+ this.collapseCount.Size = new System.Drawing.Size(120, 26);
+ this.collapseCount.TabIndex = 1;
+ this.collapseCount.Value = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ 0});
+ this.collapseCount.ValueChanged += new System.EventHandler(this.CollapseCountValueChanged);
+ //
+ // reduceCount
+ //
+ this.reduceCount.Location = new System.Drawing.Point(308, 12);
+ this.reduceCount.Maximum = new decimal(new int[] {
+ 100000,
+ 0,
+ 0,
+ 0});
+ this.reduceCount.Name = "reduceCount";
+ this.reduceCount.Size = new System.Drawing.Size(120, 26);
+ this.reduceCount.TabIndex = 2;
+ this.reduceCount.Value = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ 0});
+ this.reduceCount.ValueChanged += new System.EventHandler(this.ReduceCountValueChanged);
+ //
+ // collapseBtn
+ //
+ this.collapseBtn.Location = new System.Drawing.Point(138, 12);
+ this.collapseBtn.Name = "collapseBtn";
+ this.collapseBtn.Size = new System.Drawing.Size(164, 26);
+ this.collapseBtn.TabIndex = 3;
+ this.collapseBtn.Text = "Collapse expression";
+ this.collapseBtn.UseVisualStyleBackColor = true;
+ this.collapseBtn.Click += new System.EventHandler(this.CollapseBtnClick);
+ //
+ // reduceBtn
+ //
+ this.reduceBtn.Location = new System.Drawing.Point(434, 12);
+ this.reduceBtn.Name = "reduceBtn";
+ this.reduceBtn.Size = new System.Drawing.Size(143, 26);
+ this.reduceBtn.TabIndex = 4;
+ this.reduceBtn.Text = "Reduce graph";
+ this.reduceBtn.UseVisualStyleBackColor = true;
+ this.reduceBtn.Click += new System.EventHandler(this.ReduceBtnClick);
+ //
+ // decompileBtn
+ //
+ this.decompileBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.decompileBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.decompileBtn.Location = new System.Drawing.Point(639, 12);
+ this.decompileBtn.Name = "decompileBtn";
+ this.decompileBtn.Size = new System.Drawing.Size(109, 26);
+ this.decompileBtn.TabIndex = 5;
+ this.decompileBtn.Text = "Decompile";
+ this.decompileBtn.UseVisualStyleBackColor = true;
+ this.decompileBtn.Click += new System.EventHandler(this.DecompileBtnClick);
+ //
+ // sourceCodeBox
+ //
+ this.sourceCodeBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
- this.sourceCode.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.sourceCode.Location = new System.Drawing.Point(12, 12);
- this.sourceCode.Multiline = true;
- this.sourceCode.Name = "sourceCode";
- this.sourceCode.ScrollBars = System.Windows.Forms.ScrollBars.Both;
- this.sourceCode.Size = new System.Drawing.Size(736, 665);
- this.sourceCode.TabIndex = 0;
- this.sourceCode.WordWrap = false;
+ this.sourceCodeBox.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.sourceCodeBox.Location = new System.Drawing.Point(12, 45);
+ this.sourceCodeBox.Name = "sourceCodeBox";
+ this.sourceCodeBox.Size = new System.Drawing.Size(736, 632);
+ this.sourceCodeBox.TabIndex = 6;
+ this.sourceCodeBox.Text = "";
+ this.sourceCodeBox.WordWrap = false;
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(760, 689);
- this.Controls.Add(this.sourceCode);
+ this.Controls.Add(this.sourceCodeBox);
+ this.Controls.Add(this.decompileBtn);
+ this.Controls.Add(this.reduceBtn);
+ this.Controls.Add(this.collapseBtn);
+ this.Controls.Add(this.reduceCount);
+ this.Controls.Add(this.collapseCount);
this.Name = "MainForm";
this.Text = "Decompiler";
+ ((System.ComponentModel.ISupportInitialize)(this.collapseCount)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.reduceCount)).EndInit();
this.ResumeLayout(false);
- this.PerformLayout();
}
- private System.Windows.Forms.TextBox sourceCode;
+ private System.Windows.Forms.RichTextBox sourceCodeBox;
+ private System.Windows.Forms.Button decompileBtn;
+ private System.Windows.Forms.Button reduceBtn;
+ private System.Windows.Forms.Button collapseBtn;
+ private System.Windows.Forms.NumericUpDown reduceCount;
+ private System.Windows.Forms.NumericUpDown collapseCount;
}
}
diff --git a/src/MainForm.cs b/src/MainForm.cs
index 18ade0766..36de821f9 100644
--- a/src/MainForm.cs
+++ b/src/MainForm.cs
@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
+using Mono.Cecil;
+
namespace Decompiler
{
///
@@ -10,18 +12,60 @@ namespace Decompiler
///
public partial class MainForm : Form
{
- public MainForm()
+ string filename;
+
+ public MainForm(string filename)
{
+ this.filename = filename;
InitializeComponent();
}
public string SourceCode {
get {
- return sourceCode.Text;
+ return sourceCodeBox.Text;
}
set {
- sourceCode.Text = value;
+ sourceCodeBox.Text = value;
}
}
+
+ public void Decompile()
+ {
+ ControlFlow.Node.NextNodeID = 0;
+ Options.CollapseExpression = (int)collapseCount.Value;
+ Options.ReduceGraph = (int)reduceCount.Value;
+
+ AssemblyDefinition assembly = AssemblyFactory.GetAssembly(filename);
+ AstBuilder codeDomBuilder = new AstBuilder();
+ codeDomBuilder.AddAssembly(assembly);
+ SourceCode = codeDomBuilder.GenerateCode();
+ }
+
+ void CollapseBtnClick(object sender, EventArgs e)
+ {
+ collapseCount.Value++;
+ Decompile();
+ }
+
+ void ReduceBtnClick(object sender, EventArgs e)
+ {
+ reduceCount.Value++;
+ Decompile();
+ }
+
+ void DecompileBtnClick(object sender, EventArgs e)
+ {
+ Decompile();
+ }
+
+ void CollapseCountValueChanged(object sender, EventArgs e)
+ {
+ Decompile();
+ }
+
+ void ReduceCountValueChanged(object sender, EventArgs e)
+ {
+ Decompile();
+ }
}
}
diff --git a/src/Options.cs b/src/Options.cs
new file mode 100644
index 000000000..fd56768f7
--- /dev/null
+++ b/src/Options.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Decompiler
+{
+ public static class Options
+ {
+ public static int CollapseExpression = 0;
+ public static int ReduceGraph = 0;
+ }
+}
diff --git a/src/Program.cs b/src/Program.cs
index 1af494614..daa064739 100644
--- a/src/Program.cs
+++ b/src/Program.cs
@@ -21,21 +21,13 @@ namespace Decompiler
[STAThread]
private static void Main(string[] args)
{
- string sourceCode = Decompile(@"..\..\tests\QuickSort\bin\Release\QuickSort.exe");
+ string sourceFilename = @"..\..\tests\QuickSort\bin\Release\QuickSort.exe";
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
- MainForm mainForm = new MainForm();
- mainForm.SourceCode = sourceCode;
+ MainForm mainForm = new MainForm(sourceFilename);
+ mainForm.Decompile();
Application.Run(mainForm);
}
-
- static string Decompile(string filename)
- {
- AssemblyDefinition assembly = AssemblyFactory.GetAssembly(filename);
- AstBuilder codeDomBuilder = new AstBuilder();
- codeDomBuilder.AddAssembly(assembly);
- return codeDomBuilder.GenerateCode();
- }
}
}
diff --git a/src/StackExpression.cs b/src/StackExpression.cs
index bbecfeaf8..2e11a4d86 100644
--- a/src/StackExpression.cs
+++ b/src/StackExpression.cs
@@ -63,7 +63,7 @@ namespace Decompiler
get {
List branchesHere = new List();
foreach(ByteCode byteCode in this.FirstByteCode.BranchesHere) {
- branchesHere.Add(byteCode.Owner);
+ branchesHere.Add(byteCode.Expression);
}
return branchesHere;
}
@@ -74,7 +74,7 @@ namespace Decompiler
if (this.lastByteCode.BranchTarget == null) {
return null;
} else {
- return this.lastByteCode.BranchTarget.Owner;
+ return this.lastByteCode.BranchTarget.Expression;
}
}
}
@@ -135,7 +135,7 @@ namespace Decompiler
{
this.owner = owner;
this.lastByteCode = lastByteCode;
- this.lastByteCode.Owner = this;
+ this.lastByteCode.Expression = this;
}
public bool MustBeParenthesized {
diff --git a/src/StackExpressionCollection.cs b/src/StackExpressionCollection.cs
index 434c12bb5..829f0835f 100644
--- a/src/StackExpressionCollection.cs
+++ b/src/StackExpressionCollection.cs
@@ -27,6 +27,7 @@ namespace Decompiler
!expr.IsBranchTarget &&
prevExpr.IsClosed)
{
+ if (Options.CollapseExpression-- <= 0) return;
this.RemoveAt(i - 1); i--;
expr.LastArguments.Insert(0, prevExpr);
i--;