diff --git a/src/AstMetodBodyBuilder.cs b/src/AstMetodBodyBuilder.cs index 47ece438e..0b6791973 100644 --- a/src/AstMetodBodyBuilder.cs +++ b/src/AstMetodBodyBuilder.cs @@ -31,6 +31,14 @@ namespace Decompiler Ast.Statement astStatement = null; try { + object type = null; + try { + type = GetType(methodDef, instr); + if (type is Cecil.TypeReference) { + type = ((Cecil.TypeReference)type).FullName; + } + } catch (NotImplementedException) { + } object codeExpr = MakeCodeDomExpression( methodDef, instr, @@ -39,13 +47,14 @@ namespace Decompiler new Ast.IdentifierExpression("arg3")); if (codeExpr is Ast.Expression) { if (GetNumberOfOutputs(methodDef, instr) == 1) { - codeExpr = new Ast.AssignmentExpression( - new Ast.IdentifierExpression(string.Format("expr{0:X2}", instr.Offset)), - AssignmentOperatorType.Assign, - (Ast.Expression)codeExpr - ); + type = type ?? "object"; + string name = string.Format("expr{0:X2}", instr.Offset); + Ast.LocalVariableDeclaration astLocal = new Ast.LocalVariableDeclaration(new Ast.TypeReference(type.ToString())); + astLocal.Variables.Add(new Ast.VariableDeclaration(name, (Ast.Expression)codeExpr)); + astStatement = astLocal; + } else { + astStatement = new ExpressionStatement((Ast.Expression)codeExpr); } - astStatement = new ExpressionStatement((Ast.Expression)codeExpr); } else if (codeExpr is Ast.Statement) { astStatement = (Ast.Statement)codeExpr; } @@ -333,5 +342,216 @@ namespace Decompiler default: throw new Exception("Unknown OpCode: " + opCode); } } + + static object GetType(MethodDefinition methodDef, Instruction inst, params Cecil.TypeReference[] args) + { + OpCode opCode = inst.OpCode; + object operand = inst.Operand; + Ast.TypeReference operandAsTypeRef = operand is Cecil.TypeReference ? new Ast.TypeReference(((Cecil.TypeReference)operand).FullName) : null; + Instruction operandAsInstruction = operand is Instruction ? (Instruction)operand : null; + string operandAsInstructionLabel = operand is Instruction ? String.Format("IL_{0:X2}", ((Instruction)operand).Offset) : null; + Cecil.TypeReference arg1 = args.Length >= 1 ? args[0] : null; + Cecil.TypeReference arg2 = args.Length >= 2 ? args[1] : null; + Cecil.TypeReference arg3 = args.Length >= 3 ? args[2] : null; + + switch(opCode.Code) { + #region Arithmetic + case Code.Add: + case Code.Add_Ovf: + case Code.Add_Ovf_Un: + case Code.Div: + case Code.Div_Un: + case Code.Mul: + case Code.Mul_Ovf: + case Code.Mul_Ovf_Un: + case Code.Rem: + case Code.Rem_Un: + case Code.Sub: + case Code.Sub_Ovf: + case Code.Sub_Ovf_Un: + case Code.And: + case Code.Xor: + case Code.Shl: + case Code.Shr: + case Code.Shr_Un: return Cecil.Constants.Int32; + + case Code.Neg: return Cecil.Constants.Int32; + case Code.Not: return Cecil.Constants.Boolean; + #endregion + #region Arrays + case Code.Newarr: throw new NotImplementedException(); + + case Code.Ldlen: return Cecil.Constants.Int32; + + case Code.Ldelem_I: + case Code.Ldelem_I1: + case Code.Ldelem_I2: + case Code.Ldelem_I4: + case Code.Ldelem_I8: return Cecil.Constants.Int32; + case Code.Ldelem_U1: + case Code.Ldelem_U2: + case Code.Ldelem_U4: + case Code.Ldelem_R4: + case Code.Ldelem_R8: + case Code.Ldelem_Ref: + case Code.Ldelem_Any: + case Code.Ldelema: throw new NotImplementedException(); + + 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: + case Code.Stelem_Any: return null; + #endregion + #region Branching + case Code.Br: + case Code.Brfalse: + case Code.Brtrue: + case Code.Beq: + case Code.Bge: + case Code.Bge_Un: + case Code.Bgt: + case Code.Bgt_Un: + case Code.Ble: + case Code.Ble_Un: + case Code.Blt: + case Code.Blt_Un: + case Code.Bne_Un: return null; + #endregion + #region Comparison + case Code.Ceq: + case Code.Cgt: + case Code.Cgt_Un: + case Code.Clt: + case Code.Clt_Un: return Cecil.Constants.Boolean; + #endregion + #region Conversions + case Code.Conv_I: + case Code.Conv_I1: + case Code.Conv_I2: + case Code.Conv_I4: + case Code.Conv_I8: + case Code.Conv_U: + case Code.Conv_U1: + case Code.Conv_U2: + case Code.Conv_U4: + case Code.Conv_U8: + case Code.Conv_R4: + case Code.Conv_R8: + case Code.Conv_R_Un: + + case Code.Conv_Ovf_I: + case Code.Conv_Ovf_I1: + case Code.Conv_Ovf_I2: + case Code.Conv_Ovf_I4: + case Code.Conv_Ovf_I8: + case Code.Conv_Ovf_U: + case Code.Conv_Ovf_U1: + case Code.Conv_Ovf_U2: + case Code.Conv_Ovf_U4: + case Code.Conv_Ovf_U8: + + case Code.Conv_Ovf_I_Un: + case Code.Conv_Ovf_I1_Un: + case Code.Conv_Ovf_I2_Un: + case Code.Conv_Ovf_I4_Un: + case Code.Conv_Ovf_I8_Un: + case Code.Conv_Ovf_U_Un: + case Code.Conv_Ovf_U1_Un: + case Code.Conv_Ovf_U2_Un: + case Code.Conv_Ovf_U4_Un: + case Code.Conv_Ovf_U8_Un: return Constants.Int32; + #endregion + #region Indirect + case Code.Ldind_I: throw new NotImplementedException(); + case Code.Ldind_I1: throw new NotImplementedException(); + case Code.Ldind_I2: throw new NotImplementedException(); + case Code.Ldind_I4: throw new NotImplementedException(); + case Code.Ldind_I8: throw new NotImplementedException(); + case Code.Ldind_U1: throw new NotImplementedException(); + case Code.Ldind_U2: throw new NotImplementedException(); + case Code.Ldind_U4: throw new NotImplementedException(); + case Code.Ldind_R4: throw new NotImplementedException(); + case Code.Ldind_R8: throw new NotImplementedException(); + case Code.Ldind_Ref: throw new NotImplementedException(); + + case Code.Stind_I: throw new NotImplementedException(); + case Code.Stind_I1: throw new NotImplementedException(); + case Code.Stind_I2: throw new NotImplementedException(); + case Code.Stind_I4: throw new NotImplementedException(); + case Code.Stind_I8: throw new NotImplementedException(); + 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(); + case Code.Call: return ((MethodReference)operand).ReturnType.ReturnType; + case Code.Calli: throw new NotImplementedException(); + case Code.Callvirt: throw new NotImplementedException(); + case Code.Castclass: throw new NotImplementedException(); + 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: throw new NotImplementedException(); + case Code.Endfilter: throw new NotImplementedException(); + case Code.Endfinally: throw new NotImplementedException(); + case Code.Initblk: throw new NotImplementedException(); + case Code.Initobj: throw new NotImplementedException(); + case Code.Isinst: throw new NotImplementedException(); + case Code.Jmp: throw new NotImplementedException(); + case Code.Ldarg: return ((ParameterDefinition)operand).ParameterType; + case Code.Ldarga: throw new NotImplementedException(); + case Code.Ldc_I4: return Cecil.Constants.Int16; + case Code.Ldc_I8: return Cecil.Constants.Int64; + case Code.Ldc_R4: return Cecil.Constants.Single; + case Code.Ldc_R8: return Cecil.Constants.Double; + case Code.Ldfld: throw new NotImplementedException(); + case Code.Ldflda: throw new NotImplementedException(); + case Code.Ldftn: throw new NotImplementedException(); + case Code.Ldloc: return ((VariableDefinition)operand).VariableType; + case Code.Ldloca: throw new NotImplementedException(); + case Code.Ldnull: return Cecil.Constants.Object; + case Code.Ldobj: throw new NotImplementedException(); + case Code.Ldsfld: throw new NotImplementedException(); + case Code.Ldsflda: throw new NotImplementedException(); + case Code.Ldstr: return Cecil.Constants.String; + case Code.Ldtoken: throw new NotImplementedException(); + case Code.Ldvirtftn: throw new NotImplementedException(); + case Code.Leave: throw new NotImplementedException(); + case Code.Localloc: throw new NotImplementedException(); + case Code.Mkrefany: throw new NotImplementedException(); + case Code.Newobj: throw new NotImplementedException(); + case Code.No: throw new NotImplementedException(); + case Code.Nop: return null; + case Code.Or: throw new NotImplementedException(); + case Code.Pop: throw new NotImplementedException(); + case Code.Readonly: throw new NotImplementedException(); + case Code.Refanytype: throw new NotImplementedException(); + case Code.Refanyval: throw new NotImplementedException(); + case Code.Ret: return null; + case Code.Rethrow: throw new NotImplementedException(); + case Code.Sizeof: throw new NotImplementedException(); + case Code.Starg: throw new NotImplementedException(); + case Code.Stfld: throw new NotImplementedException(); + case Code.Stloc: return null; + case Code.Stobj: throw new NotImplementedException(); + case Code.Stsfld: throw new NotImplementedException(); + case Code.Switch: throw new NotImplementedException(); + case Code.Tail: throw new NotImplementedException(); + case Code.Throw: throw new NotImplementedException(); + 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); + } + } } }