diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index 143789f36..75c6ad1cd 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -79,9 +79,7 @@ namespace ICSharpCode.Decompiler.Ast { Ast.BlockStatement astBlock = new BlockStatement(); if (block != null) { - if (block.EntryGoto != null) - astBlock.Add((Statement)TransformExpression(block.EntryGoto)); - foreach(ILNode node in block.Body) { + foreach(ILNode node in block.GetChildren()) { astBlock.AddRange(TransformNode(node)); } } @@ -154,41 +152,6 @@ namespace ICSharpCode.Decompiler.Ast } } - List TransformExpressionArguments(ILExpression expr) - { - List args = new List(); - // Args generated by nested expressions (which must be closed) - foreach(ILExpression arg in expr.Arguments) { - args.Add((Ast.Expression)TransformExpression(arg)); - } - return args; - } - - static string FormatByteCodeOperand(object operand) - { - if (operand == null) { - return string.Empty; - //} 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) { - return ((Cecil.TypeReference)operand).FullName; - } else if (operand is VariableDefinition) { - return ((VariableDefinition)operand).Name; - } else if (operand is ParameterDefinition) { - return ((ParameterDefinition)operand).Name; - } else if (operand is FieldReference) { - return ((FieldReference)operand).Name; - } else if (operand is string) { - return "\"" + operand + "\""; - } else if (operand is int) { - return operand.ToString(); - } else { - return operand.ToString(); - } - } - AstNode TransformExpression(ILExpression expr) { AstNode node = TransformByteCode(expr); @@ -204,57 +167,57 @@ namespace ICSharpCode.Decompiler.Ast object operand = byteCode.Operand; AstType operandAsTypeRef = AstBuilder.ConvertType(operand as Cecil.TypeReference); - List args = TransformExpressionArguments(byteCode); + List args = new List(); + foreach(ILExpression arg in byteCode.Arguments) { + args.Add((Ast.Expression)TransformExpression(arg)); + } Ast.Expression arg1 = args.Count >= 1 ? args[0] : null; Ast.Expression arg2 = args.Count >= 2 ? args[1] : null; Ast.Expression arg3 = args.Count >= 3 ? args[2] : null; switch(byteCode.Code) { - #region Arithmetic - case ILCode.Add: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); - case ILCode.Add_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); - case ILCode.Add_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); - case ILCode.Div: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); - case ILCode.Div_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); - case ILCode.Mul: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2); - case ILCode.Mul_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2); - case ILCode.Mul_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2); - case ILCode.Rem: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); - case ILCode.Rem_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); - case ILCode.Sub: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); - case ILCode.Sub_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); - case ILCode.Sub_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); - case ILCode.And: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2); - case ILCode.Or: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2); - case ILCode.Xor: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2); - case ILCode.Shl: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2); - case ILCode.Shr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); - case ILCode.Shr_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); - - case ILCode.Neg: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Minus, arg1); - case ILCode.Not: return new Ast.UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1); - #endregion - #region Arrays + #region Arithmetic + case ILCode.Add: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); + case ILCode.Add_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); + case ILCode.Add_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); + case ILCode.Div: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); + case ILCode.Div_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); + case ILCode.Mul: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2); + case ILCode.Mul_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2); + case ILCode.Mul_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2); + case ILCode.Rem: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); + case ILCode.Rem_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); + case ILCode.Sub: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); + case ILCode.Sub_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); + case ILCode.Sub_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); + case ILCode.And: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2); + case ILCode.Or: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2); + case ILCode.Xor: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2); + case ILCode.Shl: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2); + case ILCode.Shr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); + case ILCode.Shr_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); + case ILCode.Neg: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Minus, arg1); + case ILCode.Not: return new Ast.UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1); + #endregion + #region Arrays case ILCode.Newarr: - case ILCode.InitArray: - { - var ace = new Ast.ArrayCreateExpression(); - ace.Type = operandAsTypeRef; - ComposedType ct = operandAsTypeRef as ComposedType; - if (ct != null) { - // change "new (int[,])[10] to new int[10][,]" - ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); - } - if (byteCode.Code == ILCode.InitArray) { - ace.Initializer = new ArrayInitializerExpression(); - ace.Initializer.Elements.AddRange(args); - } else { - ace.Arguments.Add(arg1); - } - return ace; + case ILCode.InitArray: { + var ace = new Ast.ArrayCreateExpression(); + ace.Type = operandAsTypeRef; + ComposedType ct = operandAsTypeRef as ComposedType; + if (ct != null) { + // change "new (int[,])[10] to new int[10][,]" + ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); } - case ILCode.Ldlen: - return arg1.Member("Length"); + if (byteCode.Code == ILCode.InitArray) { + ace.Initializer = new ArrayInitializerExpression(); + ace.Initializer.Elements.AddRange(args); + } else { + ace.Arguments.Add(arg1); + } + return ace; + } + case ILCode.Ldlen: return arg1.Member("Length"); case ILCode.Ldelem_I: case ILCode.Ldelem_I1: case ILCode.Ldelem_I2: @@ -268,9 +231,7 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Ldelem_Ref: case ILCode.Ldelem_Any: return arg1.Indexer(arg2); - case ILCode.Ldelema: - return MakeRef(arg1.Indexer(arg2)); - + case ILCode.Ldelema: return MakeRef(arg1.Indexer(arg2)); case ILCode.Stelem_I: case ILCode.Stelem_I1: case ILCode.Stelem_I2: @@ -281,33 +242,28 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Stelem_Ref: case ILCode.Stelem_Any: return new Ast.AssignmentExpression(arg1.Indexer(arg2), arg3); - #endregion - #region Comparison - case ILCode.Ceq: - return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2); - case ILCode.Cgt: - return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); - case ILCode.Cgt_Un: + #endregion + #region Comparison + case ILCode.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2); + case ILCode.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); + case ILCode.Cgt_Un: { // can also mean Inequality, when used with object references - { - TypeReference arg1Type = byteCode.Arguments[0].InferredType; - if (arg1Type != null && !arg1Type.IsValueType) - return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2); - else - return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); - } - case ILCode.Clt: - return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); - case ILCode.Clt_Un: - return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); - #endregion - #region Logical + TypeReference arg1Type = byteCode.Arguments[0].InferredType; + if (arg1Type != null && !arg1Type.IsValueType) + return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2); + else + return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); + } + case ILCode.Clt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); + case ILCode.Clt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); + #endregion + #region Logical case ILCode.LogicNot: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1); case ILCode.LogicAnd: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2); case ILCode.LogicOr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2); case ILCode.TernaryOp: return new Ast.ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 }; - #endregion - #region Branch + #endregion + #region Branch case ILCode.Br: return new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name); case ILCode.Brtrue: return new Ast.IfElseStatement() { @@ -316,10 +272,10 @@ namespace ICSharpCode.Decompiler.Ast new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name) } }; - case ILCode.LoopOrSwitchBreak: return new Ast.BreakStatement(); - case ILCode.LoopContinue: return new Ast.ContinueStatement(); - #endregion - #region Conversions + case ILCode.LoopOrSwitchBreak: return new Ast.BreakStatement(); + case ILCode.LoopContinue: return new Ast.ContinueStatement(); + #endregion + #region Conversions case ILCode.Conv_I1: case ILCode.Conv_I2: case ILCode.Conv_I4: @@ -329,12 +285,11 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Conv_U4: case ILCode.Conv_U8: return arg1; // conversion is handled by Convert() function using the info from type analysis - case ILCode.Conv_I: return arg1.CastTo(typeof(IntPtr)); // TODO - case ILCode.Conv_U: return arg1.CastTo(typeof(UIntPtr)); // TODO - case ILCode.Conv_R4: return arg1.CastTo(typeof(float)); - case ILCode.Conv_R8: return arg1.CastTo(typeof(double)); - case ILCode.Conv_R_Un: return arg1.CastTo(typeof(double)); // TODO - + case ILCode.Conv_I: return arg1.CastTo(typeof(IntPtr)); // TODO + case ILCode.Conv_U: return arg1.CastTo(typeof(UIntPtr)); // TODO + case ILCode.Conv_R4: return arg1.CastTo(typeof(float)); + case ILCode.Conv_R8: return arg1.CastTo(typeof(double)); + case ILCode.Conv_R_Un: return arg1.CastTo(typeof(double)); // TODO case ILCode.Conv_Ovf_I1: case ILCode.Conv_Ovf_I2: case ILCode.Conv_Ovf_I4: @@ -352,22 +307,17 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Conv_Ovf_U4_Un: case ILCode.Conv_Ovf_U8_Un: return arg1; // conversion was handled by Convert() function using the info from type analysis - case ILCode.Conv_Ovf_I: return arg1.CastTo(typeof(IntPtr)); // TODO - case ILCode.Conv_Ovf_U: return arg1.CastTo(typeof(UIntPtr)); - case ILCode.Conv_Ovf_I_Un: return arg1.CastTo(typeof(IntPtr)); - case ILCode.Conv_Ovf_U_Un: return arg1.CastTo(typeof(UIntPtr)); - - case ILCode.Castclass: - case ILCode.Unbox_Any: - return arg1.CastTo(operandAsTypeRef); - case ILCode.Isinst: - return arg1.CastAs(operandAsTypeRef); - case ILCode.Box: - return arg1; - case ILCode.Unbox: - return InlineAssembly(byteCode, args); - #endregion - #region Indirect + case ILCode.Conv_Ovf_I: return arg1.CastTo(typeof(IntPtr)); // TODO + case ILCode.Conv_Ovf_U: return arg1.CastTo(typeof(UIntPtr)); + case ILCode.Conv_Ovf_I_Un: return arg1.CastTo(typeof(IntPtr)); + case ILCode.Conv_Ovf_U_Un: return arg1.CastTo(typeof(UIntPtr)); + case ILCode.Castclass: return arg1.CastTo(operandAsTypeRef); + case ILCode.Unbox_Any: return arg1.CastTo(operandAsTypeRef); + case ILCode.Isinst: return arg1.CastAs(operandAsTypeRef); + case ILCode.Box: return arg1; + case ILCode.Unbox: return InlineAssembly(byteCode, args); + #endregion + #region Indirect case ILCode.Ldind_I: case ILCode.Ldind_I1: case ILCode.Ldind_I2: @@ -384,7 +334,6 @@ namespace ICSharpCode.Decompiler.Ast return ((DirectionExpression)args[0]).Expression.Detach(); else return InlineAssembly(byteCode, args); - case ILCode.Stind_I: case ILCode.Stind_I1: case ILCode.Stind_I2: @@ -398,49 +347,43 @@ namespace ICSharpCode.Decompiler.Ast return new AssignmentExpression(((DirectionExpression)args[0]).Expression.Detach(), args[1]); else return InlineAssembly(byteCode, args); - #endregion - case ILCode.Arglist: return InlineAssembly(byteCode, args); - case ILCode.Break: return InlineAssembly(byteCode, args); - case ILCode.Call: - return TransformCall(false, operand, methodDef, args); - case ILCode.Callvirt: - return TransformCall(true, operand, methodDef, args); - case ILCode.Ldftn: - { - Cecil.MethodReference cecilMethod = ((MethodReference)operand); - var expr = new Ast.IdentifierExpression(cecilMethod.Name); - expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod)); - expr.AddAnnotation(cecilMethod); - return new IdentifierExpression("ldftn").Invoke(expr) - .WithAnnotation(new Transforms.DelegateConstruction.Annotation(false)); - } - case ILCode.Ldvirtftn: - { - Cecil.MethodReference cecilMethod = ((MethodReference)operand); - var expr = new Ast.IdentifierExpression(cecilMethod.Name); - expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod)); - expr.AddAnnotation(cecilMethod); - return new IdentifierExpression("ldvirtftn").Invoke(expr) - .WithAnnotation(new Transforms.DelegateConstruction.Annotation(true)); - } - - case ILCode.Calli: return InlineAssembly(byteCode, args); - case ILCode.Ckfinite: return InlineAssembly(byteCode, args); - case ILCode.Constrained: return InlineAssembly(byteCode, args); - case ILCode.Cpblk: return InlineAssembly(byteCode, args); - case ILCode.Cpobj: return InlineAssembly(byteCode, args); - case ILCode.Dup: return arg1; - case ILCode.Endfilter: return InlineAssembly(byteCode, args); - case ILCode.Endfinally: return null; - case ILCode.Initblk: return InlineAssembly(byteCode, args); + #endregion + case ILCode.Arglist: return InlineAssembly(byteCode, args); + case ILCode.Break: return InlineAssembly(byteCode, args); + case ILCode.Call: return TransformCall(false, operand, methodDef, args); + case ILCode.Callvirt: return TransformCall(true, operand, methodDef, args); + case ILCode.Ldftn: { + Cecil.MethodReference cecilMethod = ((MethodReference)operand); + var expr = new Ast.IdentifierExpression(cecilMethod.Name); + expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod)); + expr.AddAnnotation(cecilMethod); + return new IdentifierExpression("ldftn").Invoke(expr) + .WithAnnotation(new Transforms.DelegateConstruction.Annotation(false)); + } + case ILCode.Ldvirtftn: { + Cecil.MethodReference cecilMethod = ((MethodReference)operand); + var expr = new Ast.IdentifierExpression(cecilMethod.Name); + expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod)); + expr.AddAnnotation(cecilMethod); + return new IdentifierExpression("ldvirtftn").Invoke(expr) + .WithAnnotation(new Transforms.DelegateConstruction.Annotation(true)); + } + case ILCode.Calli: return InlineAssembly(byteCode, args); + case ILCode.Ckfinite: return InlineAssembly(byteCode, args); + case ILCode.Constrained: return InlineAssembly(byteCode, args); + case ILCode.Cpblk: return InlineAssembly(byteCode, args); + case ILCode.Cpobj: return InlineAssembly(byteCode, args); + case ILCode.Dup: return arg1; + case ILCode.Endfilter: return InlineAssembly(byteCode, args); + case ILCode.Endfinally: return null; + case ILCode.Initblk: return InlineAssembly(byteCode, args); case ILCode.Initobj: if (args[0] is DirectionExpression) return new AssignmentExpression(((DirectionExpression)args[0]).Expression.Detach(), new DefaultValueExpression { Type = operandAsTypeRef }); else return InlineAssembly(byteCode, args); - case ILCode.Jmp: - return InlineAssembly(byteCode, args); - case ILCode.Ldarg: + case ILCode.Jmp: return InlineAssembly(byteCode, args); + case ILCode.Ldarg: { if (methodDef.HasThis && ((ParameterDefinition)operand).Index < 0) { if (context.CurrentMethod.DeclaringType.IsValueType) return MakeRef(new Ast.ThisReferenceExpression()); @@ -453,14 +396,14 @@ namespace ICSharpCode.Decompiler.Ast else return expr; } + } case ILCode.Ldarga: if (methodDef.HasThis && ((ParameterDefinition)operand).Index < 0) { return MakeRef(new Ast.ThisReferenceExpression()); } else { return MakeRef(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand)); } - case ILCode.Ldc_I4: - return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType); + case ILCode.Ldc_I4: return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType); case ILCode.Ldc_I8: case ILCode.Ldc_R4: case ILCode.Ldc_R8: @@ -482,8 +425,7 @@ namespace ICSharpCode.Decompiler.Ast AstBuilder.ConvertType(((FieldReference)operand).DeclaringType) .Member(((FieldReference)operand).Name).WithAnnotation(operand), arg1); - case ILCode.Ldflda: - return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand)); + case ILCode.Ldflda: return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand)); case ILCode.Ldsflda: return MakeRef( AstBuilder.ConvertType(((FieldReference)operand).DeclaringType) @@ -494,68 +436,61 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Ldloca: localVariablesToDefine.Add((ILVariable)operand); return MakeRef(new Ast.IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand)); - case ILCode.Ldnull: - return new Ast.NullReferenceExpression(); - case ILCode.Ldstr: - return new Ast.PrimitiveExpression(operand); + case ILCode.Ldnull: return new Ast.NullReferenceExpression(); + case ILCode.Ldstr: return new Ast.PrimitiveExpression(operand); case ILCode.Ldtoken: if (operand is Cecil.TypeReference) { return new Ast.TypeOfExpression { Type = operandAsTypeRef }.Member("TypeHandle"); } else { return InlineAssembly(byteCode, args); } - case ILCode.Leave: return new GotoStatement() { Label = ((ILLabel)operand).Name }; - case ILCode.Localloc: return InlineAssembly(byteCode, args); - case ILCode.Mkrefany: return InlineAssembly(byteCode, args); - case ILCode.Newobj: - { - Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType; - - if (declaringType is ArrayType) { - ComposedType ct = AstBuilder.ConvertType((ArrayType)declaringType) as ComposedType; - if (ct != null && ct.ArraySpecifiers.Count >= 1) { - var ace = new Ast.ArrayCreateExpression(); - ct.ArraySpecifiers.First().Remove(); - ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); - ace.Type = ct; - ace.Arguments.AddRange(args); - return ace; - } - } - var oce = new Ast.ObjectCreateExpression(); - oce.Type = AstBuilder.ConvertType(declaringType); - oce.Arguments.AddRange(args); - return oce.WithAnnotation(operand); - } - case ILCode.No: return InlineAssembly(byteCode, args); - case ILCode.Nop: return null; - case ILCode.Pop: return arg1; - case ILCode.Readonly: return InlineAssembly(byteCode, args); - case ILCode.Refanytype: return InlineAssembly(byteCode, args); - case ILCode.Refanyval: return InlineAssembly(byteCode, args); - case ILCode.Ret: { - if (methodDef.ReturnType.FullName != "System.Void") { - return new Ast.ReturnStatement { Expression = arg1 }; - } else { - return new Ast.ReturnStatement(); + case ILCode.Leave: return new GotoStatement() { Label = ((ILLabel)operand).Name }; + case ILCode.Localloc: return InlineAssembly(byteCode, args); + case ILCode.Mkrefany: return InlineAssembly(byteCode, args); + case ILCode.Newobj: { + Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType; + if (declaringType is ArrayType) { + ComposedType ct = AstBuilder.ConvertType((ArrayType)declaringType) as ComposedType; + if (ct != null && ct.ArraySpecifiers.Count >= 1) { + var ace = new Ast.ArrayCreateExpression(); + ct.ArraySpecifiers.First().Remove(); + ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); + ace.Type = ct; + ace.Arguments.AddRange(args); + return ace; } } - case ILCode.Rethrow: return new Ast.ThrowStatement(); - case ILCode.Sizeof: - return new Ast.SizeOfExpression { Type = operandAsTypeRef }; - case ILCode.Starg: - return new Ast.AssignmentExpression(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand), arg1); - case ILCode.Stloc: { - ILVariable locVar = (ILVariable)operand; - localVariablesToDefine.Add(locVar); - return new Ast.AssignmentExpression(new Ast.IdentifierExpression(locVar.Name).WithAnnotation(locVar), arg1); + var oce = new Ast.ObjectCreateExpression(); + oce.Type = AstBuilder.ConvertType(declaringType); + oce.Arguments.AddRange(args); + return oce.WithAnnotation(operand); + } + case ILCode.No: return InlineAssembly(byteCode, args); + case ILCode.Nop: return null; + case ILCode.Pop: return arg1; + case ILCode.Readonly: return InlineAssembly(byteCode, args); + case ILCode.Refanytype: return InlineAssembly(byteCode, args); + case ILCode.Refanyval: return InlineAssembly(byteCode, args); + case ILCode.Ret: + if (methodDef.ReturnType.FullName != "System.Void") { + return new Ast.ReturnStatement { Expression = arg1 }; + } else { + return new Ast.ReturnStatement(); } - case ILCode.Switch: return InlineAssembly(byteCode, args); - case ILCode.Tail: return InlineAssembly(byteCode, args); - case ILCode.Throw: return new Ast.ThrowStatement { Expression = arg1 }; - case ILCode.Unaligned: return InlineAssembly(byteCode, args); - case ILCode.Volatile: return InlineAssembly(byteCode, args); - default: throw new Exception("Unknown OpCode: " + byteCode.Code); + case ILCode.Rethrow: return new Ast.ThrowStatement(); + case ILCode.Sizeof: return new Ast.SizeOfExpression { Type = operandAsTypeRef }; + case ILCode.Starg: return new Ast.AssignmentExpression(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand), arg1); + case ILCode.Stloc: { + ILVariable locVar = (ILVariable)operand; + localVariablesToDefine.Add(locVar); + return new Ast.AssignmentExpression(new Ast.IdentifierExpression(locVar.Name).WithAnnotation(locVar), arg1); + } + case ILCode.Switch: return InlineAssembly(byteCode, args); + case ILCode.Tail: return InlineAssembly(byteCode, args); + case ILCode.Throw: return new Ast.ThrowStatement { Expression = arg1 }; + case ILCode.Unaligned: return InlineAssembly(byteCode, args); + case ILCode.Volatile: return InlineAssembly(byteCode, args); + default: throw new Exception("Unknown OpCode: " + byteCode.Code); } } @@ -707,6 +642,31 @@ namespace ICSharpCode.Decompiler.Ast return new IdentifierExpression(byteCode.Code.GetName()).Invoke(args); } + static string FormatByteCodeOperand(object operand) + { + if (operand == null) { + return string.Empty; + //} 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) { + return ((Cecil.TypeReference)operand).FullName; + } else if (operand is VariableDefinition) { + return ((VariableDefinition)operand).Name; + } else if (operand is ParameterDefinition) { + return ((ParameterDefinition)operand).Name; + } else if (operand is FieldReference) { + return ((FieldReference)operand).Name; + } else if (operand is string) { + return "\"" + operand + "\""; + } else if (operand is int) { + return operand.ToString(); + } else { + return operand.ToString(); + } + } + static IEnumerable ConvertTypeArguments(MethodReference cecilMethod) { GenericInstanceMethod g = cecilMethod as GenericInstanceMethod;