|
|
|
@ -1,8 +1,8 @@
@@ -1,8 +1,8 @@
|
|
|
|
|
using System; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using Ast = ICSharpCode.NRefactory.Ast; |
|
|
|
|
using ICSharpCode.NRefactory.Ast; |
|
|
|
|
using Ast = ICSharpCode.NRefactory.CSharp; |
|
|
|
|
using ICSharpCode.NRefactory.CSharp; |
|
|
|
|
using Cecil = Mono.Cecil; |
|
|
|
|
using Mono.Cecil; |
|
|
|
|
using Mono.Cecil.Cil; |
|
|
|
@ -11,7 +11,7 @@ using Decompiler.ControlFlow;
@@ -11,7 +11,7 @@ using Decompiler.ControlFlow;
|
|
|
|
|
|
|
|
|
|
namespace Decompiler |
|
|
|
|
{ |
|
|
|
|
public class AstMetodBodyBuilder |
|
|
|
|
public class AstMethodBodyBuilder |
|
|
|
|
{ |
|
|
|
|
MethodDefinition methodDef; |
|
|
|
|
static Dictionary<string, Cecil.TypeReference> localVarTypes = new Dictionary<string, Cecil.TypeReference>(); |
|
|
|
@ -19,7 +19,7 @@ namespace Decompiler
@@ -19,7 +19,7 @@ namespace Decompiler
|
|
|
|
|
|
|
|
|
|
public static BlockStatement CreateMetodBody(MethodDefinition methodDef) |
|
|
|
|
{ |
|
|
|
|
AstMetodBodyBuilder builder = new AstMetodBodyBuilder(); |
|
|
|
|
AstMethodBodyBuilder builder = new AstMethodBodyBuilder(); |
|
|
|
|
builder.methodDef = methodDef; |
|
|
|
|
if (Debugger.IsAttached) { |
|
|
|
|
return builder.CreateMethodBody(); |
|
|
|
@ -28,7 +28,7 @@ namespace Decompiler
@@ -28,7 +28,7 @@ namespace Decompiler
|
|
|
|
|
return builder.CreateMethodBody(); |
|
|
|
|
} catch { |
|
|
|
|
BlockStatement block = new BlockStatement(); |
|
|
|
|
block.Children.Add(MakeComment("// Exception during decompilation")); |
|
|
|
|
block.AddChild(new Comment("// Exception during decompilation"), BlockStatement.Roles.Comment); |
|
|
|
|
return block; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -53,9 +53,7 @@ namespace Decompiler
@@ -53,9 +53,7 @@ namespace Decompiler
|
|
|
|
|
|
|
|
|
|
public BlockStatement CreateMethodBody() |
|
|
|
|
{ |
|
|
|
|
Ast.BlockStatement astBlock = new Ast.BlockStatement(); |
|
|
|
|
|
|
|
|
|
if (methodDef.Body == null) return astBlock; |
|
|
|
|
if (methodDef.Body == null) return new Ast.BlockStatement(); |
|
|
|
|
|
|
|
|
|
List<ILNode> body = new ILAstBuilder().Build(methodDef, true); |
|
|
|
|
|
|
|
|
@ -106,12 +104,13 @@ namespace Decompiler
@@ -106,12 +104,13 @@ namespace Decompiler
|
|
|
|
|
// astBlock.Children.Add(astLocalVar);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
astBlock.Children.AddRange(TransformNodes(bodyGraph.Childs)); |
|
|
|
|
|
|
|
|
|
Ast.BlockStatement astBlock = new Ast.BlockStatement(); |
|
|
|
|
astBlock.Statements = TransformNodes(bodyGraph.Childs); |
|
|
|
|
CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments
|
|
|
|
|
return astBlock; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IEnumerable<Ast.INode> TransformNodes(IEnumerable<Node> nodes) |
|
|
|
|
IEnumerable<Statement> TransformNodes(IEnumerable<Node> nodes) |
|
|
|
|
{ |
|
|
|
|
foreach(Node node in nodes) { |
|
|
|
|
foreach(Ast.Statement stmt in TransformNode(node)) { |
|
|
|
@ -120,18 +119,18 @@ namespace Decompiler
@@ -120,18 +119,18 @@ namespace Decompiler
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IEnumerable<Ast.INode> TransformNode(Node node) |
|
|
|
|
IEnumerable<Statement> TransformNode(Node node) |
|
|
|
|
{ |
|
|
|
|
if (Options.NodeComments) { |
|
|
|
|
yield return MakeComment("// " + node.Description); |
|
|
|
|
yield return new CommentStatement("// " + node.Description); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
yield return new Ast.LabelStatement(node.Label); |
|
|
|
|
yield return new Ast.LabelStatement { Label = node.Label }; |
|
|
|
|
|
|
|
|
|
if (node is BasicBlock) { |
|
|
|
|
foreach(ILNode expr in ((BasicBlock)node).Body) { |
|
|
|
|
if (expr is ILLabel) { |
|
|
|
|
yield return new Ast.LabelStatement(((ILLabel)expr).Name); |
|
|
|
|
yield return new Ast.LabelStatement { Label = ((ILLabel)expr).Name }; |
|
|
|
|
} else { |
|
|
|
|
Statement stmt = TransformExpressionToStatement((ILExpression)expr); |
|
|
|
|
if (stmt != null) { |
|
|
|
@ -139,108 +138,100 @@ namespace Decompiler
@@ -139,108 +138,100 @@ namespace Decompiler
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach(Ast.INode inode in TransformNodes(node.Childs)) { |
|
|
|
|
foreach(Statement inode in TransformNodes(node.Childs)) { |
|
|
|
|
yield return inode; |
|
|
|
|
} |
|
|
|
|
Node fallThroughNode = ((BasicBlock)node).FallThroughBasicBlock; |
|
|
|
|
// If there is default branch and it is not the following node
|
|
|
|
|
if (fallThroughNode != null) { |
|
|
|
|
yield return new Ast.GotoStatement(fallThroughNode.Label); |
|
|
|
|
yield return new Ast.GotoStatement { GotoType = GotoType.Label, Label = fallThroughNode.Label }; |
|
|
|
|
} |
|
|
|
|
} else if (node is AcyclicGraph) { |
|
|
|
|
foreach(Ast.INode inode in TransformNodes(node.Childs)) { |
|
|
|
|
foreach(Statement inode in TransformNodes(node.Childs)) { |
|
|
|
|
yield return inode; |
|
|
|
|
} |
|
|
|
|
} else if (node is Loop) { |
|
|
|
|
Ast.BlockStatement blockStatement = new Ast.BlockStatement(); |
|
|
|
|
blockStatement.Children.AddRange(TransformNodes(node.Childs)); |
|
|
|
|
yield return new Ast.ForStatement( |
|
|
|
|
null, |
|
|
|
|
null, |
|
|
|
|
null, |
|
|
|
|
blockStatement |
|
|
|
|
); |
|
|
|
|
blockStatement.Statements = TransformNodes(node.Childs); |
|
|
|
|
yield return new Ast.ForStatement { |
|
|
|
|
EmbeddedStatement = blockStatement |
|
|
|
|
}; |
|
|
|
|
} else if (node is Block) { |
|
|
|
|
foreach(Ast.INode inode in TransformNodes(node.Childs)) { |
|
|
|
|
foreach(Statement inode in TransformNodes(node.Childs)) { |
|
|
|
|
yield return inode; |
|
|
|
|
} |
|
|
|
|
} else if (node is Branch) { |
|
|
|
|
yield return new Ast.LabelStatement(((Branch)node).FirstBasicBlock.Label); |
|
|
|
|
yield return new Ast.LabelStatement { Label = ((Branch)node).FirstBasicBlock.Label }; |
|
|
|
|
|
|
|
|
|
Ast.BlockStatement trueBlock = new Ast.BlockStatement(); |
|
|
|
|
trueBlock.Children.Add(new Ast.GotoStatement(((Branch)node).TrueSuccessor.Label)); |
|
|
|
|
trueBlock.AddStatement(new Ast.GotoStatement(((Branch)node).TrueSuccessor.Label)); |
|
|
|
|
|
|
|
|
|
Ast.BlockStatement falseBlock = new Ast.BlockStatement(); |
|
|
|
|
falseBlock.Children.Add(new Ast.GotoStatement(((Branch)node).FalseSuccessor.Label)); |
|
|
|
|
falseBlock.AddStatement(new Ast.GotoStatement(((Branch)node).FalseSuccessor.Label)); |
|
|
|
|
|
|
|
|
|
Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement( |
|
|
|
|
MakeBranchCondition((Branch)node), |
|
|
|
|
trueBlock, |
|
|
|
|
falseBlock |
|
|
|
|
); |
|
|
|
|
trueBlock.Parent = ifElseStmt; |
|
|
|
|
falseBlock.Parent = ifElseStmt; |
|
|
|
|
Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement { |
|
|
|
|
Condition = MakeBranchCondition((Branch)node), |
|
|
|
|
TrueStatement = trueBlock, |
|
|
|
|
FalseStatement = falseBlock |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
yield return ifElseStmt; |
|
|
|
|
} else if (node is ConditionalNode) { |
|
|
|
|
ConditionalNode conditionalNode = (ConditionalNode)node; |
|
|
|
|
yield return new Ast.LabelStatement(conditionalNode.Condition.FirstBasicBlock.Label); |
|
|
|
|
yield return new Ast.LabelStatement { Label = conditionalNode.Condition.FirstBasicBlock.Label }; |
|
|
|
|
|
|
|
|
|
Ast.BlockStatement trueBlock = new Ast.BlockStatement(); |
|
|
|
|
// The block entry code
|
|
|
|
|
trueBlock.Children.Add(new Ast.GotoStatement(conditionalNode.Condition.TrueSuccessor.Label)); |
|
|
|
|
trueBlock.AddStatement(new Ast.GotoStatement(conditionalNode.Condition.TrueSuccessor.Label)); |
|
|
|
|
// Sugested content
|
|
|
|
|
trueBlock.Children.AddRange(TransformNode(conditionalNode.TrueBody)); |
|
|
|
|
trueBlock.AddStatements(TransformNode(conditionalNode.TrueBody)); |
|
|
|
|
|
|
|
|
|
Ast.BlockStatement falseBlock = new Ast.BlockStatement(); |
|
|
|
|
// The block entry code
|
|
|
|
|
falseBlock.Children.Add(new Ast.GotoStatement(conditionalNode.Condition.FalseSuccessor.Label)); |
|
|
|
|
falseBlock.AddStatement(new Ast.GotoStatement(conditionalNode.Condition.FalseSuccessor.Label)); |
|
|
|
|
// Sugested content
|
|
|
|
|
falseBlock.Children.AddRange(TransformNode(conditionalNode.FalseBody)); |
|
|
|
|
falseBlock.AddStatements(TransformNode(conditionalNode.FalseBody)); |
|
|
|
|
|
|
|
|
|
Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement( |
|
|
|
|
Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement { |
|
|
|
|
// Method bodies are swapped
|
|
|
|
|
new Ast.UnaryOperatorExpression( |
|
|
|
|
new Ast.ParenthesizedExpression( |
|
|
|
|
MakeBranchCondition(conditionalNode.Condition) |
|
|
|
|
), |
|
|
|
|
UnaryOperatorType.Not |
|
|
|
|
Condition = new Ast.UnaryOperatorExpression( |
|
|
|
|
UnaryOperatorType.Not, |
|
|
|
|
MakeBranchCondition(conditionalNode.Condition) |
|
|
|
|
), |
|
|
|
|
falseBlock, |
|
|
|
|
trueBlock |
|
|
|
|
); |
|
|
|
|
trueBlock.Parent = ifElseStmt; |
|
|
|
|
falseBlock.Parent = ifElseStmt; |
|
|
|
|
TrueStatement = falseBlock, |
|
|
|
|
FalseStatement = trueBlock |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
yield return ifElseStmt; |
|
|
|
|
} else if (node is TryCatchNode) { |
|
|
|
|
TryCatchNode tryCachNode = ((TryCatchNode)node); |
|
|
|
|
Ast.BlockStatement tryBlock = new Ast.BlockStatement(); |
|
|
|
|
tryBlock.Children.AddRange(TransformNode(tryCachNode.Childs[0])); |
|
|
|
|
tryBlock.Statements = TransformNode(tryCachNode.Childs[0]); |
|
|
|
|
Ast.BlockStatement finallyBlock = null; |
|
|
|
|
if (tryCachNode.Childs[1].Childs.Count > 0) { |
|
|
|
|
finallyBlock = new Ast.BlockStatement(); |
|
|
|
|
finallyBlock.Children.AddRange(TransformNode(tryCachNode.Childs[1])); |
|
|
|
|
finallyBlock.Statements = TransformNode(tryCachNode.Childs[1]); |
|
|
|
|
} |
|
|
|
|
List<Ast.CatchClause> ccs = new List<CatchClause>(); |
|
|
|
|
for (int i = 0; i < tryCachNode.Types.Count; i++) { |
|
|
|
|
Ast.BlockStatement catchBlock = new Ast.BlockStatement(); |
|
|
|
|
catchBlock.Children.AddRange(TransformNode(tryCachNode.Childs[i + 2])); |
|
|
|
|
Ast.CatchClause cc = new Ast.CatchClause( |
|
|
|
|
new Ast.TypeReference(tryCachNode.Types[i].FullName), |
|
|
|
|
"exception", |
|
|
|
|
catchBlock |
|
|
|
|
); |
|
|
|
|
catchBlock.Statements = TransformNode(tryCachNode.Childs[i + 2]); |
|
|
|
|
Ast.CatchClause cc = new Ast.CatchClause { |
|
|
|
|
Type = AstBuilder.ConvertType(tryCachNode.Types[i]), |
|
|
|
|
VariableName = "exception", |
|
|
|
|
Body = catchBlock |
|
|
|
|
}; |
|
|
|
|
ccs.Add(cc); |
|
|
|
|
} |
|
|
|
|
Ast.TryCatchStatement tryCachStmt = new Ast.TryCatchStatement(tryBlock, ccs, finallyBlock); |
|
|
|
|
yield return tryCachStmt; |
|
|
|
|
yield return new Ast.TryCatchStatement { |
|
|
|
|
TryBlock = tryBlock, CatchClauses = ccs, FinallyBlock = finallyBlock |
|
|
|
|
}; |
|
|
|
|
} else { |
|
|
|
|
throw new Exception("Bad node type"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (Options.NodeComments) { |
|
|
|
|
yield return MakeComment(""); |
|
|
|
|
yield return new CommentStatement(""); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -266,7 +257,7 @@ namespace Decompiler
@@ -266,7 +257,7 @@ namespace Decompiler
|
|
|
|
|
if (codeExpr == null) { |
|
|
|
|
return null; |
|
|
|
|
} else if (codeExpr is Ast.Expression) { |
|
|
|
|
return new Ast.ExpressionStatement((Ast.Expression)codeExpr); |
|
|
|
|
return new Ast.ExpressionStatement { Expression = (Ast.Expression)codeExpr }; |
|
|
|
|
} else if (codeExpr is Ast.Statement) { |
|
|
|
|
return (Ast.Statement)codeExpr; |
|
|
|
|
} else { |
|
|
|
@ -274,15 +265,9 @@ namespace Decompiler
@@ -274,15 +265,9 @@ namespace Decompiler
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static Ast.ExpressionStatement MakeComment(string text) |
|
|
|
|
{ |
|
|
|
|
text = "/***" + text + "***/"; |
|
|
|
|
return new Ast.ExpressionStatement(new PrimitiveExpression(text, text)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ast.Expression MakeBranchCondition(Branch branch) |
|
|
|
|
{ |
|
|
|
|
return new ParenthesizedExpression(MakeBranchCondition_Internal(branch)); |
|
|
|
|
return MakeBranchCondition_Internal(branch); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ast.Expression MakeBranchCondition_Internal(Branch branch) |
|
|
|
@ -292,20 +277,20 @@ namespace Decompiler
@@ -292,20 +277,20 @@ namespace Decompiler
|
|
|
|
|
Ast.Expression arg1 = args.Count >= 1 ? args[0] : null; |
|
|
|
|
Ast.Expression arg2 = args.Count >= 2 ? args[1] : null; |
|
|
|
|
switch(((ILExpression)((SimpleBranch)branch).BasicBlock.Body[0]).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); |
|
|
|
|
case Code.Leave: return new Ast.PrimitiveExpression(true, true.ToString()); |
|
|
|
|
default: throw new Exception("Bad opcode"); |
|
|
|
|
case Code.Brfalse: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1); |
|
|
|
|
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); |
|
|
|
|
case Code.Leave: return new Ast.PrimitiveExpression(true); |
|
|
|
|
default: throw new Exception("Bad opcode"); |
|
|
|
|
} |
|
|
|
|
} else if (branch is ShortCircuitBranch) { |
|
|
|
|
ShortCircuitBranch scBranch = (ShortCircuitBranch)branch; |
|
|
|
@ -313,25 +298,25 @@ namespace Decompiler
@@ -313,25 +298,25 @@ namespace Decompiler
|
|
|
|
|
case ShortCircuitOperator.LeftAndRight: |
|
|
|
|
return new BinaryOperatorExpression( |
|
|
|
|
MakeBranchCondition(scBranch.Left), |
|
|
|
|
BinaryOperatorType.LogicalAnd, |
|
|
|
|
BinaryOperatorType.ConditionalAnd, |
|
|
|
|
MakeBranchCondition(scBranch.Right) |
|
|
|
|
); |
|
|
|
|
case ShortCircuitOperator.LeftOrRight: |
|
|
|
|
return new BinaryOperatorExpression( |
|
|
|
|
MakeBranchCondition(scBranch.Left), |
|
|
|
|
BinaryOperatorType.LogicalOr, |
|
|
|
|
BinaryOperatorType.ConditionalOr, |
|
|
|
|
MakeBranchCondition(scBranch.Right) |
|
|
|
|
); |
|
|
|
|
case ShortCircuitOperator.NotLeftAndRight: |
|
|
|
|
return new BinaryOperatorExpression( |
|
|
|
|
new UnaryOperatorExpression(MakeBranchCondition(scBranch.Left), UnaryOperatorType.Not), |
|
|
|
|
BinaryOperatorType.LogicalAnd, |
|
|
|
|
new UnaryOperatorExpression(UnaryOperatorType.Not, MakeBranchCondition(scBranch.Left)), |
|
|
|
|
BinaryOperatorType.ConditionalAnd, |
|
|
|
|
MakeBranchCondition(scBranch.Right) |
|
|
|
|
); |
|
|
|
|
case ShortCircuitOperator.NotLeftOrRight: |
|
|
|
|
return new BinaryOperatorExpression( |
|
|
|
|
new UnaryOperatorExpression(MakeBranchCondition(scBranch.Left), UnaryOperatorType.Not), |
|
|
|
|
BinaryOperatorType.LogicalOr, |
|
|
|
|
new UnaryOperatorExpression(UnaryOperatorType.Not, MakeBranchCondition(scBranch.Left)), |
|
|
|
|
BinaryOperatorType.ConditionalOr, |
|
|
|
|
MakeBranchCondition(scBranch.Right) |
|
|
|
|
); |
|
|
|
|
default: |
|
|
|
@ -345,10 +330,7 @@ namespace Decompiler
@@ -345,10 +330,7 @@ namespace Decompiler
|
|
|
|
|
static object TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args) |
|
|
|
|
{ |
|
|
|
|
try { |
|
|
|
|
Ast.INode ret = TransformByteCode_Internal(methodDef, byteCode, args); |
|
|
|
|
if (ret is Ast.Expression) { |
|
|
|
|
ret = new ParenthesizedExpression((Ast.Expression)ret); |
|
|
|
|
} |
|
|
|
|
AstNode ret = TransformByteCode_Internal(methodDef, byteCode, args); |
|
|
|
|
// ret.UserData["Type"] = byteCode.Type;
|
|
|
|
|
return ret; |
|
|
|
|
} catch (NotImplementedException) { |
|
|
|
@ -356,7 +338,7 @@ namespace Decompiler
@@ -356,7 +338,7 @@ namespace Decompiler
|
|
|
|
|
if (byteCode.Operand != null) { |
|
|
|
|
args.Insert(0, new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand))); |
|
|
|
|
} |
|
|
|
|
return new Ast.InvocationExpression(new IdentifierExpression(byteCode.OpCode.Name), args); |
|
|
|
|
return new IdentifierExpression(byteCode.OpCode.Name).Invoke(args); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -364,8 +346,8 @@ namespace Decompiler
@@ -364,8 +346,8 @@ namespace Decompiler
|
|
|
|
|
{ |
|
|
|
|
if (operand == null) { |
|
|
|
|
return string.Empty; |
|
|
|
|
//} else if (operand is ILExpression) {
|
|
|
|
|
// return string.Format("IL_{0:X2}", ((ILExpression)operand).Offset);
|
|
|
|
|
//} else if (operand is ILExpression) {
|
|
|
|
|
// return string.Format("IL_{0:X2}", ((ILExpression)operand).Offset);
|
|
|
|
|
} else if (operand is MethodReference) { |
|
|
|
|
return ((MethodReference)operand).Name + "()"; |
|
|
|
|
} else if (operand is Cecil.TypeReference) { |
|
|
|
@ -385,13 +367,13 @@ namespace Decompiler
@@ -385,13 +367,13 @@ namespace Decompiler
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static Ast.INode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args) |
|
|
|
|
static AstNode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args) |
|
|
|
|
{ |
|
|
|
|
// throw new NotImplementedException();
|
|
|
|
|
|
|
|
|
|
OpCode opCode = byteCode.OpCode; |
|
|
|
|
object operand = byteCode.Operand; |
|
|
|
|
Ast.TypeReference operandAsTypeRef = operand is Cecil.TypeReference ? new Ast.TypeReference(((Cecil.TypeReference)operand).FullName) : null; |
|
|
|
|
AstType operandAsTypeRef = AstBuilder.ConvertType(operand as Cecil.TypeReference); |
|
|
|
|
ILExpression operandAsByteCode = operand as ILExpression; |
|
|
|
|
Ast.Expression arg1 = args.Count >= 1 ? args[0] : null; |
|
|
|
|
Ast.Expression arg2 = args.Count >= 2 ? args[1] : null; |
|
|
|
@ -403,7 +385,7 @@ namespace Decompiler
@@ -403,7 +385,7 @@ namespace Decompiler
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch(opCode.Code) { |
|
|
|
|
#region Arithmetic
|
|
|
|
|
#region Arithmetic
|
|
|
|
|
case Code.Add: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); |
|
|
|
|
case Code.Add_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); |
|
|
|
|
case Code.Add_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); |
|
|
|
@ -423,43 +405,52 @@ namespace Decompiler
@@ -423,43 +405,52 @@ namespace Decompiler
|
|
|
|
|
case Code.Shr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); |
|
|
|
|
case Code.Shr_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); |
|
|
|
|
|
|
|
|
|
case Code.Neg: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Minus); |
|
|
|
|
case Code.Not: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.BitNot); |
|
|
|
|
#endregion
|
|
|
|
|
#region Arrays
|
|
|
|
|
case Code.Newarr: |
|
|
|
|
operandAsTypeRef.RankSpecifier = new int[] {0}; |
|
|
|
|
return new Ast.ArrayCreateExpression(operandAsTypeRef, new List<Expression>(new Expression[] {arg1})); |
|
|
|
|
case Code.Neg: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Minus, arg1); |
|
|
|
|
case Code.Not: return new Ast.UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1); |
|
|
|
|
#endregion
|
|
|
|
|
#region Arrays
|
|
|
|
|
case Code.Newarr: |
|
|
|
|
operandAsTypeRef = operandAsTypeRef.MakeArrayType(0); |
|
|
|
|
return new Ast.ArrayCreateExpression { |
|
|
|
|
Type = operandAsTypeRef, |
|
|
|
|
Arguments = new Expression[] {arg1} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
case Code.Ldlen: return new Ast.MemberReferenceExpression(arg1, "Length"); |
|
|
|
|
case Code.Ldlen: |
|
|
|
|
return arg1.Member("Length"); |
|
|
|
|
|
|
|
|
|
case Code.Ldelem_I: |
|
|
|
|
case Code.Ldelem_I1: |
|
|
|
|
case Code.Ldelem_I2: |
|
|
|
|
case Code.Ldelem_I4: |
|
|
|
|
case Code.Ldelem_I8: |
|
|
|
|
case Code.Ldelem_U1: |
|
|
|
|
case Code.Ldelem_U2: |
|
|
|
|
case Code.Ldelem_U4: |
|
|
|
|
case Code.Ldelem_R4: |
|
|
|
|
case Code.Ldelem_R8: |
|
|
|
|
case Code.Ldelem_Ref: return new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2})); |
|
|
|
|
case Code.Ldelem_Any: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldelema: return new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2})); |
|
|
|
|
case Code.Ldelem_I: |
|
|
|
|
case Code.Ldelem_I1: |
|
|
|
|
case Code.Ldelem_I2: |
|
|
|
|
case Code.Ldelem_I4: |
|
|
|
|
case Code.Ldelem_I8: |
|
|
|
|
case Code.Ldelem_U1: |
|
|
|
|
case Code.Ldelem_U2: |
|
|
|
|
case Code.Ldelem_U4: |
|
|
|
|
case Code.Ldelem_R4: |
|
|
|
|
case Code.Ldelem_R8: |
|
|
|
|
case Code.Ldelem_Ref: |
|
|
|
|
return arg1.Indexer(arg2); |
|
|
|
|
case Code.Ldelem_Any: |
|
|
|
|
throw new NotImplementedException(); |
|
|
|
|
case Code.Ldelema: |
|
|
|
|
return arg1.Indexer(arg2); |
|
|
|
|
|
|
|
|
|
case Code.Stelem_I: |
|
|
|
|
case Code.Stelem_I1: |
|
|
|
|
case Code.Stelem_I2: |
|
|
|
|
case Code.Stelem_I4: |
|
|
|
|
case Code.Stelem_I8: |
|
|
|
|
case Code.Stelem_R4: |
|
|
|
|
case Code.Stelem_R8: |
|
|
|
|
case Code.Stelem_Ref: return new Ast.AssignmentExpression(new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2})), AssignmentOperatorType.Assign, arg3); |
|
|
|
|
case Code.Stelem_Any: throw new NotImplementedException(); |
|
|
|
|
#endregion
|
|
|
|
|
#region Branching
|
|
|
|
|
case Code.Stelem_I: |
|
|
|
|
case Code.Stelem_I1: |
|
|
|
|
case Code.Stelem_I2: |
|
|
|
|
case Code.Stelem_I4: |
|
|
|
|
case Code.Stelem_I8: |
|
|
|
|
case Code.Stelem_R4: |
|
|
|
|
case Code.Stelem_R8: |
|
|
|
|
case Code.Stelem_Ref: |
|
|
|
|
return new Ast.AssignmentExpression(arg1.Indexer(arg2), arg3); |
|
|
|
|
case Code.Stelem_Any: |
|
|
|
|
throw new NotImplementedException(); |
|
|
|
|
#endregion
|
|
|
|
|
#region Branching
|
|
|
|
|
case Code.Br: return branchCommand; |
|
|
|
|
case Code.Brfalse: return new Ast.IfElseStatement(new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Not), branchCommand); |
|
|
|
|
case Code.Brfalse: return new Ast.IfElseStatement(new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1), branchCommand); |
|
|
|
|
case Code.Brtrue: return new Ast.IfElseStatement(arg1, branchCommand); |
|
|
|
|
case Code.Beq: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2), branchCommand); |
|
|
|
|
case Code.Bge: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), branchCommand); |
|
|
|
@ -471,52 +462,52 @@ namespace Decompiler
@@ -471,52 +462,52 @@ namespace Decompiler
|
|
|
|
|
case Code.Blt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), branchCommand); |
|
|
|
|
case Code.Blt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), branchCommand); |
|
|
|
|
case Code.Bne_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2), branchCommand); |
|
|
|
|
#endregion
|
|
|
|
|
#region Comparison
|
|
|
|
|
#endregion
|
|
|
|
|
#region Comparison
|
|
|
|
|
case Code.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, ConvertIntToBool(arg2)); |
|
|
|
|
case Code.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); |
|
|
|
|
case Code.Cgt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); |
|
|
|
|
case Code.Clt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); |
|
|
|
|
case Code.Clt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); |
|
|
|
|
#endregion
|
|
|
|
|
#region Conversions
|
|
|
|
|
case Code.Conv_I: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
|
|
|
|
|
case Code.Conv_I1: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_I2: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_I4: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_I8: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_U: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
|
|
|
|
|
case Code.Conv_U1: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_U2: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_U4: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_U8: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_R4: return new Ast.CastExpression(new Ast.TypeReference(typeof(float).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_R8: return new Ast.CastExpression(new Ast.TypeReference(typeof(double).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_R_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(double).FullName), arg1, CastType.Cast); // TODO
|
|
|
|
|
#endregion
|
|
|
|
|
#region Conversions
|
|
|
|
|
case Code.Conv_I: return arg1.CastTo(typeof(int)); // TODO
|
|
|
|
|
case Code.Conv_I1: return arg1.CastTo(typeof(SByte)); |
|
|
|
|
case Code.Conv_I2: return arg1.CastTo(typeof(Int16)); |
|
|
|
|
case Code.Conv_I4: return arg1.CastTo(typeof(Int32)); |
|
|
|
|
case Code.Conv_I8: return arg1.CastTo(typeof(Int64)); |
|
|
|
|
case Code.Conv_U: return arg1.CastTo(typeof(uint)); // TODO
|
|
|
|
|
case Code.Conv_U1: return arg1.CastTo(typeof(Byte)); |
|
|
|
|
case Code.Conv_U2: return arg1.CastTo(typeof(UInt16)); |
|
|
|
|
case Code.Conv_U4: return arg1.CastTo(typeof(UInt32)); |
|
|
|
|
case Code.Conv_U8: return arg1.CastTo(typeof(UInt64)); |
|
|
|
|
case Code.Conv_R4: return arg1.CastTo(typeof(float)); |
|
|
|
|
case Code.Conv_R8: return arg1.CastTo(typeof(double)); |
|
|
|
|
case Code.Conv_R_Un: return arg1.CastTo(typeof(double)); // TODO
|
|
|
|
|
|
|
|
|
|
case Code.Conv_Ovf_I: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
|
|
|
|
|
case Code.Conv_Ovf_I1: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_I2: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_I4: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_I8: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_U: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
|
|
|
|
|
case Code.Conv_Ovf_U1: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_U2: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_U4: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_U8: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_I: return arg1.CastTo(typeof(int)); |
|
|
|
|
case Code.Conv_Ovf_I1: return arg1.CastTo(typeof(SByte)); |
|
|
|
|
case Code.Conv_Ovf_I2: return arg1.CastTo(typeof(Int16)); |
|
|
|
|
case Code.Conv_Ovf_I4: return arg1.CastTo(typeof(Int32)); |
|
|
|
|
case Code.Conv_Ovf_I8: return arg1.CastTo(typeof(Int64)); |
|
|
|
|
case Code.Conv_Ovf_U: return arg1.CastTo(typeof(uint)); |
|
|
|
|
case Code.Conv_Ovf_U1: return arg1.CastTo(typeof(Byte)); |
|
|
|
|
case Code.Conv_Ovf_U2: return arg1.CastTo(typeof(UInt16)); |
|
|
|
|
case Code.Conv_Ovf_U4: return arg1.CastTo(typeof(UInt32)); |
|
|
|
|
case Code.Conv_Ovf_U8: return arg1.CastTo(typeof(UInt64)); |
|
|
|
|
|
|
|
|
|
case Code.Conv_Ovf_I_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
|
|
|
|
|
case Code.Conv_Ovf_I1_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_I2_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_I4_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_I8_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_U_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
|
|
|
|
|
case Code.Conv_Ovf_U1_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_U2_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_U4_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast); |
|
|
|
|
case Code.Conv_Ovf_U8_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast); |
|
|
|
|
#endregion
|
|
|
|
|
#region Indirect
|
|
|
|
|
case Code.Conv_Ovf_I_Un: return arg1.CastTo(typeof(int)); |
|
|
|
|
case Code.Conv_Ovf_I1_Un: return arg1.CastTo(typeof(SByte)); |
|
|
|
|
case Code.Conv_Ovf_I2_Un: return arg1.CastTo(typeof(Int16)); |
|
|
|
|
case Code.Conv_Ovf_I4_Un: return arg1.CastTo(typeof(Int32)); |
|
|
|
|
case Code.Conv_Ovf_I8_Un: return arg1.CastTo(typeof(Int64)); |
|
|
|
|
case Code.Conv_Ovf_U_Un: return arg1.CastTo(typeof(uint)); |
|
|
|
|
case Code.Conv_Ovf_U1_Un: return arg1.CastTo(typeof(Byte)); |
|
|
|
|
case Code.Conv_Ovf_U2_Un: return arg1.CastTo(typeof(UInt16)); |
|
|
|
|
case Code.Conv_Ovf_U4_Un: return arg1.CastTo(typeof(UInt32)); |
|
|
|
|
case Code.Conv_Ovf_U8_Un: return arg1.CastTo(typeof(UInt64)); |
|
|
|
|
#endregion
|
|
|
|
|
#region Indirect
|
|
|
|
|
case Code.Ldind_I: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldind_I1: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldind_I2: throw new NotImplementedException(); |
|
|
|
@ -537,10 +528,10 @@ namespace Decompiler
@@ -537,10 +528,10 @@ namespace Decompiler
|
|
|
|
|
case Code.Stind_R4: throw new NotImplementedException(); |
|
|
|
|
case Code.Stind_R8: throw new NotImplementedException(); |
|
|
|
|
case Code.Stind_Ref: throw new NotImplementedException(); |
|
|
|
|
#endregion
|
|
|
|
|
case Code.Arglist: throw new NotImplementedException(); |
|
|
|
|
case Code.Box: throw new NotImplementedException(); |
|
|
|
|
case Code.Break: throw new NotImplementedException(); |
|
|
|
|
#endregion
|
|
|
|
|
case Code.Arglist: throw new NotImplementedException(); |
|
|
|
|
case Code.Box: throw new NotImplementedException(); |
|
|
|
|
case Code.Break: throw new NotImplementedException(); |
|
|
|
|
case Code.Call: |
|
|
|
|
case Code.Callvirt: |
|
|
|
|
// TODO: Diferentiate vitual and non-vitual dispach
|
|
|
|
@ -556,21 +547,21 @@ namespace Decompiler
@@ -556,21 +547,21 @@ namespace Decompiler
|
|
|
|
|
|
|
|
|
|
// TODO: Constructors are ignored
|
|
|
|
|
if (cecilMethod.Name == ".ctor") { |
|
|
|
|
return MakeComment("// Constructor"); |
|
|
|
|
return new CommentStatement("// Constructor"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: Hack, detect properties properly
|
|
|
|
|
if (cecilMethod.Name.StartsWith("get_")) { |
|
|
|
|
return new Ast.MemberReferenceExpression(target, cecilMethod.Name.Remove(0, 4)); |
|
|
|
|
return target.Member(cecilMethod.Name.Remove(0, 4)); |
|
|
|
|
} else if (cecilMethod.Name.StartsWith("set_")) { |
|
|
|
|
return new Ast.AssignmentExpression( |
|
|
|
|
new Ast.MemberReferenceExpression(target, cecilMethod.Name.Remove(0, 4)), |
|
|
|
|
AssignmentOperatorType.Assign, |
|
|
|
|
target.Member(cecilMethod.Name.Remove(0, 4)), |
|
|
|
|
methodArgs[0] |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Multi-dimensional array acces // TODO: do properly
|
|
|
|
|
/* |
|
|
|
|
if (cecilMethod.Name == "Get") { |
|
|
|
|
return new Ast.IndexerExpression(target, methodArgs); |
|
|
|
|
} else if (cecilMethod.Name == "Set") { |
|
|
|
@ -581,162 +572,134 @@ namespace Decompiler
@@ -581,162 +572,134 @@ namespace Decompiler
|
|
|
|
|
AssignmentOperatorType.Assign, |
|
|
|
|
Convert(val, ((Cecil.ArrayType)target.UserData["Type"]).ElementType) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}*/ |
|
|
|
|
|
|
|
|
|
// Default invocation
|
|
|
|
|
return new Ast.InvocationExpression( |
|
|
|
|
new Ast.MemberReferenceExpression(target, cecilMethod.Name), |
|
|
|
|
methodArgs |
|
|
|
|
); |
|
|
|
|
case Code.Calli: throw new NotImplementedException(); |
|
|
|
|
case Code.Castclass: return new Ast.CastExpression(operandAsTypeRef, arg1, CastType.Cast); |
|
|
|
|
case Code.Ckfinite: throw new NotImplementedException(); |
|
|
|
|
case Code.Constrained: throw new NotImplementedException(); |
|
|
|
|
case Code.Cpblk: throw new NotImplementedException(); |
|
|
|
|
case Code.Cpobj: throw new NotImplementedException(); |
|
|
|
|
case Code.Dup: return arg1; |
|
|
|
|
case Code.Endfilter: throw new NotImplementedException(); |
|
|
|
|
case Code.Endfinally: return null; |
|
|
|
|
case Code.Initblk: throw new NotImplementedException(); |
|
|
|
|
case Code.Initobj: throw new NotImplementedException(); |
|
|
|
|
case Code.Isinst: return new Ast.TypeOfIsExpression(arg1, new Ast.TypeReference(((Cecil.TypeReference)operand).FullName)); |
|
|
|
|
case Code.Jmp: throw new NotImplementedException(); |
|
|
|
|
return target.Invoke(cecilMethod.Name, methodArgs); |
|
|
|
|
case Code.Calli: throw new NotImplementedException(); |
|
|
|
|
case Code.Castclass: return arg1.CastTo(operandAsTypeRef); |
|
|
|
|
case Code.Ckfinite: throw new NotImplementedException(); |
|
|
|
|
case Code.Constrained: throw new NotImplementedException(); |
|
|
|
|
case Code.Cpblk: throw new NotImplementedException(); |
|
|
|
|
case Code.Cpobj: throw new NotImplementedException(); |
|
|
|
|
case Code.Dup: return arg1; |
|
|
|
|
case Code.Endfilter: throw new NotImplementedException(); |
|
|
|
|
case Code.Endfinally: return null; |
|
|
|
|
case Code.Initblk: throw new NotImplementedException(); |
|
|
|
|
case Code.Initobj: throw new NotImplementedException(); |
|
|
|
|
case Code.Isinst: return arg1.IsType(AstBuilder.ConvertType((Cecil.TypeReference)operand)); |
|
|
|
|
case Code.Jmp: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldarg: |
|
|
|
|
if (methodDef.HasThis && ((ParameterDefinition)operand).Index < 0) { |
|
|
|
|
return new Ast.ThisReferenceExpression(); |
|
|
|
|
} else { |
|
|
|
|
return new Ast.IdentifierExpression(((ParameterDefinition)operand).Name); |
|
|
|
|
} |
|
|
|
|
case Code.Ldarga: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldc_I4: |
|
|
|
|
case Code.Ldc_I8: |
|
|
|
|
case Code.Ldc_R4: |
|
|
|
|
case Code.Ldc_R8: return new Ast.PrimitiveExpression(operand, null); |
|
|
|
|
case Code.Ldarga: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldc_I4: |
|
|
|
|
case Code.Ldc_I8: |
|
|
|
|
case Code.Ldc_R4: |
|
|
|
|
case Code.Ldc_R8: |
|
|
|
|
return new Ast.PrimitiveExpression(operand); |
|
|
|
|
case Code.Ldfld: |
|
|
|
|
case Code.Ldsfld: { |
|
|
|
|
if (operand is FieldDefinition) { |
|
|
|
|
FieldDefinition field = (FieldDefinition) operand; |
|
|
|
|
if (field.IsStatic) { |
|
|
|
|
return new Ast.MemberReferenceExpression( |
|
|
|
|
new Ast.IdentifierExpression(field.DeclaringType.FullName), |
|
|
|
|
field.Name |
|
|
|
|
); |
|
|
|
|
} else { |
|
|
|
|
return new Ast.MemberReferenceExpression(arg1, field.Name); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// TODO: Static accesses
|
|
|
|
|
return new Ast.MemberReferenceExpression(arg1, ((FieldReference)operand).Name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return arg1.Member(((FieldReference) operand).Name); |
|
|
|
|
case Code.Ldsfld: |
|
|
|
|
return AstBuilder.ConvertType(((FieldReference)operand).DeclaringType).Member(((FieldReference)operand).Name); |
|
|
|
|
case Code.Stfld: |
|
|
|
|
case Code.Stsfld: { |
|
|
|
|
FieldDefinition field = (FieldDefinition) operand; |
|
|
|
|
if (field.IsStatic) { |
|
|
|
|
return new AssignmentExpression( |
|
|
|
|
new Ast.MemberReferenceExpression( |
|
|
|
|
new Ast.IdentifierExpression(field.DeclaringType.FullName), |
|
|
|
|
field.Name |
|
|
|
|
), |
|
|
|
|
AssignmentOperatorType.Assign, |
|
|
|
|
arg1 |
|
|
|
|
); |
|
|
|
|
} else { |
|
|
|
|
return new AssignmentExpression( |
|
|
|
|
new Ast.MemberReferenceExpression(arg1, field.Name), |
|
|
|
|
AssignmentOperatorType.Assign, |
|
|
|
|
arg2 |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return new AssignmentExpression(arg1.Member(((FieldReference) operand).Name), arg2); |
|
|
|
|
case Code.Stsfld: |
|
|
|
|
return new AssignmentExpression( |
|
|
|
|
AstBuilder.ConvertType(((FieldReference)operand).DeclaringType).Member(((FieldReference)operand).Name), |
|
|
|
|
arg2); |
|
|
|
|
case Code.Ldflda: |
|
|
|
|
case Code.Ldsflda: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldftn: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldloc: |
|
|
|
|
case Code.Ldsflda: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldftn: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldloc: |
|
|
|
|
if (operand is ILVariable) { |
|
|
|
|
return new Ast.IdentifierExpression(((ILVariable)operand).Name); |
|
|
|
|
} else { |
|
|
|
|
return new Ast.IdentifierExpression(((VariableDefinition)operand).Name); |
|
|
|
|
} |
|
|
|
|
case Code.Ldloca: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldnull: return new Ast.PrimitiveExpression(null, null); |
|
|
|
|
case Code.Ldobj: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldstr: return new Ast.PrimitiveExpression(operand, null); |
|
|
|
|
case Code.Ldloca: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldnull: return new Ast.PrimitiveExpression(null); |
|
|
|
|
case Code.Ldobj: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldstr: return new Ast.PrimitiveExpression(operand); |
|
|
|
|
case Code.Ldtoken: |
|
|
|
|
if (operand is Cecil.TypeReference) { |
|
|
|
|
return new Ast.MemberReferenceExpression( |
|
|
|
|
new Ast.TypeOfExpression(operandAsTypeRef), |
|
|
|
|
"TypeHandle" |
|
|
|
|
); |
|
|
|
|
return new Ast.TypeOfExpression { Type = operandAsTypeRef }.Member("TypeHandle"); |
|
|
|
|
} else { |
|
|
|
|
throw new NotImplementedException(); |
|
|
|
|
} |
|
|
|
|
case Code.Ldvirtftn: throw new NotImplementedException(); |
|
|
|
|
case Code.Leave: return null; |
|
|
|
|
case Code.Localloc: throw new NotImplementedException(); |
|
|
|
|
case Code.Mkrefany: throw new NotImplementedException(); |
|
|
|
|
case Code.Ldvirtftn: throw new NotImplementedException(); |
|
|
|
|
case Code.Leave: return null; |
|
|
|
|
case Code.Localloc: throw new NotImplementedException(); |
|
|
|
|
case Code.Mkrefany: throw new NotImplementedException(); |
|
|
|
|
case Code.Newobj: |
|
|
|
|
Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType; |
|
|
|
|
// TODO: Ensure that the corrent overloaded constructor is called
|
|
|
|
|
if (declaringType is ArrayType) { |
|
|
|
|
return new Ast.ArrayCreateExpression( |
|
|
|
|
new Ast.TypeReference(((ArrayType)declaringType).ElementType.FullName, new int[] {}), |
|
|
|
|
new List<Expression>(args) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
return new Ast.ObjectCreateExpression( |
|
|
|
|
new Ast.TypeReference(declaringType.FullName), |
|
|
|
|
new List<Expression>(args) |
|
|
|
|
); |
|
|
|
|
case Code.No: throw new NotImplementedException(); |
|
|
|
|
case Code.Nop: return null; |
|
|
|
|
case Code.Or: throw new NotImplementedException(); |
|
|
|
|
case Code.Pop: return arg1; |
|
|
|
|
case Code.Readonly: throw new NotImplementedException(); |
|
|
|
|
case Code.Refanytype: throw new NotImplementedException(); |
|
|
|
|
case Code.Refanyval: throw new NotImplementedException(); |
|
|
|
|
case Code.Ret: { |
|
|
|
|
if (methodDef.ReturnType.FullName != Constants.Void) { |
|
|
|
|
arg1 = Convert(arg1, methodDef.ReturnType); |
|
|
|
|
return new Ast.ReturnStatement(arg1); |
|
|
|
|
} else { |
|
|
|
|
return new Ast.ReturnStatement(null); |
|
|
|
|
return new Ast.ArrayCreateExpression { |
|
|
|
|
Type = AstBuilder.ConvertType((ArrayType)declaringType), |
|
|
|
|
Arguments = args |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
case Code.Rethrow: return new Ast.ThrowStatement(new IdentifierExpression("exception")); |
|
|
|
|
case Code.Sizeof: throw new NotImplementedException(); |
|
|
|
|
case Code.Starg: throw new NotImplementedException(); |
|
|
|
|
case Code.Stloc: { |
|
|
|
|
if (operand is ILVariable) { |
|
|
|
|
Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(new Ast.VariableDeclaration(((ILVariable)operand).Name, arg1)); |
|
|
|
|
astLocalVar.TypeReference = new Ast.TypeReference("var"); |
|
|
|
|
return astLocalVar; |
|
|
|
|
} |
|
|
|
|
VariableDefinition locVar = (VariableDefinition)operand; |
|
|
|
|
string name = locVar.Name; |
|
|
|
|
arg1 = Convert(arg1, locVar.VariableType); |
|
|
|
|
if (localVarDefined.ContainsKey(name)) { |
|
|
|
|
if (localVarDefined[name]) { |
|
|
|
|
return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), AssignmentOperatorType.Assign, arg1); |
|
|
|
|
return new Ast.ObjectCreateExpression { |
|
|
|
|
Type = AstBuilder.ConvertType(declaringType), |
|
|
|
|
Arguments = args |
|
|
|
|
}; |
|
|
|
|
case Code.No: throw new NotImplementedException(); |
|
|
|
|
case Code.Nop: return null; |
|
|
|
|
case Code.Or: throw new NotImplementedException(); |
|
|
|
|
case Code.Pop: return arg1; |
|
|
|
|
case Code.Readonly: throw new NotImplementedException(); |
|
|
|
|
case Code.Refanytype: throw new NotImplementedException(); |
|
|
|
|
case Code.Refanyval: throw new NotImplementedException(); |
|
|
|
|
case Code.Ret: { |
|
|
|
|
if (methodDef.ReturnType.FullName != Constants.Void) { |
|
|
|
|
arg1 = Convert(arg1, methodDef.ReturnType); |
|
|
|
|
return new Ast.ReturnStatement { Expression = arg1 }; |
|
|
|
|
} else { |
|
|
|
|
Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(new Ast.VariableDeclaration(name, arg1)); |
|
|
|
|
astLocalVar.TypeReference = new Ast.TypeReference(localVarTypes[name].FullName); |
|
|
|
|
localVarDefined[name] = true; |
|
|
|
|
return new Ast.ReturnStatement(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
case Code.Rethrow: return new Ast.ThrowStatement(); |
|
|
|
|
case Code.Sizeof: throw new NotImplementedException(); |
|
|
|
|
case Code.Starg: throw new NotImplementedException(); |
|
|
|
|
case Code.Stloc: { |
|
|
|
|
if (operand is ILVariable) { |
|
|
|
|
var astLocalVar = new Ast.VariableDeclarationStatement(); |
|
|
|
|
astLocalVar.Type = new Ast.PrimitiveType("var"); |
|
|
|
|
astLocalVar.Variables = new [] { |
|
|
|
|
new Ast.VariableInitializer(((ILVariable)operand).Name, arg1) |
|
|
|
|
}; |
|
|
|
|
return astLocalVar; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), AssignmentOperatorType.Assign, arg1); |
|
|
|
|
VariableDefinition locVar = (VariableDefinition)operand; |
|
|
|
|
string name = locVar.Name; |
|
|
|
|
arg1 = Convert(arg1, locVar.VariableType); |
|
|
|
|
if (localVarDefined.ContainsKey(name)) { |
|
|
|
|
if (localVarDefined[name]) { |
|
|
|
|
return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), arg1); |
|
|
|
|
} else { |
|
|
|
|
var astLocalVar = new Ast.VariableDeclarationStatement(); |
|
|
|
|
astLocalVar.Type = AstBuilder.ConvertType(localVarTypes[name]); |
|
|
|
|
astLocalVar.Variables = new[] { new Ast.VariableInitializer(name, arg1) }; |
|
|
|
|
localVarDefined[name] = true; |
|
|
|
|
return astLocalVar; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), arg1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
case Code.Stobj: throw new NotImplementedException(); |
|
|
|
|
case Code.Switch: throw new NotImplementedException(); |
|
|
|
|
case Code.Tail: throw new NotImplementedException(); |
|
|
|
|
case Code.Throw: return new Ast.ThrowStatement(arg1); |
|
|
|
|
case Code.Unaligned: throw new NotImplementedException(); |
|
|
|
|
case Code.Unbox: throw new NotImplementedException(); |
|
|
|
|
case Code.Unbox_Any: throw new NotImplementedException(); |
|
|
|
|
case Code.Volatile: throw new NotImplementedException(); |
|
|
|
|
default: throw new Exception("Unknown OpCode: " + opCode); |
|
|
|
|
case Code.Stobj: throw new NotImplementedException(); |
|
|
|
|
case Code.Switch: throw new NotImplementedException(); |
|
|
|
|
case Code.Tail: throw new NotImplementedException(); |
|
|
|
|
case Code.Throw: return new Ast.ThrowStatement { Expression = arg1 }; |
|
|
|
|
case Code.Unaligned: throw new NotImplementedException(); |
|
|
|
|
case Code.Unbox: throw new NotImplementedException(); |
|
|
|
|
case Code.Unbox_Any: throw new NotImplementedException(); |
|
|
|
|
case Code.Volatile: throw new NotImplementedException(); |
|
|
|
|
default: throw new Exception("Unknown OpCode: " + opCode); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|