internal static void ProcessInvocationExpression(InvocationExpression invocationExpression, StringBuilder sb) { IMethod methodRef = invocationExpression.Annotation <IMethod>(); if (methodRef == null) { return; } var arguments = invocationExpression.Arguments.ToArray(); // Reduce "String.Concat(a, b)" to "a + b" if (methodRef.Name == "Concat" && methodRef.DeclaringType != null && arguments.Length >= 2 && methodRef.DeclaringType.FullName == "System.String") { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression Expression expr = arguments[0]; for (int i = 1; i < arguments.Length; i++) { expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]); } invocationExpression.ReplaceWith(expr); expr.AddAnnotation(invocationExpression.GetAllRecursiveILRanges()); return; } bool isSupportedType = CheckType(methodRef.DeclaringType, systemString, typeString) || CheckType(methodRef.DeclaringType, systemReflectionString, fieldInfoString); switch (isSupportedType ? methodRef.Name.String : string.Empty) { case "GetTypeFromHandle": if (arguments.Length == 1 && methodRef.FullName == "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)") { if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) { invocationExpression.ReplaceWith(((MemberReferenceExpression)arguments[0]).Target .WithAnnotation(invocationExpression.GetAllRecursiveILRanges())); return; } } break; case "GetFieldFromHandle": if (arguments.Length == 1 && methodRef.FullName == "System.Reflection.FieldInfo System.Reflection.FieldInfo::GetFieldFromHandle(System.RuntimeFieldHandle)") { MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression; if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation <LdTokenAnnotation>() != null) { invocationExpression.ReplaceWith(mre.Target .WithAnnotation(invocationExpression.GetAllRecursiveILRanges())); return; } } else if (arguments.Length == 2 && methodRef.FullName == "System.Reflection.FieldInfo System.Reflection.FieldInfo::GetFieldFromHandle(System.RuntimeFieldHandle,System.RuntimeTypeHandle)") { MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression; MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression; if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation <LdTokenAnnotation>() != null) { if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) { Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single(); IField field = oldArg.Annotation <IField>(); if (field != null) { var ilRanges = invocationExpression.GetAllRecursiveILRanges(); AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach(); oldArg.ReplaceWith(declaringType.Member(field.Name, field).WithAnnotation(field)); invocationExpression.ReplaceWith(mre1.Target.WithAnnotation(ilRanges)); return; } } } } break; } BinaryOperatorType?bop = GetBinaryOperatorTypeFromMetadataName(methodRef.Name); if (bop != null && arguments.Length == 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression invocationExpression.ReplaceWith( new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).WithAnnotation(methodRef) .WithAnnotation(invocationExpression.GetAllRecursiveILRanges()) ); return; } UnaryOperatorType?uop = GetUnaryOperatorTypeFromMetadataName(methodRef.Name); if (uop != null && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( new UnaryOperatorExpression(uop.Value, arguments[0]).WithAnnotation(methodRef) .WithAnnotation(invocationExpression.GetAllRecursiveILRanges()) ); return; } if (methodRef.Name == "op_Explicit" && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( arguments[0].CastTo(AstBuilder.ConvertType(methodRef.MethodSig.GetRetType(), sb)) .WithAnnotation(methodRef) .WithAnnotation(invocationExpression.GetAllRecursiveILRanges()) ); return; } if (methodRef.Name == "op_Implicit" && arguments.Length == 1) { invocationExpression.ReplaceWith(arguments[0].WithAnnotation(invocationExpression.GetAllRecursiveILRanges())); return; } if (methodRef.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) { invocationExpression.ReplaceWith(arguments[0].WithAnnotation(invocationExpression.GetAllRecursiveILRanges())); return; } return; }
Expression ConvertBinaryOperator(InvocationExpression invocation, BinaryOperatorType op, bool? isChecked = null) { if (invocation.Arguments.Count < 2) return NotSupported(invocation); Expression left = Convert(invocation.Arguments.ElementAt(0)); if (left == null) return null; Expression right = Convert(invocation.Arguments.ElementAt(1)); if (right == null) return null; BinaryOperatorExpression boe = new BinaryOperatorExpression(left, op, right); if (isChecked != null) boe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); switch (invocation.Arguments.Count) { case 2: return boe; case 3: Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2)); if (m.Success) return boe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>()); else return null; case 4: if (!trueOrFalse.IsMatch(invocation.Arguments.ElementAt(2))) return null; m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(3)); if (m.Success) return boe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>()); else return null; default: return NotSupported(invocation); } }
Expression ConvertBinaryOperator(InvocationExpression invocation, BinaryOperatorType op, bool?isChecked = null) { if (invocation.Arguments.Count < 2) { return(NotSupported(invocation)); } Expression left = Convert(invocation.Arguments.ElementAt(0)); if (left == null) { return(null); } Expression right = Convert(invocation.Arguments.ElementAt(1)); if (right == null) { return(null); } BinaryOperatorExpression boe = new BinaryOperatorExpression(left, op, right); if (isChecked != null) { boe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); } switch (invocation.Arguments.Count) { case 2: return(boe); case 3: Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2)); if (m.Success) { return(boe.WithAnnotation(m.Get <AstNode>("method").Single().Annotation <IMethod>())); } else { return(null); } case 4: if (!trueOrFalse.IsMatch(invocation.Arguments.ElementAt(2))) { return(null); } m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(3)); if (m.Success) { return(boe.WithAnnotation(m.Get <AstNode>("method").Single().Annotation <IMethod>())); } else { return(null); } default: return(NotSupported(invocation)); } }
AstNode TransformByteCode(ILExpression byteCode) { object operand = byteCode.Operand; AstType operandAsTypeRef = AstBuilder.ConvertType(operand as ITypeDefOrRef); List<Expression> args = new List<Expression>(); foreach(ILExpression arg in byteCode.Arguments) { args.Add((Expression)TransformExpression(arg)); } Expression arg1 = args.Count >= 1 ? args[0] : null; Expression arg2 = args.Count >= 2 ? args[1] : null; Expression arg3 = args.Count >= 3 ? args[2] : null; switch (byteCode.Code) { #region Arithmetic case ILCode.Add: case ILCode.Add_Ovf: case ILCode.Add_Ovf_Un: { BinaryOperatorExpression boe; if (byteCode.InferredType is PtrSig) { boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); if (byteCode.Arguments[0].ExpectedType is PtrSig || byteCode.Arguments[1].ExpectedType is PtrSig) { boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation); } } else { boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); } boe.AddAnnotation(byteCode.Code == ILCode.Add ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); return boe; } case ILCode.Sub: case ILCode.Sub_Ovf: case ILCode.Sub_Ovf_Un: { BinaryOperatorExpression boe; if (byteCode.InferredType is PtrSig) { boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); if (byteCode.Arguments[0].ExpectedType is PtrSig) { boe.WithAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation); } } else { boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); } boe.AddAnnotation(byteCode.Code == ILCode.Sub ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); return boe; } case ILCode.Div: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); case ILCode.Div_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); case ILCode.Mul: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation); case ILCode.Mul_Ovf: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation); case ILCode.Mul_Ovf_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation); case ILCode.Rem: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); case ILCode.Rem_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); case ILCode.And: return new BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2); case ILCode.Or: return new BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2); case ILCode.Xor: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2); case ILCode.Shl: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2); case ILCode.Shr: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); case ILCode.Shr_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); case ILCode.Neg: return new UnaryOperatorExpression(UnaryOperatorType.Minus, arg1).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation); case ILCode.Not: return new UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1); case ILCode.PostIncrement: case ILCode.PostIncrement_Ovf: case ILCode.PostIncrement_Ovf_Un: { if (arg1 is DirectionExpression) arg1 = ((DirectionExpression)arg1).Expression.Detach(); var uoe = new UnaryOperatorExpression( (int)byteCode.Operand > 0 ? UnaryOperatorType.PostIncrement : UnaryOperatorType.PostDecrement, arg1); uoe.AddAnnotation((byteCode.Code == ILCode.PostIncrement) ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); return uoe; } #endregion #region Arrays case ILCode.Newarr: { var ace = new 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 ArrayCreateExpression(); ace.Type = operandAsTypeRef; ComposedType ct = operandAsTypeRef as ComposedType; var arrayType = (ArraySigBase)((ITypeDefOrRef)operand).ToTypeSig(); ; if (ct != null) { // change "new (int[,])[10] to new int[10][,]" ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); ace.Initializer = new ArrayInitializerExpression(); } var newArgs = new List<Expression>(); if (arrayType is ArraySig) { foreach (var size in arrayType.GetSizes().Skip(1).Reverse()) { int length = (int)size; for (int j = 0; j < args.Count; j += length) { var child = new ArrayInitializerExpression(); child.Elements.AddRange(args.GetRange(j, length)); newArgs.Add(child); } var temp = args; args = newArgs; newArgs = temp; newArgs.Clear(); } } ace.Initializer.Elements.AddRange(args); return ace; } case ILCode.Ldlen: return arg1.Member("Length").WithAnnotation(GetArrayLengthRef()); case ILCode.Ldelem_I: case ILCode.Ldelem_I1: case ILCode.Ldelem_I2: case ILCode.Ldelem_I4: case ILCode.Ldelem_I8: case ILCode.Ldelem_U1: case ILCode.Ldelem_U2: case ILCode.Ldelem_U4: case ILCode.Ldelem_R4: case ILCode.Ldelem_R8: case ILCode.Ldelem_Ref: case ILCode.Ldelem_Any: return arg1.Indexer(arg2); case ILCode.Ldelema: return MakeRef(arg1.Indexer(arg2)); case ILCode.Stelem_I: case ILCode.Stelem_I1: case ILCode.Stelem_I2: case ILCode.Stelem_I4: case ILCode.Stelem_I8: case ILCode.Stelem_R4: case ILCode.Stelem_R8: case ILCode.Stelem_Ref: case ILCode.Stelem_Any: return new AssignmentExpression(arg1.Indexer(arg2), arg3); case ILCode.CompoundAssignment: { CastExpression cast = arg1 as CastExpression; var boe = cast != null ? (BinaryOperatorExpression)cast.Expression : arg1 as BinaryOperatorExpression; // AssignmentExpression doesn't support overloaded operators so they have to be processed to BinaryOperatorExpression if (boe == null) { var tmp = new ParenthesizedExpression(arg1); ReplaceMethodCallsWithOperators.ProcessInvocationExpression((InvocationExpression)arg1); boe = (BinaryOperatorExpression)tmp.Expression; } var assignment = new AssignmentExpression { Left = boe.Left.Detach(), Operator = ReplaceMethodCallsWithOperators.GetAssignmentOperatorForBinaryOperator(boe.Operator), Right = boe.Right.Detach() }.CopyAnnotationsFrom(boe); // We do not mark the resulting assignment as RestoreOriginalAssignOperatorAnnotation, because // the operator cannot be translated back to the expanded form (as the left-hand expression // would be evaluated twice, and might have side-effects) if (cast != null) { cast.Expression = assignment; return cast; } else { return assignment; } } #endregion #region Comparison case ILCode.Ceq: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2); case ILCode.Cne: return new BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2); case ILCode.Cgt: return new BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); case ILCode.Cgt_Un: { // can also mean Inequality, when used with object references var arg1Type = byteCode.Arguments[0].InferredType; if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Cne; // when comparing signed integral values using Cgt_Un with 0 // the Ast should actually contain InEquality since "(uint)a > 0u" is identical to "a != 0" if (arg1Type.IsSignedIntegralType()) { var p = arg2 as PrimitiveExpression; if (p != null && p.Value.IsZero()) goto case ILCode.Cne; } goto case ILCode.Cgt; } case ILCode.Cle_Un: { // can also mean Equality, when used with object references var arg1Type = byteCode.Arguments[0].InferredType; if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Ceq; // when comparing signed integral values using Cle_Un with 0 // the Ast should actually contain Equality since "(uint)a <= 0u" is identical to "a == 0" if (arg1Type.IsSignedIntegralType()) { var p = arg2 as PrimitiveExpression; if (p != null && p.Value.IsZero()) goto case ILCode.Ceq; } goto case ILCode.Cle; } case ILCode.Cle: return new BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2); case ILCode.Cge_Un: case ILCode.Cge: return new BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2); case ILCode.Clt_Un: case ILCode.Clt: return new BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); #endregion #region Logical case ILCode.LogicNot: return new UnaryOperatorExpression(UnaryOperatorType.Not, arg1); case ILCode.LogicAnd: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2); case ILCode.LogicOr: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2); case ILCode.TernaryOp: return new ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 }; case ILCode.NullCoalescing: return new BinaryOperatorExpression(arg1, BinaryOperatorType.NullCoalescing, arg2); #endregion #region Branch case ILCode.Br: return new GotoStatement(((ILLabel)byteCode.Operand).Name); case ILCode.Brtrue: return new IfElseStatement() { Condition = arg1, TrueStatement = new BlockStatement() { new GotoStatement(((ILLabel)byteCode.Operand).Name) } }; case ILCode.LoopOrSwitchBreak: return new BreakStatement(); case ILCode.LoopContinue: return new ContinueStatement(); #endregion #region Conversions case ILCode.Conv_I1: case ILCode.Conv_I2: case ILCode.Conv_I4: case ILCode.Conv_I8: case ILCode.Conv_U1: case ILCode.Conv_U2: case ILCode.Conv_U4: case ILCode.Conv_U8: case ILCode.Conv_I: case ILCode.Conv_U: { // conversion was handled by Convert() function using the info from type analysis CastExpression cast = arg1 as CastExpression; if (cast != null) { cast.AddAnnotation(AddCheckedBlocks.UncheckedAnnotation); } return arg1; } case ILCode.Conv_R4: case ILCode.Conv_R8: case ILCode.Conv_R_Un: // TODO return arg1; case ILCode.Conv_Ovf_I1: case ILCode.Conv_Ovf_I2: case ILCode.Conv_Ovf_I4: case ILCode.Conv_Ovf_I8: case ILCode.Conv_Ovf_U1: case ILCode.Conv_Ovf_U2: case ILCode.Conv_Ovf_U4: case ILCode.Conv_Ovf_U8: case ILCode.Conv_Ovf_I1_Un: case ILCode.Conv_Ovf_I2_Un: case ILCode.Conv_Ovf_I4_Un: case ILCode.Conv_Ovf_I8_Un: case ILCode.Conv_Ovf_U1_Un: case ILCode.Conv_Ovf_U2_Un: case ILCode.Conv_Ovf_U4_Un: case ILCode.Conv_Ovf_U8_Un: case ILCode.Conv_Ovf_I: case ILCode.Conv_Ovf_U: case ILCode.Conv_Ovf_I_Un: case ILCode.Conv_Ovf_U_Un: { // conversion was handled by Convert() function using the info from type analysis CastExpression cast = arg1 as CastExpression; if (cast != null) { cast.AddAnnotation(AddCheckedBlocks.CheckedAnnotation); } return arg1; } case ILCode.Unbox_Any: // unboxing does not require a cast if the argument was an isinst instruction if (arg1 is AsExpression && byteCode.Arguments[0].Code == ILCode.Isinst && TypeAnalysis.IsSameType(operand as ITypeDefOrRef, byteCode.Arguments[0].Operand as ITypeDefOrRef)) return arg1; else goto case ILCode.Castclass; case ILCode.Castclass: if ((byteCode.Arguments[0].InferredType != null && byteCode.Arguments[0].InferredType.IsGenericParameter) || ((ITypeDefOrRef)operand).TryGetGenericSig() != null) return arg1.CastTo(new PrimitiveType("object").WithAnnotation(context.CurrentModule.CorLibTypes.Object.ToTypeDefOrRef())).CastTo(operandAsTypeRef); else return arg1.CastTo(operandAsTypeRef); case ILCode.Isinst: return arg1.CastAs(operandAsTypeRef); case ILCode.Box: return arg1; case ILCode.Unbox: return MakeRef(arg1.CastTo(operandAsTypeRef)); #endregion #region Indirect case ILCode.Ldind_Ref: case ILCode.Ldobj: if (arg1 is DirectionExpression) return ((DirectionExpression)arg1).Expression.Detach(); else return new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1); case ILCode.Stind_Ref: case ILCode.Stobj: if (arg1 is DirectionExpression) return new AssignmentExpression(((DirectionExpression)arg1).Expression.Detach(), arg2); else return new AssignmentExpression(new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1), arg2); #endregion case ILCode.Arglist: return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess }; case ILCode.Break: return InlineAssembly(byteCode, args); case ILCode.Call: case ILCode.CallGetter: case ILCode.CallSetter: return TransformCall(false, byteCode, args); case ILCode.Callvirt: case ILCode.CallvirtGetter: case ILCode.CallvirtSetter: return TransformCall(true, byteCode, args); case ILCode.Ldftn: { IMethod method = (IMethod)operand; var expr = new IdentifierExpression(method.Name); expr.TypeArguments.AddRange(ConvertTypeArguments(method)); expr.AddAnnotation(method); return new IdentifierExpression("ldftn").Invoke(expr) .WithAnnotation(new DelegateConstruction.Annotation(false)); } case ILCode.Ldvirtftn: { IMethod method = (IMethod)operand; var expr = new IdentifierExpression(method.Name); expr.TypeArguments.AddRange(ConvertTypeArguments(method)); expr.AddAnnotation(method); return new IdentifierExpression("ldvirtftn").Invoke(expr) .WithAnnotation(new 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 new ReturnStatement { Expression = arg1 }; case ILCode.Endfinally: return null; case ILCode.Initblk: return InlineAssembly(byteCode, args); case ILCode.Initobj: return InlineAssembly(byteCode, args); case ILCode.DefaultValue: return MakeDefaultValue(((ITypeDefOrRef)operand).ToTypeSig()); case ILCode.Jmp: return InlineAssembly(byteCode, args); case ILCode.Ldc_I4: return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType); case ILCode.Ldc_I8: return AstBuilder.MakePrimitive((long)operand, byteCode.InferredType); case ILCode.Ldc_R4: case ILCode.Ldc_R8: case ILCode.Ldc_Decimal: return new PrimitiveExpression(operand); case ILCode.Ldfld: if (arg1 is DirectionExpression) arg1 = ((DirectionExpression)arg1).Expression.Detach(); return arg1.Member(((IField)operand).Name).WithAnnotation(operand); case ILCode.Ldsfld: return AstBuilder.ConvertType(((IField)operand).DeclaringType) .Member(((IField)operand).Name).WithAnnotation(operand); case ILCode.Stfld: if (arg1 is DirectionExpression) arg1 = ((DirectionExpression)arg1).Expression.Detach(); return new AssignmentExpression(arg1.Member(((IField)operand).Name).WithAnnotation(operand), arg2); case ILCode.Stsfld: return new AssignmentExpression( AstBuilder.ConvertType(((IField)operand).DeclaringType) .Member(((IField)operand).Name).WithAnnotation(operand), arg1); case ILCode.Ldflda: if (arg1 is DirectionExpression) arg1 = ((DirectionExpression)arg1).Expression.Detach(); return MakeRef(arg1.Member(((IField)operand).Name).WithAnnotation(operand)); case ILCode.Ldsflda: return MakeRef( AstBuilder.ConvertType(((IField)operand).DeclaringType) .Member(((IField)operand).Name).WithAnnotation(operand)); case ILCode.Ldloc: { ILVariable v = (ILVariable)operand; if (!v.IsParameter) localVariablesToDefine.Add((ILVariable)operand); Expression expr; if (v.IsParameter && v.OriginalParameter.IsHiddenThisParameter) expr = new ThisReferenceExpression(); else expr = new IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand); return v.IsParameter && v.Type is ByRefSig ? MakeRef(expr) : expr; } case ILCode.Ldloca: { ILVariable v = (ILVariable)operand; if (v.IsParameter && v.OriginalParameter.IsHiddenThisParameter) return MakeRef(new ThisReferenceExpression()); if (!v.IsParameter) localVariablesToDefine.Add((ILVariable)operand); return MakeRef(new IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand)); } case ILCode.Ldnull: return new NullReferenceExpression(); case ILCode.Ldstr: return new PrimitiveExpression(operand); case ILCode.Ldtoken: if (operand is ITypeDefOrRef) { return AstBuilder.CreateTypeOfExpression(((ITypeDefOrRef)operand).ToTypeSig()).Member("TypeHandle").WithAnnotation(GetTypeHandleRef()); } else { Expression referencedEntity; string loadName; string handleName; MemberRef memberRef; if (dnlibExtensions.IsField(operand)) { loadName = "fieldof"; handleName = "FieldHandle"; memberRef = GetFieldHandleRef(); IField fr = (IField)operand; referencedEntity = AstBuilder.ConvertType(fr.DeclaringType).Member(fr.Name).WithAnnotation(fr); } else if (dnlibExtensions.IsMethod(operand)) { loadName = "methodof"; handleName = "MethodHandle"; memberRef = GetMethodHandleRef(); IMethod mr = (IMethod)operand; var methodParameters = mr.MethodSig.Params.Select(p => new TypeReferenceExpression(AstBuilder.ConvertType(p))); referencedEntity = AstBuilder.ConvertType(mr.DeclaringType).Invoke(mr.Name, methodParameters).WithAnnotation(mr); } else { loadName = "ldtoken"; handleName = "Handle"; memberRef = null; referencedEntity = new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand)); } return new IdentifierExpression(loadName).Invoke(referencedEntity).WithAnnotation(new LdTokenAnnotation()).Member(handleName); } case ILCode.Leave: return new GotoStatement() { Label = ((ILLabel)operand).Name }; case ILCode.Localloc: { PtrSig ptrType = byteCode.InferredType as PtrSig; TypeSig type; if (ptrType != null) { type = ptrType.Next; } else { type = typeSystem.Byte; } return new StackAllocExpression { Type = AstBuilder.ConvertType(type), CountExpression = arg1 }; } case ILCode.Mkrefany: { DirectionExpression dir = arg1 as DirectionExpression; if (dir != null) { return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.MakeRef, Arguments = { dir.Expression.Detach() } }; } else { return InlineAssembly(byteCode, args); } } case ILCode.Refanytype: return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.RefType, Arguments = { arg1 } }.Member("TypeHandle").WithAnnotation(GetTypeHandleRef()); case ILCode.Refanyval: return MakeRef( new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.RefValue, Arguments = { arg1, new TypeReferenceExpression(operandAsTypeRef) } }); case ILCode.Newobj: { ITypeDefOrRef declaringType = ((IMethod)operand).DeclaringType; if (declaringType.TryGetArraySig() != null) { ComposedType ct = AstBuilder.ConvertType(declaringType) as ComposedType; if (ct != null && ct.ArraySpecifiers.Count >= 1) { var ace = new ArrayCreateExpression(); ct.ArraySpecifiers.First().Remove(); ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); ace.Type = ct; ace.Arguments.AddRange(args); return ace; } } if (declaringType.IsAnonymousType()) { MethodDef ctor = ((IMethod)operand).ResolveMethodDef(); if (ctor != null) { AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) { atce.Initializers.AddRange(args); } else { for (int i = 0; i < args.Count; i++) { atce.Initializers.Add( new NamedExpression { Name = ctor.Parameters[i].Name, Expression = args[i] }); } } return atce; } } var oce = new ObjectCreateExpression(); oce.Type = AstBuilder.ConvertType(declaringType); oce.Arguments.AddRange(args); return oce.WithAnnotation(operand); } case ILCode.Nop: return null; case ILCode.Pop: return arg1; case ILCode.Readonly: return InlineAssembly(byteCode, args); case ILCode.Ret: if (methodDef.ReturnType.FullName != "System.Void") { return new ReturnStatement { Expression = arg1 }; } else { return new ReturnStatement(); } case ILCode.Rethrow: return new ThrowStatement(); case ILCode.Sizeof: return new SizeOfExpression { Type = operandAsTypeRef }; case ILCode.Stloc: { ILVariable locVar = (ILVariable)operand; if (!locVar.IsParameter) localVariablesToDefine.Add(locVar); return new AssignmentExpression(new 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 ThrowStatement { Expression = arg1 }; case ILCode.Unaligned: return InlineAssembly(byteCode, args); case ILCode.Volatile: return InlineAssembly(byteCode, args); case ILCode.YieldBreak: return new YieldBreakStatement(); case ILCode.YieldReturn: return new YieldReturnStatement { Expression = arg1 }; case ILCode.InitObject: case ILCode.InitCollection: { ArrayInitializerExpression initializer = new ArrayInitializerExpression(); for (int i = 1; i < args.Count; i++) { Match m = objectInitializerPattern.Match(args[i]); if (m.Success) { MemberReferenceExpression mre = m.Get<MemberReferenceExpression>("left").Single(); var exp = new NamedExpression { Name = mre.MemberName, Expression = m.Get<Expression>("right").Single().Detach() }; exp.NameToken.CopyAnnotationsFrom(mre); initializer.Elements.Add(exp); } else { m = collectionInitializerPattern.Match(args[i]); if (m.Success) { if (m.Get("arg").Count() == 1) { initializer.Elements.Add(m.Get<Expression>("arg").Single().Detach()); } else { ArrayInitializerExpression argList = new ArrayInitializerExpression(); foreach (var expr in m.Get<Expression>("arg")) { argList.Elements.Add(expr.Detach()); } initializer.Elements.Add(argList); } } else { initializer.Elements.Add(args[i]); } } } ObjectCreateExpression oce = arg1 as ObjectCreateExpression; DefaultValueExpression dve = arg1 as DefaultValueExpression; if (oce != null) { oce.Initializer = initializer; return oce; } else if (dve != null) { oce = new ObjectCreateExpression(dve.Type.Detach()); oce.CopyAnnotationsFrom(dve); oce.Initializer = initializer; return oce; } else { return new AssignmentExpression(arg1, initializer); } } case ILCode.InitializedObject: return new InitializedObjectExpression(); case ILCode.Wrap: return arg1.WithAnnotation(PushNegation.LiftedOperatorAnnotation); case ILCode.AddressOf: return MakeRef(arg1); case ILCode.ExpressionTreeParameterDeclarations: args[args.Count - 1].AddAnnotation(new ParameterDeclarationAnnotation(byteCode)); return args[args.Count - 1]; case ILCode.Await: return new UnaryOperatorExpression(UnaryOperatorType.Await, UnpackDirectionExpression(arg1)); case ILCode.NullableOf: case ILCode.ValueOf: return arg1; default: throw new Exception("Unknown OpCode: " + byteCode.Code); } }
AstNode TransformByteCode(ILExpression byteCode) { object operand = byteCode.Operand; AstType operandAsTypeRef = AstBuilder.ConvertType(operand as Cecil.TypeReference); var args = new List<Expression>(); foreach(ILExpression arg in byteCode.Arguments) { args.Add((Expression)TransformExpression(arg)); } Expression arg1 = args.Count >= 1 ? args[0] : null; Expression arg2 = args.Count >= 2 ? args[1] : null; Expression arg3 = args.Count >= 3 ? args[2] : null; switch (byteCode.Code) { #region Arithmetic case ILCode.Add: case ILCode.Add_Ovf: case ILCode.Add_Ovf_Un: { BinaryOperatorExpression boe; if (byteCode.InferredType is PointerType) { if (byteCode.Arguments[0].ExpectedType is PointerType) { arg2 = DivideBySize(arg2, ((PointerType)byteCode.InferredType).ElementType); boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation); } else if (byteCode.Arguments[1].ExpectedType is PointerType) { arg1 = DivideBySize(arg1, ((PointerType)byteCode.InferredType).ElementType); boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation); } else { boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); } } else { boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); } boe.AddAnnotation(byteCode.Code == ILCode.Add ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); return boe; } case ILCode.Sub: case ILCode.Sub_Ovf: case ILCode.Sub_Ovf_Un: { BinaryOperatorExpression boe; if (byteCode.InferredType is PointerType) { if (byteCode.Arguments[0].ExpectedType is PointerType) { arg2 = DivideBySize(arg2, ((PointerType)byteCode.InferredType).ElementType); boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); boe.WithAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation); } else { boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); } } else { boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); } boe.AddAnnotation(byteCode.Code == ILCode.Sub ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); return boe; } case ILCode.Div: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); case ILCode.Div_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); case ILCode.Mul: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation); case ILCode.Mul_Ovf: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation); case ILCode.Mul_Ovf_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation); case ILCode.Rem: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); case ILCode.Rem_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); case ILCode.And: return new BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2); case ILCode.Or: return new BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2); case ILCode.Xor: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2); case ILCode.Shl: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2); case ILCode.Shr: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); case ILCode.Shr_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); case ILCode.Neg: return new UnaryOperatorExpression(UnaryOperatorType.Minus, arg1).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation); case ILCode.Not: return new UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1); case ILCode.PostIncrement: case ILCode.PostIncrement_Ovf: case ILCode.PostIncrement_Ovf_Un: { if (arg1 is DirectionExpression) arg1 = ((DirectionExpression)arg1).Expression.Detach(); var uoe = new UnaryOperatorExpression( (int)byteCode.Operand > 0 ? UnaryOperatorType.PostIncrement : UnaryOperatorType.PostDecrement, arg1); uoe.AddAnnotation((byteCode.Code == ILCode.PostIncrement) ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); return uoe; } #endregion #region Arrays case ILCode.Newarr: { var ace = new 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 ArrayCreateExpression(); ace.Type = operandAsTypeRef; ComposedType ct = operandAsTypeRef as ComposedType; var arrayType = (ArrayType) operand; if (ct != null) { // change "new (int[,])[10] to new int[10][,]" ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); ace.Initializer = new ArrayInitializerExpression(); var first = ace.AdditionalArraySpecifiers.First(); first.Remove(); ace.Arguments.AddRange(Enumerable.Repeat(0, first.Dimensions).Select(i => (Expression)new EmptyExpression())); } var newArgs = new List<Expression>(); foreach (var arrayDimension in arrayType.Dimensions.Skip(1).Reverse()) { int length = (int)arrayDimension.UpperBound - (arrayDimension.LowerBound ?? 0); for (int j = 0; j < args.Count; j += length) { var child = new ArrayInitializerExpression(); child.Elements.AddRange(args.GetRange(j, length)); newArgs.Add(child); } var temp = args; args = newArgs; newArgs = temp; newArgs.Clear(); } ace.Initializer.Elements.AddRange(args); return ace; } case ILCode.Ldlen: return arg1.Member("Length"); case ILCode.Ldelem_I: case ILCode.Ldelem_I1: case ILCode.Ldelem_I2: case ILCode.Ldelem_I4: case ILCode.Ldelem_I8: case ILCode.Ldelem_U1: case ILCode.Ldelem_U2: case ILCode.Ldelem_U4: case ILCode.Ldelem_R4: case ILCode.Ldelem_R8: case ILCode.Ldelem_Ref: case ILCode.Ldelem_Any: return arg1.Indexer(arg2); case ILCode.Ldelema: return MakeRef(arg1.Indexer(arg2)); case ILCode.Stelem_I: case ILCode.Stelem_I1: case ILCode.Stelem_I2: case ILCode.Stelem_I4: case ILCode.Stelem_I8: case ILCode.Stelem_R4: case ILCode.Stelem_R8: case ILCode.Stelem_Ref: case ILCode.Stelem_Any: return new AssignmentExpression(arg1.Indexer(arg2), arg3); case ILCode.CompoundAssignment: { CastExpression cast = arg1 as CastExpression; BinaryOperatorExpression boe = (BinaryOperatorExpression)(cast != null ? cast.Expression : arg1); var assignment = new AssignmentExpression { Left = boe.Left.Detach(), Operator = ReplaceMethodCallsWithOperators.GetAssignmentOperatorForBinaryOperator(boe.Operator), Right = boe.Right.Detach() }.CopyAnnotationsFrom(boe); // We do not mark the resulting assignment as RestoreOriginalAssignOperatorAnnotation, because // the operator cannot be translated back to the expanded form (as the left-hand expression // would be evaluated twice, and might have side-effects) if (cast != null) { cast.Expression = assignment; return cast; } else { return assignment; } } #endregion #region Comparison case ILCode.Ceq: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2); case ILCode.Cgt: return new 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 BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2); else return new BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); } case ILCode.Clt: return new BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); case ILCode.Clt_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); #endregion #region Logical case ILCode.LogicNot: return new UnaryOperatorExpression(UnaryOperatorType.Not, arg1); case ILCode.LogicAnd: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2); case ILCode.LogicOr: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2); case ILCode.TernaryOp: return new ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 }; case ILCode.NullCoalescing: return new BinaryOperatorExpression(arg1, BinaryOperatorType.NullCoalescing, arg2); #endregion #region Branch case ILCode.Br: return new GotoStatement(((ILLabel)byteCode.Operand).Name); case ILCode.Brtrue: return new IfElseStatement() { Condition = arg1, TrueStatement = new BlockStatement() { new GotoStatement(((ILLabel)byteCode.Operand).Name) } }; case ILCode.LoopOrSwitchBreak: return new BreakStatement(); case ILCode.LoopContinue: return new ContinueStatement(); #endregion #region Conversions case ILCode.Conv_I1: case ILCode.Conv_I2: case ILCode.Conv_I4: case ILCode.Conv_I8: case ILCode.Conv_U1: case ILCode.Conv_U2: case ILCode.Conv_U4: case ILCode.Conv_U8: case ILCode.Conv_I: case ILCode.Conv_U: { // conversion was handled by Convert() function using the info from type analysis CastExpression cast = arg1 as CastExpression; if (cast != null) { cast.AddAnnotation(AddCheckedBlocks.UncheckedAnnotation); } return arg1; } case ILCode.Conv_R4: case ILCode.Conv_R8: case ILCode.Conv_R_Un: // TODO return arg1; case ILCode.Conv_Ovf_I1: case ILCode.Conv_Ovf_I2: case ILCode.Conv_Ovf_I4: case ILCode.Conv_Ovf_I8: case ILCode.Conv_Ovf_U1: case ILCode.Conv_Ovf_U2: case ILCode.Conv_Ovf_U4: case ILCode.Conv_Ovf_U8: case ILCode.Conv_Ovf_I1_Un: case ILCode.Conv_Ovf_I2_Un: case ILCode.Conv_Ovf_I4_Un: case ILCode.Conv_Ovf_I8_Un: case ILCode.Conv_Ovf_U1_Un: case ILCode.Conv_Ovf_U2_Un: case ILCode.Conv_Ovf_U4_Un: case ILCode.Conv_Ovf_U8_Un: { // conversion was handled by Convert() function using the info from type analysis CastExpression cast = arg1 as CastExpression; if (cast != null) { cast.AddAnnotation(AddCheckedBlocks.CheckedAnnotation); } return arg1; } 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: // unboxing does not require a cast if the argument was an isinst instruction if (arg1 is AsExpression && byteCode.Arguments[0].Code == ILCode.Isinst && TypeAnalysis.IsSameType(operand as TypeReference, byteCode.Arguments[0].Operand as TypeReference)) return arg1; else return arg1.CastTo(operandAsTypeRef); case ILCode.Isinst: return arg1.CastAs(operandAsTypeRef); case ILCode.Box: return arg1; case ILCode.Unbox: return MakeRef(arg1.CastTo(operandAsTypeRef)); #endregion #region Indirect case ILCode.Ldind_Ref: case ILCode.Ldobj: if (arg1 is DirectionExpression) return ((DirectionExpression)arg1).Expression.Detach(); else return new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1); case ILCode.Stind_Ref: case ILCode.Stobj: if (arg1 is DirectionExpression) return new AssignmentExpression(((DirectionExpression)arg1).Expression.Detach(), arg2); else return new AssignmentExpression(new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1), arg2); #endregion case ILCode.Arglist: return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess }; case ILCode.Break: return InlineAssembly(byteCode, args); case ILCode.Call: case ILCode.CallGetter: case ILCode.CallSetter: return TransformCall(false, byteCode, args); case ILCode.Callvirt: case ILCode.CallvirtGetter: case ILCode.CallvirtSetter: return TransformCall(true, byteCode, args); case ILCode.Ldftn: { Cecil.MethodReference cecilMethod = ((MethodReference)operand); var expr = new 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 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: return InlineAssembly(byteCode, args); case ILCode.DefaultValue: return MakeDefaultValue((TypeReference)operand); case ILCode.Jmp: return InlineAssembly(byteCode, args); case ILCode.Ldc_I4: return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType); case ILCode.Ldc_I8: return AstBuilder.MakePrimitive((long)operand, byteCode.InferredType); case ILCode.Ldc_R4: case ILCode.Ldc_R8: case ILCode.Ldc_Decimal: return new PrimitiveExpression(operand); case ILCode.Ldfld: if (arg1 is DirectionExpression) arg1 = ((DirectionExpression)arg1).Expression.Detach(); return arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand); case ILCode.Ldsfld: return AstBuilder.ConvertType(((FieldReference)operand).DeclaringType) .Member(((FieldReference)operand).Name).WithAnnotation(operand); case ILCode.Stfld: if (arg1 is DirectionExpression) arg1 = ((DirectionExpression)arg1).Expression.Detach(); return new AssignmentExpression(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand), arg2); case ILCode.Stsfld: return new AssignmentExpression( AstBuilder.ConvertType(((FieldReference)operand).DeclaringType) .Member(((FieldReference)operand).Name).WithAnnotation(operand), arg1); case ILCode.Ldflda: if (arg1 is DirectionExpression) arg1 = ((DirectionExpression)arg1).Expression.Detach(); return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand)); case ILCode.Ldsflda: return MakeRef( AstBuilder.ConvertType(((FieldReference)operand).DeclaringType) .Member(((FieldReference)operand).Name).WithAnnotation(operand)); case ILCode.Ldloc: { ILVariable v = (ILVariable)operand; if (!v.IsParameter) localVariablesToDefine.Add((ILVariable)operand); Expression expr; if (v.IsParameter && v.OriginalParameter.Index < 0) expr = new ThisReferenceExpression(); else expr = new IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand); return v.IsParameter && v.Type is ByReferenceType ? MakeRef(expr) : expr; } case ILCode.Ldloca: { ILVariable v = (ILVariable)operand; if (v.IsParameter && v.OriginalParameter.Index < 0) return MakeRef(new ThisReferenceExpression()); if (!v.IsParameter) localVariablesToDefine.Add((ILVariable)operand); return MakeRef(new IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand)); } case ILCode.Ldnull: return new NullReferenceExpression(); case ILCode.Ldstr: return new PrimitiveExpression(operand); case ILCode.Ldtoken: if (operand is Cecil.TypeReference) { return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle"); } else { return InlineAssembly(byteCode, args); } case ILCode.Leave: return new GotoStatement() { Label = ((ILLabel)operand).Name }; case ILCode.Localloc: { PointerType ptrType = byteCode.InferredType as PointerType; TypeReference type; if (ptrType != null) { type = ptrType.ElementType; } else { type = typeSystem.Byte; } return new StackAllocExpression { Type = AstBuilder.ConvertType(type), CountExpression = DivideBySize(arg1, type) }; } case ILCode.Mkrefany: { DirectionExpression dir = arg1 as DirectionExpression; if (dir != null) { return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.MakeRef, Arguments = { dir.Expression.Detach() } }; } else { return InlineAssembly(byteCode, args); } } case ILCode.Refanytype: return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.RefType, Arguments = { arg1 } }.Member("TypeHandle"); case ILCode.Refanyval: return MakeRef( new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.RefValue, Arguments = { arg1, new TypeReferenceExpression(operandAsTypeRef) } }); 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 ArrayCreateExpression(); ct.ArraySpecifiers.First().Remove(); ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); ace.Type = ct; ace.Arguments.AddRange(args); return ace; } } var oce = new ObjectCreateExpression(); if (declaringType.IsAnonymousType()) { MethodDefinition ctor = ((MethodReference)operand).Resolve(); if (methodDef != null) { oce.Initializer = new ArrayInitializerExpression(); for (int i = 0; i < args.Count; i++) { oce.Initializer.Elements.Add( new NamedArgumentExpression { Identifier = ctor.Parameters[i].Name, Expression = args[i] }); } } return oce; } 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.Ret: if (methodDef.ReturnType.FullName != "System.Void") { return new ReturnStatement { Expression = arg1 }; } else { return new ReturnStatement(); } case ILCode.Rethrow: return new ThrowStatement(); case ILCode.Sizeof: return new SizeOfExpression { Type = operandAsTypeRef }; case ILCode.Stloc: { ILVariable locVar = (ILVariable)operand; if (!locVar.IsParameter) localVariablesToDefine.Add(locVar); return new AssignmentExpression(new 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 ThrowStatement { Expression = arg1 }; case ILCode.Unaligned: return InlineAssembly(byteCode, args); case ILCode.Volatile: return InlineAssembly(byteCode, args); case ILCode.YieldBreak: return new YieldBreakStatement(); case ILCode.YieldReturn: return new YieldStatement { Expression = arg1 }; case ILCode.InitObject: case ILCode.InitCollection: { ArrayInitializerExpression initializer = new ArrayInitializerExpression(); for (int i = 1; i < args.Count; i++) { Match m = objectInitializerPattern.Match(args[i]); if (m.Success) { MemberReferenceExpression mre = m.Get<MemberReferenceExpression>("left").Single(); initializer.Elements.Add( new NamedArgumentExpression { Identifier = mre.MemberName, Expression = m.Get<Expression>("right").Single().Detach() }.CopyAnnotationsFrom(mre)); } else { m = collectionInitializerPattern.Match(args[i]); if (m.Success) { if (m.Get("arg").Count() == 1) { initializer.Elements.Add(m.Get<Expression>("arg").Single().Detach()); } else { ArrayInitializerExpression argList = new ArrayInitializerExpression(); foreach (var expr in m.Get<Expression>("arg")) { argList.Elements.Add(expr.Detach()); } initializer.Elements.Add(argList); } } else { initializer.Elements.Add(args[i]); } } } ObjectCreateExpression oce = arg1 as ObjectCreateExpression; DefaultValueExpression dve = arg1 as DefaultValueExpression; if (oce != null) { oce.Initializer = initializer; return oce; } else if (dve != null) { oce = new ObjectCreateExpression(dve.Type.Detach()); oce.CopyAnnotationsFrom(dve); oce.Initializer = initializer; return oce; } else { return new AssignmentExpression(arg1, initializer); } } case ILCode.InitializedObject: return new InitializedObjectExpression(); case ILCode.AddressOf: return MakeRef(arg1); default: throw new Exception("Unknown OpCode: " + byteCode.Code); } }