@ -87,12 +87,12 @@ namespace Decompiler
@@ -87,12 +87,12 @@ namespace Decompiler
if ( node is BasicBlock ) {
foreach ( StackExpression expr in ( ( BasicBlock ) node ) . Body ) {
yield return TransformExpression ( expr ) ;
yield return TransformExpressionToStatement ( expr ) ;
}
Node fallThroughNode = ( ( BasicBlock ) node ) . FallThroughBasicBlock ;
// If there is default branch and it is not the following node
if ( fallThroughNode ! = null ) {
yield return MakeBranchCommand ( node , fallThroughNode ) ;
yield return new Ast . GotoStatement ( fallThroughNode . Label ) ;
}
} else if ( node is AcyclicGraph ) {
Ast . BlockStatement blockStatement = new Ast . BlockStatement ( ) ;
@ -111,38 +111,55 @@ namespace Decompiler
@@ -111,38 +111,55 @@ namespace Decompiler
foreach ( Ast . INode inode in TransformNodes ( node . Childs ) ) {
yield return inode ;
}
} else if ( node is Branch ) {
yield return new Ast . LabelStatement ( ( ( Branch ) node ) . FirstBasicBlock . Label ) ;
Ast . BlockStatement trueBlock = new Ast . BlockStatement ( ) ;
trueBlock . Children . Add ( new Ast . GotoStatement ( ( ( Branch ) node ) . TrueSuccessor . Label ) ) ;
Ast . BlockStatement falseBlock = new Ast . BlockStatement ( ) ;
falseBlock . Children . Add ( new Ast . GotoStatement ( ( ( Branch ) node ) . FalseSuccessor . Label ) ) ;
Ast . IfElseStatement ifElseStmt = new Ast . IfElseStatement (
MakeBranchCondition ( ( Branch ) node ) ,
trueBlock ,
falseBlock
) ;
trueBlock . Parent = ifElseStmt ;
falseBlock . Parent = ifElseStmt ;
yield return ifElseStmt ;
} else if ( node is ConditionalNode ) {
ConditionalNode conditionalNode = ( ConditionalNode ) node ;
yield return new Ast . LabelStatement ( conditionalNode . Condition . Label ) ;
Ast . Statement lastStatement = null ;
foreach ( StackExpression expr in conditionalNode . Condition . Body ) {
lastStatement = TransformExpression ( expr ) ;
yield return lastStatement ;
}
Ast . IfElseStatement ifElseStmt = lastStatement as Ast . IfElseStatement ;
if ( ifElseStmt = = null ) {
ifElseStmt = new IfElseStatement ( Ast . Expression . Null , Ast . Statement . Null , Ast . Statement . Null ) ;
}
Ast . Statement oldTrueBody = ifElseStmt . TrueStatement [ 0 ] ;
ifElseStmt . TrueStatement . Clear ( ) ;
// Swap the method bodies
ifElseStmt . Condition = new Ast . UnaryOperatorExpression ( new Ast . ParenthesizedExpression ( ifElseStmt . Condition ) , UnaryOperatorType . Not ) ;
yield return new Ast . LabelStatement ( conditionalNode . Condition . FirstBasicBlock . Label ) ;
Ast . BlockStatement trueBlock = new Ast . BlockStatement ( ) ;
// The block entry code
trueBlock . Children . Add ( MakeBranchCommand ( node , conditionalNode . Condition . FallThroughBasicBlock ) ) ;
trueBlock . Children . Add ( new Ast . GotoStatement ( conditionalNode . Condition . TrueSuccessor . Label ) ) ;
// Sugested content
trueBlock . Children . AddRange ( TransformNode ( conditionalNode . TrueBody ) ) ;
ifElseStmt . TrueStatement . Add ( trueBlock ) ;
trueBlock . Parent = ifElseStmt ;
Ast . BlockStatement falseBlock = new Ast . BlockStatement ( ) ;
// The block entry code
falseBlock . Children . Add ( oldTrueBody ) ;
falseBlock . Children . Add ( new Ast . GotoStatement ( conditionalNode . Condition . FalseSuccessor . Label ) ) ;
// Sugested content
falseBlock . Children . AddRange ( TransformNode ( conditionalNode . FalseBody ) ) ;
ifElseStmt . FalseStatement . Add ( falseBlock ) ;
Ast . IfElseStatement ifElseStmt = new Ast . IfElseStatement (
// Method bodies are swapped
new Ast . UnaryOperatorExpression (
new Ast . ParenthesizedExpression (
MakeBranchCondition ( conditionalNode . Condition )
) ,
UnaryOperatorType . Not
) ,
falseBlock ,
trueBlock
) ;
trueBlock . Parent = ifElseStmt ;
falseBlock . Parent = ifElseStmt ;
yield return ifElseStmt ;
} else {
throw new Exception ( "Bad node type" ) ;
}
@ -152,29 +169,57 @@ namespace Decompiler
@@ -152,29 +169,57 @@ namespace Decompiler
}
}
Ast . Statement TransformExpression ( StackExpression expr )
List < Ast . Expression > TransformExpressionArguments ( StackExpression expr )
{
Ast . Statement astStatement = null ;
List < Ast . Expression > args = new List < Ast . Expression > ( ) ;
foreach ( CilStackSlot stackSlot in expr . StackBefore . PeekCount ( expr . PopCount ) ) {
string name = string . Format ( "expr{0:X2}" , stackSlot . AllocadedBy . Offset ) ;
args . Add ( new Ast . IdentifierExpression ( name ) ) ;
}
object codeExpr = MakeCodeDomExpression ( methodDef , expr , args . ToArray ( ) ) ;
// Args generated by nested expressions (which must be closed)
foreach ( StackExpression nestedExpr in expr . LastArguments ) {
Ast . Expression astExpr = ( Ast . Expression ) TransformExpression ( nestedExpr ) ;
if ( nestedExpr . MustBeParenthesized ) {
args . Add ( new Ast . ParenthesizedExpression ( astExpr ) ) ;
} else {
args . Add ( astExpr ) ;
}
}
return args ;
}
object TransformExpression ( StackExpression expr )
{
List < Ast . Expression > args = TransformExpressionArguments ( expr ) ;
try {
return TransformByteCode ( methodDef , expr . LastByteCode , args . ToArray ( ) ) ;
} catch ( NotImplementedException ) {
// Output the operand of the unknown IL code as well
if ( expr . LastByteCode . Operand ! = null ) {
args . Insert ( 0 , new IdentifierExpression ( expr . LastByteCode . FormatedOperand ) ) ;
}
return new Ast . InvocationExpression ( new IdentifierExpression ( "IL__" + expr . LastByteCode . OpCode . Name ) , args ) ;
}
}
Ast . Statement TransformExpressionToStatement ( StackExpression expr )
{
object codeExpr = TransformExpression ( expr ) ;
if ( codeExpr is Ast . Expression ) {
if ( expr . PushCount = = 1 ) {
string type = expr . LastByteCode . Type . FullName ;
string name = string . Format ( "expr{0:X2}" , expr . LastByteCode . Offset ) ;
Ast . LocalVariableDeclaration astLocal = new Ast . LocalVariableDeclaration ( new Ast . TypeReference ( type . ToString ( ) ) ) ;
astLocal . Variables . Add ( new Ast . VariableDeclaration ( name , ( Ast . Expression ) codeExpr ) ) ;
astStatement = astLocal ;
return astLocal ;
} else {
astStatement = new ExpressionStatement ( ( Ast . Expression ) codeExpr ) ;
return new Ast . ExpressionStatement ( ( Ast . Expression ) codeExpr ) ;
}
} else if ( codeExpr is Ast . Statement ) {
astStatement = ( Ast . Statement ) codeExpr ;
return ( Ast . Statement ) codeExpr ;
} else {
throw new Exception ( ) ;
}
return astStatement ;
}
static Ast . ExpressionStatement MakeComment ( string text )
@ -183,48 +228,72 @@ namespace Decompiler
@@ -183,48 +228,72 @@ namespace Decompiler
return new Ast . ExpressionStatement ( new PrimitiveExpression ( text , text ) ) ;
}
public static Ast . Statement MakeBranchCommand ( Node contextNode , Node targetNode )
Ast . Expression MakeBranchCondition ( Branch branch )
{
// // 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 . GotoStatement ( targetNode . Label ) ;
if ( branch is SimpleBranch ) { // TODO: Delete
return MakeBranchCondition_Internal ( branch ) ;
} else {
return new ParenthesizedExpression ( MakeBranchCondition_Internal ( branch ) ) ;
}
}
static object MakeCodeDomExpression ( MethodDefinition methodDef , StackExpression expr , params Ast . Expression [ ] args )
Ast . Expression MakeBranchCondition_Internal ( Branch branch )
{
List < Ast . Expression > allArgs = new List < Ast . Expression > ( ) ;
// Add args from stack
allArgs . AddRange ( args ) ;
// Args generated by nested expressions (which must be closed)
foreach ( StackExpression nestedExpr in expr . LastArguments ) {
Ast . Expression astExpr = ( Ast . Expression ) MakeCodeDomExpression ( methodDef , nestedExpr ) ;
if ( nestedExpr . MustBeParenthesized ) {
allArgs . Add ( new Ast . ParenthesizedExpression ( astExpr ) ) ;
} else {
allArgs . Add ( astExpr ) ;
if ( branch is SimpleBranch ) {
List < Ast . Expression > args = TransformExpressionArguments ( ( ( SimpleBranch ) branch ) . BasicBlock . Body [ 0 ] ) ;
Ast . Expression arg1 = args . Count > = 1 ? args [ 0 ] : null ;
Ast . Expression arg2 = args . Count > = 2 ? args [ 1 ] : null ;
switch ( ( ( SimpleBranch ) branch ) . BasicBlock . Body [ 0 ] . LastByteCode . OpCode . Code ) {
case Code . Brfalse : return new Ast . UnaryOperatorExpression ( arg1 , UnaryOperatorType . Not ) ;
case Code . Brtrue : return arg1 ;
case Code . Beq : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . Equality , arg2 ) ;
case Code . Bge : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . GreaterThanOrEqual , arg2 ) ;
case Code . Bge_Un : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . GreaterThanOrEqual , arg2 ) ;
case Code . Bgt : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . GreaterThan , arg2 ) ;
case Code . Bgt_Un : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . GreaterThan , arg2 ) ;
case Code . Ble : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . LessThanOrEqual , arg2 ) ;
case Code . Ble_Un : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . LessThanOrEqual , arg2 ) ;
case Code . Blt : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . LessThan , arg2 ) ;
case Code . Blt_Un : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . LessThan , arg2 ) ;
case Code . Bne_Un : return new Ast . BinaryOperatorExpression ( arg1 , BinaryOperatorType . InEquality , arg2 ) ;
default : throw new Exception ( "Bad opcode" ) ;
}
}
try {
return MakeCodeDomExpression ( methodDef , expr . LastByteCode , allArgs . ToArray ( ) ) ;
} catch ( NotImplementedException ) {
if ( expr . LastByteCode . Operand ! = null ) {
allArgs . Insert ( 0 , new IdentifierExpression ( expr . LastByteCode . FormatedOperand ) ) ;
} else if ( branch is ShortCircuitBranch ) {
ShortCircuitBranch scBranch = ( ShortCircuitBranch ) branch ;
switch ( scBranch . Operator ) {
case ShortCircuitOperator . LeftAndRight :
return new BinaryOperatorExpression (
MakeBranchCondition ( scBranch . Left ) ,
BinaryOperatorType . LogicalAnd ,
MakeBranchCondition ( scBranch . Right )
) ;
case ShortCircuitOperator . LeftOrRight :
return new BinaryOperatorExpression (
MakeBranchCondition ( scBranch . Left ) ,
BinaryOperatorType . LogicalOr ,
MakeBranchCondition ( scBranch . Right )
) ;
case ShortCircuitOperator . NotLeftAndRight :
return new BinaryOperatorExpression (
new UnaryOperatorExpression ( MakeBranchCondition ( scBranch . Left ) , UnaryOperatorType . Not ) ,
BinaryOperatorType . LogicalAnd ,
MakeBranchCondition ( scBranch . Right )
) ;
case ShortCircuitOperator . NotLeftOrRight :
return new BinaryOperatorExpression (
new UnaryOperatorExpression ( MakeBranchCondition ( scBranch . Left ) , UnaryOperatorType . Not ) ,
BinaryOperatorType . LogicalOr ,
MakeBranchCondition ( scBranch . Right )
) ;
default :
throw new Exception ( "Bad operator" ) ;
}
return new Ast . InvocationExpression ( new IdentifierExpression ( "IL__" + expr . LastByteCode . OpCode . Name ) , allArgs ) ;
} else {
throw new Exception ( "Bad type" ) ;
}
}
static object MakeCodeDomExpression ( MethodDefinition methodDef , ByteCode byteCode , params Ast . Expression [ ] args )
static object TransformByteCode ( MethodDefinition methodDef , ByteCode byteCode , params Ast . Expression [ ] args )
{
OpCode opCode = byteCode . OpCode ;
object operand = byteCode . Operand ;
@ -236,7 +305,7 @@ namespace Decompiler
@@ -236,7 +305,7 @@ namespace Decompiler
Ast . Statement branchCommand = null ;
if ( operand is ByteCode ) {
branchCommand = MakeBranchCommand ( byteCode . Expression . BasicBlock , ( ( ByteCode ) operand ) . Expression . BasicBlock ) ;
branchCommand = new Ast . GotoStatement ( ( ( ByteCode ) operand ) . Expression . BasicBlock . Label ) ;
}
switch ( opCode . Code ) {