|
|
|
@ -79,9 +79,7 @@ namespace ICSharpCode.Decompiler.Ast
@@ -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
@@ -154,41 +152,6 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<Ast.Expression> TransformExpressionArguments(ILExpression expr) |
|
|
|
|
{ |
|
|
|
|
List<Ast.Expression> args = new List<Ast.Expression>(); |
|
|
|
|
// 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,7 +167,10 @@ namespace ICSharpCode.Decompiler.Ast
@@ -204,7 +167,10 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
object operand = byteCode.Operand; |
|
|
|
|
AstType operandAsTypeRef = AstBuilder.ConvertType(operand as Cecil.TypeReference); |
|
|
|
|
|
|
|
|
|
List<Ast.Expression> args = TransformExpressionArguments(byteCode); |
|
|
|
|
List<Ast.Expression> args = new List<Expression>(); |
|
|
|
|
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; |
|
|
|
@ -230,14 +196,12 @@ namespace ICSharpCode.Decompiler.Ast
@@ -230,14 +196,12 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
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: |
|
|
|
|
{ |
|
|
|
|
case ILCode.InitArray: { |
|
|
|
|
var ace = new Ast.ArrayCreateExpression(); |
|
|
|
|
ace.Type = operandAsTypeRef; |
|
|
|
|
ComposedType ct = operandAsTypeRef as ComposedType; |
|
|
|
@ -253,8 +217,7 @@ namespace ICSharpCode.Decompiler.Ast
@@ -253,8 +217,7 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
} |
|
|
|
|
return ace; |
|
|
|
|
} |
|
|
|
|
case ILCode.Ldlen: |
|
|
|
|
return arg1.Member("Length"); |
|
|
|
|
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
@@ -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: |
|
|
|
@ -283,23 +244,18 @@ namespace ICSharpCode.Decompiler.Ast
@@ -283,23 +244,18 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
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: |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
@ -334,7 +290,6 @@ namespace ICSharpCode.Decompiler.Ast
@@ -334,7 +290,6 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
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: |
|
|
|
@ -356,16 +311,11 @@ namespace ICSharpCode.Decompiler.Ast
@@ -356,16 +311,11 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
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); |
|
|
|
|
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: |
|
|
|
@ -384,7 +334,6 @@ namespace ICSharpCode.Decompiler.Ast
@@ -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: |
|
|
|
@ -401,12 +350,9 @@ namespace ICSharpCode.Decompiler.Ast
@@ -401,12 +350,9 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
#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: |
|
|
|
|
{ |
|
|
|
|
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)); |
|
|
|
@ -414,8 +360,7 @@ namespace ICSharpCode.Decompiler.Ast
@@ -414,8 +360,7 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
return new IdentifierExpression("ldftn").Invoke(expr) |
|
|
|
|
.WithAnnotation(new Transforms.DelegateConstruction.Annotation(false)); |
|
|
|
|
} |
|
|
|
|
case ILCode.Ldvirtftn: |
|
|
|
|
{ |
|
|
|
|
case ILCode.Ldvirtftn: { |
|
|
|
|
Cecil.MethodReference cecilMethod = ((MethodReference)operand); |
|
|
|
|
var expr = new Ast.IdentifierExpression(cecilMethod.Name); |
|
|
|
|
expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod)); |
|
|
|
@ -423,7 +368,6 @@ namespace ICSharpCode.Decompiler.Ast
@@ -423,7 +368,6 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
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); |
|
|
|
@ -438,9 +382,8 @@ namespace ICSharpCode.Decompiler.Ast
@@ -438,9 +382,8 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
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
@@ -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
@@ -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,10 +436,8 @@ namespace ICSharpCode.Decompiler.Ast
@@ -494,10 +436,8 @@ 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"); |
|
|
|
@ -507,10 +447,8 @@ namespace ICSharpCode.Decompiler.Ast
@@ -507,10 +447,8 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
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: |
|
|
|
|
{ |
|
|
|
|
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) { |
|
|
|
@ -533,18 +471,15 @@ namespace ICSharpCode.Decompiler.Ast
@@ -533,18 +471,15 @@ namespace ICSharpCode.Decompiler.Ast
|
|
|
|
|
case ILCode.Readonly: return InlineAssembly(byteCode, args); |
|
|
|
|
case ILCode.Refanytype: return InlineAssembly(byteCode, args); |
|
|
|
|
case ILCode.Refanyval: return InlineAssembly(byteCode, args); |
|
|
|
|
case ILCode.Ret: { |
|
|
|
|
case ILCode.Ret: |
|
|
|
|
if (methodDef.ReturnType.FullName != "System.Void") { |
|
|
|
|
return new Ast.ReturnStatement { Expression = arg1 }; |
|
|
|
|
} else { |
|
|
|
|
return new Ast.ReturnStatement(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
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.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); |
|
|
|
@ -707,6 +642,31 @@ namespace ICSharpCode.Decompiler.Ast
@@ -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<AstType> ConvertTypeArguments(MethodReference cecilMethod) |
|
|
|
|
{ |
|
|
|
|
GenericInstanceMethod g = cecilMethod as GenericInstanceMethod; |
|
|
|
|