using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Reflection.Emit; using System.Runtime.InteropServices; using UnitTestProject.RefVm; using VMProtect; using OpCodes = System.Reflection.Emit.OpCodes; namespace UnitTestProject { [TestClass] public class UnitTestCombine { // шаблон для окружающего кода для некой инструкции public enum CodeTemplate { BranchTwoOpBool, // 2 операнда на стеке, 2 ветки исполнения (одна возвращает true, другая false) SingleOpAny, // 1 операнд на стеке, инструкция, возвращающая разные типы TwoOpBool, // 2 операнда на стеке, инструкция, возвращающая bool TwoOpAny, // 2 операнда на стеке, инструкция, возвращающая разные типы } [TestMethod] public void TestMethodRefVm() { InitStrings(); TestMethod(new MsilToVmTestCompilerRefVm()); } [TestMethod] public void TestMethodVmp() { TestMethod(new MsilToVmTestCompilerVmp()); } [SuppressMessage("ReSharper", "RedundantCast")] public void TestMethod(MsilToVmTestCompiler c) { // типовые и крайние значения следующих типов: // SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, // float, double, // LongEnum, ULongEnum, Char, SByteEnum, ByteEnum, ShortEnum, UShortEnum, IntEnum, UIntEnum // bool, object, IntPtr, UIntPtr //TODO: decimal #region valsVector // ReSharper disable once RedundantExplicitArrayCreation var valsVector = new object [] { (SByte)0, (SByte)1, (SByte)(-1), SByte.MaxValue, SByte.MinValue, (SByte)0x55, // SByte (Byte)0, (Byte)1, Byte.MaxValue, (Byte)0xAA, // Byte (Int16)0, (Int16)1, (Int16)(-1), Int16.MaxValue, Int16.MinValue, (Int16)0x55AA, // Int16 (UInt16)0, (UInt16)1, UInt16.MaxValue, (UInt16)0xAA55, // UInt16 0, 1, -1, Int32.MaxValue, Int32.MinValue, 0x55AA55AA, // Int32 (UInt32)0, (UInt32)1, UInt32.MaxValue, 0xAA5555AA, // UInt32 (Int64)0, (Int64)1, (Int64)(-1), Int64.MaxValue, Int64.MinValue, 0x55AA55AA55AA55AA, // Int64 (UInt64)0, (UInt64)1, UInt64.MaxValue, 0xAA5555AAAA5555AA, // UInt64 (float)0, (float)1, (float)(-1), float.MaxValue, float.MinValue, float.Epsilon, float.NaN, float.NegativeInfinity, float.PositiveInfinity, (float)(5678.1234),(float)(1234.5678), (float)(-5678.1234), (float)(-1234.5678), (float)(2147483647.0 * 3.0), (float)(-2147483647.0 * 3.0), (float)(9223372336854775807.0 * 3.0), -(float)(9223372336854775807.0 * 3.0), // float (double)0, (double)1, (double)(-1), double.MaxValue, double.MinValue, double.Epsilon, double.NaN, double.NegativeInfinity, double.PositiveInfinity, 5678.1234, 1234.5678, -5678.1234, -1234.5678, (double)(2147483647.0 * 3.0), (double)(-2147483647.0 * 3.0), (double)9223372336854775807.0 * 3.0, -(double)9223372336854775807.0 * 3.0, // double (MsilToVmTestCompiler.LongEnum)0, (MsilToVmTestCompiler.LongEnum)1, (MsilToVmTestCompiler.LongEnum)(-1), (MsilToVmTestCompiler.LongEnum)Int64.MaxValue, (MsilToVmTestCompiler.LongEnum)Int64.MinValue, (MsilToVmTestCompiler.LongEnum)0x55AA55AA55AA55AA, // LongEnum (MsilToVmTestCompiler.ULongEnum)0, (MsilToVmTestCompiler.ULongEnum)1, (MsilToVmTestCompiler.ULongEnum)UInt64.MaxValue, (MsilToVmTestCompiler.ULongEnum)0xAA5555AAAA5555AA, // ULongEnum (Char)0, (Char)1, 'Ю', Char.MaxValue, (Char)0xAA55, // Char (MsilToVmTestCompiler.SByteEnum)0, (MsilToVmTestCompiler.SByteEnum)1, (MsilToVmTestCompiler.SByteEnum)(-1), (MsilToVmTestCompiler.SByteEnum)sbyte.MaxValue, (MsilToVmTestCompiler.SByteEnum)sbyte.MinValue, (MsilToVmTestCompiler.SByteEnum)0x55, // SByteEnum (MsilToVmTestCompiler.ByteEnum)0, (MsilToVmTestCompiler.ByteEnum)1, (MsilToVmTestCompiler.ByteEnum)Byte.MaxValue, (MsilToVmTestCompiler.ByteEnum)0xAA, // ByteEnum (MsilToVmTestCompiler.ShortEnum)0, (MsilToVmTestCompiler.ShortEnum)1, (MsilToVmTestCompiler.ShortEnum)(-1), (MsilToVmTestCompiler.ShortEnum)short.MaxValue, (MsilToVmTestCompiler.ShortEnum)short.MinValue, (MsilToVmTestCompiler.ShortEnum)0x55AA, // ShortEnum (MsilToVmTestCompiler.UShortEnum)0, (MsilToVmTestCompiler.UShortEnum)1, (MsilToVmTestCompiler.UShortEnum)ushort.MaxValue, (MsilToVmTestCompiler.UShortEnum)0xAA55, // UShortEnum (MsilToVmTestCompiler.IntEnum)0, (MsilToVmTestCompiler.IntEnum)1, (MsilToVmTestCompiler.IntEnum)(-1), (MsilToVmTestCompiler.IntEnum)int.MaxValue, (MsilToVmTestCompiler.IntEnum)int.MinValue, (MsilToVmTestCompiler.IntEnum)0x55AA55AA, // IntEnum (MsilToVmTestCompiler.UIntEnum)0, (MsilToVmTestCompiler.UIntEnum)1, (MsilToVmTestCompiler.UIntEnum)uint.MaxValue, (MsilToVmTestCompiler.UIntEnum)0xAA5555AA, // UIntEnum true, false, // bool new object(), //object new IntPtr(0), new UIntPtr(0), // IntPtr, UIntPtr }; #endregion var errCounters = new int[(int)MsilToVmTestCompiler.InvokeTestCombineError.Cnt]; var operations = new List> { new KeyValuePair(OpCodes.Add, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Add_Ovf, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Add_Ovf_Un, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.And, CodeTemplate.TwoOpAny), //Arglist не годится для этого теста new KeyValuePair(OpCodes.Beq_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Bge_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Bge_Un_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Bgt_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Bgt_Un_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Ble_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Ble_Un_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Blt_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Blt_Un_S, CodeTemplate.BranchTwoOpBool), new KeyValuePair(OpCodes.Bne_Un_S, CodeTemplate.BranchTwoOpBool), //TODO Box //Br_S тестируется неявно в этом тесте //Break не годится для этого теста //TODO Brfalse_S //TODO Brtrue_S //Call тестируется в TestNewobj //Calli Callvirt Castclass не годятся для этого теста new KeyValuePair(OpCodes.Ceq, CodeTemplate.TwoOpBool), new KeyValuePair(OpCodes.Cgt, CodeTemplate.TwoOpBool), new KeyValuePair(OpCodes.Cgt_Un, CodeTemplate.TwoOpBool), new KeyValuePair(OpCodes.Ckfinite, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Clt, CodeTemplate.TwoOpBool), new KeyValuePair(OpCodes.Clt_Un, CodeTemplate.TwoOpBool), //Constrained не годится для этого теста new KeyValuePair(OpCodes.Conv_I, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_I1, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_I2, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_I4, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_I8, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I1, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I1_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I2, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I2_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I4, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I4_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I8, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I8_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_I_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U1, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U1_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U2, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U2_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U4, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U4_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U8, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U8_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_Ovf_U_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_R4, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_R8, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_R_Un, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_U, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_U1, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_U2, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_U4, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Conv_U8, CodeTemplate.SingleOpAny), //Cpblk Cpobj не годятся для этого теста new KeyValuePair(OpCodes.Div, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Div_Un, CodeTemplate.TwoOpAny), //TODO: Dup //Endfilter Endfinally Initblk Initobj Isinst Jmp Ldarg не годятся для этого теста //Ldarg_0 тестируется неявно в этом тесте //Ldarg_1 тестируется неявно в этом тесте //Ldarg_2 Ldarg_3 Ldarg_S Ldarga не годятся для этого теста //Ldarga_S тестируется в TestNewobj //Ldc_I4 не годится для этого теста //Ldc_I4_0 тестируется неявно в этом тесте //Ldc_I4_1 тестируется неявно в этом тесте //Ldc_I4_2 Ldc_I4_3 Ldc_I4_4 Ldc_I4_5 Ldc_I4_6 Ldc_I4_7 Ldc_I4_8 Ldc_I4_M1 Ldc_I4_S Ldc_I8 Ldc_R4 Ldc_R8 не годятся для этого теста //Ldelem* Ldfld Ldflda Ldftn Ldind_* Ldlen Ldloc* Ldnull Ldobj Ldsfld Ldsflda Ldstr Ldtoken Ldvirtftn Leave Leave_S Localloc Mkrefany не годятся для этого теста new KeyValuePair(OpCodes.Mul, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Mul_Ovf, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Mul_Ovf_Un, CodeTemplate.TwoOpAny), //TODO new KeyValuePair(OpCodes.Neg, CodeTemplate.SingleOp), //Newarr не годится для этого теста //Newobj тестируется в TestNewobj //Nop не годится для этого теста new KeyValuePair(OpCodes.Not, CodeTemplate.SingleOpAny), new KeyValuePair(OpCodes.Or, CodeTemplate.TwoOpAny), //Pop Prefix* Readonly Refanytype Refanyval не годятся для этого теста new KeyValuePair(OpCodes.Rem, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Rem_Un, CodeTemplate.TwoOpAny), //Ret тестируется неявно в этом тесте //Rethrow не годится для этого теста new KeyValuePair(OpCodes.Shl, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Shr, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Shr_Un, CodeTemplate.TwoOpAny), //Sizeof //St* не годятся для этого теста new KeyValuePair(OpCodes.Sub, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Sub_Ovf, CodeTemplate.TwoOpAny), new KeyValuePair(OpCodes.Sub_Ovf_Un, CodeTemplate.TwoOpAny), //Switch Tailcall Throw Unaligned //TODO Unbox //TODO Unbox_Any //Volatile не годится для этого теста new KeyValuePair(OpCodes.Xor, CodeTemplate.TwoOpAny), }; foreach (var op in operations) { switch (op.Value) { case CodeTemplate.BranchTwoOpBool: case CodeTemplate.TwoOpBool: case CodeTemplate.TwoOpAny: TestOperationTwoOp(c, op, valsVector, errCounters); break; case CodeTemplate.SingleOpAny: TestOperationSingleOp(c, op, valsVector, errCounters); break; default: Assert.Fail("Unsupported op.Value: {0}", op.Value); break; } } Console.Error.WriteLine("--- {0} results ---", IntPtr.Size == 4 ? "x86" : "x64"); var sum = 0; for (var i = 0; i < errCounters.Length; i++) { Console.Error.WriteLine("{0}: {1}", (MsilToVmTestCompiler.InvokeTestCombineError)i, errCounters[i]); sum += errCounters[i]; } Console.Error.WriteLine("--- TOTAL: {0} ---", sum); Assert.AreEqual(sum, errCounters[(int)MsilToVmTestCompiler.InvokeTestCombineError.NoError] + errCounters[(int)MsilToVmTestCompiler.InvokeTestCombineError.NoErrorByStdEx]); Console.Error.WriteLine(sum == errCounters[(int) MsilToVmTestCompiler.InvokeTestCombineError.NoError] + errCounters[(int) MsilToVmTestCompiler.InvokeTestCombineError.NoErrorByStdEx] ? "TEST PASSED" : "TEST FAILED"); } private void TestOperationTwoOp(MsilToVmTestCompiler c, KeyValuePair op, object[] valsVector, int[] errCounters) { foreach (var i in valsVector) { foreach (var j in valsVector) { object[] parameters = {i, j}; string err, istr = i.ToString(), jstr = j.ToString(); if (i is Char) istr = $@"'\{Convert.ToInt32(i)}'"; if (j is Char) jstr = $@"'\{Convert.ToInt32(j)}'"; var res = TestOperation(c, op, parameters, errCounters, out err); if(res > MsilToVmTestCompiler.InvokeTestCombineError.NoErrorByStdEx) Console.Error.WriteLine("{0}.{1}(({4}){2}, ({5}){3}) = {6}", op.Key, op.Value, istr, jstr, i.GetType().FullName, j.GetType().FullName, err); } } } private void TestOperationSingleOp(MsilToVmTestCompiler c, KeyValuePair op, object[] valsVector, int[] errCounters) { foreach (object i in valsVector) { object[] parameters = { i }; string err, istr = i.ToString(); if (i is Char) istr = $@"'\{Convert.ToInt32(i)}'"; var res = TestOperation(c, op, parameters, errCounters, out err); if (res > MsilToVmTestCompiler.InvokeTestCombineError.NoErrorByStdEx) Console.Error.WriteLine("{0}.{1}(({3}){2}) = {4}", op.Key, op.Value, istr, i.GetType().FullName, err); } } [TestMethod] public void TempRefVm() { InitStrings(); var errCounters = new int[(int)MsilToVmTestCompiler.InvokeTestCombineError.Cnt]; string err; TestOperation(new MsilToVmTestCompilerRefVm(), new KeyValuePair(OpCodes.Add_Ovf_Un, CodeTemplate.TwoOpAny), // ReSharper disable once RedundantExplicitArrayCreation new object[] { new object(), (System.SByte)0 }, errCounters, out err); Assert.AreEqual(1, errCounters[0] + errCounters[1]); } [TestMethod] public void TempVmp() { var errCounters = new int[(int)MsilToVmTestCompiler.InvokeTestCombineError.Cnt]; string err; TestOperation(new MsilToVmTestCompilerVmp(), new KeyValuePair(OpCodes.Conv_U4, CodeTemplate.SingleOpAny), // ReSharper disable once RedundantCast new object[] { (Int32)0 }, errCounters, out err); Console.WriteLine(err); Assert.AreEqual(1, errCounters[0] + errCounters[1]); } private static void InitStrings() { StringDecryptor.SetString(-1550347095, "The value is not finite real number."); } private MsilToVmTestCompiler.InvokeTestCombineError TestOperation( MsilToVmTestCompiler c, KeyValuePair op, object[] parameters, int [] errCounters, out string err) { DynamicMethod dyn; err = ""; var types = parameters.Select(o => o.GetType()).ToArray(); switch (op.Value) { case CodeTemplate.BranchTwoOpBool: dyn = DynBranch2Op(op, types); break; case CodeTemplate.SingleOpAny: dyn = DynSingleOpAny(op, types); break; case CodeTemplate.TwoOpBool: dyn = Dyn2OpBool(op, types); break; case CodeTemplate.TwoOpAny: dyn = Dyn2OpAny(op, types); break; default: Assert.Fail("Unsupported op.Value: {0}", op.Value); // ReSharper disable once HeuristicUnreachableCode return MsilToVmTestCompiler.InvokeTestCombineError.Cnt; } object dynRet, vmRet; var ret = c.InvokeTestCombine(dyn, parameters, out dynRet, out vmRet, out err); // TODO: для регрессии надо как-то научиться закладывать сюда все правильные результаты if (errCounters != null) { if (ret > MsilToVmTestCompiler.InvokeTestCombineError.NoErrorByStdEx && ExtendedEcma335.Check(op, parameters, vmRet)) { ret = MsilToVmTestCompiler.InvokeTestCombineError.NoErrorByStdEx; } errCounters[(int)ret]++; } return ret; } private DynamicMethod DynSingleOpAny(KeyValuePair op, Type[] types) { Type pushedT; switch (op.Key.StackBehaviourPush) { default: Assert.Fail("DynSingleOp unsupported StackBehaviourPush={0}", op.Key.StackBehaviourPush); // ReSharper disable once HeuristicUnreachableCode return null; case StackBehaviour.Pushi: pushedT = typeof(Int32); break; case StackBehaviour.Pushi8: pushedT = typeof(Int64); break; case StackBehaviour.Pushr4: pushedT = typeof(float); break; case StackBehaviour.Pushr8: pushedT = typeof(double); break; case StackBehaviour.Push1: pushedT = CompatibleType(types[0], types[0], false); if (pushedT == typeof(object)) pushedT = typeof(IntPtr); break; } if ((IntPtr.Size == 8) && (op.Key.Equals(OpCodes.Conv_I) || op.Key.Equals(OpCodes.Conv_Ovf_I) || op.Key.Equals(OpCodes.Conv_Ovf_I_Un))) pushedT = typeof(Int64); if (op.Key.Equals(OpCodes.Conv_U) ||op.Key.Equals(OpCodes.Conv_Ovf_U) || op.Key.Equals(OpCodes.Conv_Ovf_U_Un)) pushedT = (IntPtr.Size == 8) ? typeof(UInt64) : typeof(UInt32); var dyn = new DynamicMethod(op.Key.Name, pushedT, types, typeof(void), true); var gen = dyn.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(op.Key); gen.Emit(OpCodes.Ret); return dyn; } internal class ClassNewobj { public const long Check = 0xF00D; public long Ptr; public unsafe ClassNewobj(byte *ptr) { Ptr = (long) ptr; } } public static unsafe object StatNewobj(IntPtr ptr) { return new ClassNewobj((byte *)ptr.ToPointer()); } [TestMethod] [SuppressMessage("ReSharper", "PossibleNullReferenceException")] public void TestNewobj() //https://ursoft.asuscomm.com:8080/browse/VMP-134?focusedCommentId=15312&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-15312 { InitStrings(); MsilToVmTestCompiler c = new MsilToVmTestCompilerVmp(); var mi = typeof (UnitTestCombine).GetMethod("StatNewobj"); var no = (ClassNewobj)c.Invoke(new object[] {new IntPtr(ClassNewobj.Check)}, c.CreateVmStream(mi.ReturnType, mi.GetParameters(), mi.GetMethodBody().LocalVariables.Select(o => o.LocalType).ToArray(), mi.GetMethodBody().GetILAsByteArray())); Assert.AreEqual(ClassNewobj.Check, no.Ptr); } private static DynamicMethod DynBranch2Op(KeyValuePair op, Type[] types) { var dyn = new DynamicMethod(op.Key.Name, typeof(bool), types, typeof(void), true); var gen = dyn.GetILGenerator(); var retTrue = gen.DefineLabel(); var endOfMthd = gen.DefineLabel(); gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Ldarg_0); gen.Emit(op.Key, retTrue); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Br_S, endOfMthd); gen.MarkLabel(retTrue); gen.Emit(OpCodes.Ldc_I4_1); gen.MarkLabel(endOfMthd); gen.Emit(OpCodes.Ret); return dyn; } private static DynamicMethod Dyn2OpAny(KeyValuePair op, Type[] types) { Type pushedT; switch (op.Key.StackBehaviourPush) { default: Assert.Fail("Dyn2OpAny unsupported StackBehaviourPush={0}", op.Key.StackBehaviourPush); // ReSharper disable once HeuristicUnreachableCode return null; case StackBehaviour.Pushi: pushedT = typeof(Int32); break; case StackBehaviour.Pushi8: pushedT = typeof(Int64); break; case StackBehaviour.Pushr4: pushedT = typeof(float); break; case StackBehaviour.Pushr8: pushedT = typeof(double); break; case StackBehaviour.Push1: pushedT = (op.Key.Value == OpCodes.Shl.Value || op.Key.Value == OpCodes.Shr.Value || op.Key.Value == OpCodes.Shr_Un.Value) ? types[1]: types[0]; pushedT = CompatibleType(pushedT, types[1], !op.Key.Name.EndsWith("_Un")); if (pushedT == typeof (object)) pushedT = typeof(IntPtr); break; } return Dyn2Op(op, types, pushedT); } public static Type CompatibleType(Type type0, Type type1, bool signed) { if (type0.IsEnum) type0 = type0.GetEnumUnderlyingType(); if (type1.IsEnum) type1 = type1.GetEnumUnderlyingType(); if (type0 == typeof (bool) && type1 == typeof (bool)) return typeof (sbyte); // true + true = 2 if (type0 == typeof (IntPtr)) type0 = IntPtr.Size == 4 ? typeof (Int32) : typeof (Int64); if (type0 == typeof (UIntPtr)) type0 = IntPtr.Size == 4 ? typeof (UInt32) : typeof (UInt64); if (type1 == typeof (IntPtr)) type1 = IntPtr.Size == 4 ? typeof (Int32) : typeof (Int64); if (type1 == typeof (UIntPtr)) type1 = IntPtr.Size == 4 ? typeof (UInt32) : typeof (UInt64); if (type0 == type1) return type0; // возвращаем наиболее широкий из типов return TypeWidth(type0) >= TypeWidth(type1) ? EnsureSign(type0, signed) : EnsureSign(type1, signed); } private static Type EnsureSign(Type t, bool signed) { if (t == typeof (Int32)) return signed ? t : typeof (UInt32); if (t == typeof (UInt32)) return signed ? typeof (Int32) : t; if (t == typeof (Int64)) return signed ? t : typeof (UInt64); if (t == typeof (UInt64)) return signed ? typeof (Int64) : t; return t; } private static int TypeWidth(Type t) { if (t.IsEnum) t = t.GetEnumUnderlyingType(); if (t == typeof (bool)) return 1; if (t == typeof (byte) || t == typeof (sbyte)) return 2; if (t == typeof (short) || t == typeof (ushort) || t == typeof(Char)) return 3; if (t == typeof (int) || t == typeof (uint)) return 4; if (t == typeof (long) || t == typeof (ulong)) return 5; if (t == typeof(float)) return 6; if (t == typeof(double)) return 7; return 8; // object etc } private static DynamicMethod Dyn2OpBool(KeyValuePair op, Type[] types) { Type pushedT = typeof(bool); return Dyn2Op(op, types, pushedT); } private static DynamicMethod Dyn2Op(KeyValuePair op, Type[] types, Type ret) { var dyn = new DynamicMethod(op.Key.Name, ret, types, typeof(void), true); var gen = dyn.GetILGenerator(); gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Ldarg_0); gen.Emit(op.Key); gen.Emit(OpCodes.Ret); return dyn; } } internal class MsilToVmTestCompilerVmp : MsilToVmTestCompiler { #region opcodes internal static readonly Dictionary> IlToVmInstrInfo = new Dictionary>() { { OpCodes.Add.Value, new KeyValuePair(OpCodes.Add, VMProtect.OpCodes.icAdd) }, { OpCodes.Add_Ovf.Value, new KeyValuePair(OpCodes.Add_Ovf, VMProtect.OpCodes.icAdd_ovf) }, { OpCodes.Add_Ovf_Un.Value, new KeyValuePair(OpCodes.Add_Ovf_Un, VMProtect.OpCodes.icAdd_ovf_un) }, { OpCodes.And.Value, new KeyValuePair(OpCodes.And, VMProtect.OpCodes.icAnd) }, //{ OpCodes.Arglist.Value, new KeyValuePair(OpCodes.Arglist, VMProtect.OpCodes.icArglist) }, { OpCodes.Beq_S.Value, new KeyValuePair(OpCodes.Beq_S, VMProtect.OpCodes.icBeq) }, { OpCodes.Bge_S.Value, new KeyValuePair(OpCodes.Bge_S, VMProtect.OpCodes.icBge) }, { OpCodes.Bge_Un_S.Value, new KeyValuePair(OpCodes.Bge_Un_S, VMProtect.OpCodes.icBge_un) }, { OpCodes.Bgt_S.Value, new KeyValuePair(OpCodes.Bgt_S, VMProtect.OpCodes.icBgt) }, { OpCodes.Bgt_Un_S.Value, new KeyValuePair(OpCodes.Bgt_Un_S, VMProtect.OpCodes.icBgt_un) }, { OpCodes.Ble_S.Value, new KeyValuePair(OpCodes.Ble_S, VMProtect.OpCodes.icBle) }, { OpCodes.Ble_Un_S.Value, new KeyValuePair(OpCodes.Ble_Un_S, VMProtect.OpCodes.icBle_un) }, { OpCodes.Blt_S.Value, new KeyValuePair(OpCodes.Blt_S, VMProtect.OpCodes.icBlt) }, { OpCodes.Blt_Un_S.Value, new KeyValuePair(OpCodes.Blt_Un_S, VMProtect.OpCodes.icBlt_un) }, { OpCodes.Bne_Un_S.Value, new KeyValuePair(OpCodes.Bne_Un_S, VMProtect.OpCodes.icBne_un) }, //{ OpCodes.Box.Value, new KeyValuePair(OpCodes.Box, VMProtect.OpCodes.icBox) }, { OpCodes.Br_S.Value, new KeyValuePair(OpCodes.Br_S, VMProtect.OpCodes.icBr) }, //{ OpCodes.Break.Value, new KeyValuePair(OpCodes.Break, VMProtect.OpCodes.icBreak) }, //{ OpCodes.Brfalse_S.Value, new KeyValuePair(OpCodes.Brfalse_S, VMProtect.OpCodes.icBrfalse_S) }, //{ OpCodes.Brtrue_S.Value, new KeyValuePair(OpCodes.Brtrue_S, VMProtect.OpCodes.icBrtrue_S) }, { OpCodes.Call.Value, new KeyValuePair(OpCodes.Call, VMProtect.OpCodes.icCall) }, //{ OpCodes.Calli.Value, new KeyValuePair(OpCodes.Calli, VMProtect.OpCodes.icCalli) }, //{ OpCodes.Callvirt.Value, new KeyValuePair(OpCodes.Callvirt, VMProtect.OpCodes.icCallvirt) }, //{ OpCodes.Castclass.Value, new KeyValuePair(OpCodes.Castclass, VMProtect.OpCodes.icCastclass) }, { OpCodes.Ceq.Value, new KeyValuePair(OpCodes.Ceq, VMProtect.OpCodes.icCeq) }, { OpCodes.Cgt.Value, new KeyValuePair(OpCodes.Cgt, VMProtect.OpCodes.icCgt) }, { OpCodes.Cgt_Un.Value, new KeyValuePair(OpCodes.Cgt_Un, VMProtect.OpCodes.icCgt_un) }, { OpCodes.Ckfinite.Value, new KeyValuePair(OpCodes.Ckfinite, VMProtect.OpCodes.icCkfinite) }, { OpCodes.Clt.Value, new KeyValuePair(OpCodes.Clt, VMProtect.OpCodes.icClt) }, { OpCodes.Clt_Un.Value, new KeyValuePair(OpCodes.Clt_Un, VMProtect.OpCodes.icClt_un) }, //{ OpCodes.Constrained.Value, new KeyValuePair(OpCodes.Constrained, VMProtect.OpCodes.icConstrained) }, { OpCodes.Conv_I.Value, new KeyValuePair(OpCodes.Conv_I, VMProtect.OpCodes.icConv_i) }, { OpCodes.Conv_I1.Value, new KeyValuePair(OpCodes.Conv_I1, VMProtect.OpCodes.icConv_i1) }, { OpCodes.Conv_I2.Value, new KeyValuePair(OpCodes.Conv_I2, VMProtect.OpCodes.icConv_i2) }, { OpCodes.Conv_I4.Value, new KeyValuePair(OpCodes.Conv_I4, VMProtect.OpCodes.icConv_i4) }, { OpCodes.Conv_I8.Value, new KeyValuePair(OpCodes.Conv_I8, VMProtect.OpCodes.icConv_i8) }, { OpCodes.Conv_Ovf_I.Value, new KeyValuePair(OpCodes.Conv_Ovf_I, VMProtect.OpCodes.icConv_ovf_i) }, { OpCodes.Conv_Ovf_I_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I_Un, VMProtect.OpCodes.icConv_ovf_i_un) }, { OpCodes.Conv_Ovf_I1.Value, new KeyValuePair(OpCodes.Conv_Ovf_I1, VMProtect.OpCodes.icConv_ovf_i1) }, { OpCodes.Conv_Ovf_I1_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I1_Un, VMProtect.OpCodes.icConv_ovf_i1_un) }, { OpCodes.Conv_Ovf_I2.Value, new KeyValuePair(OpCodes.Conv_Ovf_I2, VMProtect.OpCodes.icConv_ovf_i2) }, { OpCodes.Conv_Ovf_I2_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I2_Un, VMProtect.OpCodes.icConv_ovf_i2_un) }, { OpCodes.Conv_Ovf_I4.Value, new KeyValuePair(OpCodes.Conv_Ovf_I4, VMProtect.OpCodes.icConv_ovf_i4) }, { OpCodes.Conv_Ovf_I4_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I4_Un, VMProtect.OpCodes.icConv_ovf_i4_un) }, { OpCodes.Conv_Ovf_I8.Value, new KeyValuePair(OpCodes.Conv_Ovf_I8, VMProtect.OpCodes.icConv_ovf_i8) }, { OpCodes.Conv_Ovf_I8_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I8_Un, VMProtect.OpCodes.icConv_ovf_i8_un) }, { OpCodes.Conv_Ovf_U.Value, new KeyValuePair(OpCodes.Conv_Ovf_U, VMProtect.OpCodes.icConv_ovf_u) }, { OpCodes.Conv_Ovf_U_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U_Un, VMProtect.OpCodes.icConv_ovf_u_un) }, { OpCodes.Conv_Ovf_U1.Value, new KeyValuePair(OpCodes.Conv_Ovf_U1, VMProtect.OpCodes.icConv_ovf_u1) }, { OpCodes.Conv_Ovf_U1_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U1_Un, VMProtect.OpCodes.icConv_ovf_u1_un) }, { OpCodes.Conv_Ovf_U2.Value, new KeyValuePair(OpCodes.Conv_Ovf_U2, VMProtect.OpCodes.icConv_ovf_u2) }, { OpCodes.Conv_Ovf_U2_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U2_Un, VMProtect.OpCodes.icConv_ovf_u2_un) }, { OpCodes.Conv_Ovf_U4.Value, new KeyValuePair(OpCodes.Conv_Ovf_U4, VMProtect.OpCodes.icConv_ovf_u4) }, { OpCodes.Conv_Ovf_U4_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U4_Un, VMProtect.OpCodes.icConv_ovf_u4_un) }, { OpCodes.Conv_Ovf_U8.Value, new KeyValuePair(OpCodes.Conv_Ovf_U8, VMProtect.OpCodes.icConv_ovf_u8) }, { OpCodes.Conv_Ovf_U8_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U8_Un, VMProtect.OpCodes.icConv_ovf_u8_un) }, { OpCodes.Conv_R_Un.Value, new KeyValuePair(OpCodes.Conv_R_Un, VMProtect.OpCodes.icConv_r_un) }, { OpCodes.Conv_R4.Value, new KeyValuePair(OpCodes.Conv_R4, VMProtect.OpCodes.icConv_r4) }, { OpCodes.Conv_R8.Value, new KeyValuePair(OpCodes.Conv_R8, VMProtect.OpCodes.icConv_r8) }, { OpCodes.Conv_U.Value, new KeyValuePair(OpCodes.Conv_U, VMProtect.OpCodes.icConv_u) }, { OpCodes.Conv_U1.Value, new KeyValuePair(OpCodes.Conv_U1, VMProtect.OpCodes.icConv_u1) }, { OpCodes.Conv_U2.Value, new KeyValuePair(OpCodes.Conv_U2, VMProtect.OpCodes.icConv_u2) }, { OpCodes.Conv_U4.Value, new KeyValuePair(OpCodes.Conv_U4, VMProtect.OpCodes.icConv_u4) }, { OpCodes.Conv_U8.Value, new KeyValuePair(OpCodes.Conv_U8, VMProtect.OpCodes.icConv_u8) }, //{ OpCodes.Cpblk.Value, new KeyValuePair(OpCodes.Cpblk, VMProtect.OpCodes.icCpblk) }, //{ OpCodes.Cpobj.Value, new KeyValuePair(OpCodes.Cpobj, VMProtect.OpCodes.icCpobj) }, { OpCodes.Div.Value, new KeyValuePair(OpCodes.Div, VMProtect.OpCodes.icDiv) }, { OpCodes.Div_Un.Value, new KeyValuePair(OpCodes.Div_Un, VMProtect.OpCodes.icDiv_un) }, //{ OpCodes.Dup.Value, new KeyValuePair(OpCodes.Dup, VMProtect.OpCodes.icDup) }, //{ OpCodes.Endfilter.Value, new KeyValuePair(OpCodes.Endfilter, VMProtect.OpCodes.icEndfilter) }, //{ OpCodes.Endfinally.Value, new KeyValuePair(OpCodes.Endfinally, VMProtect.OpCodes.icEndfinally) }, //{ OpCodes.Initblk.Value, new KeyValuePair(OpCodes.Initblk, VMProtect.OpCodes.icInitblk) }, //{ OpCodes.Initobj.Value, new KeyValuePair(OpCodes.Initobj, VMProtect.OpCodes.icInitobj) }, //{ OpCodes.Isinst.Value, new KeyValuePair(OpCodes.Isinst, VMProtect.OpCodes.icIsinst) }, //{ OpCodes.Jmp.Value, new KeyValuePair(OpCodes.Jmp, VMProtect.OpCodes.icJmp) }, //{ OpCodes.Ldarg.Value, new KeyValuePair(OpCodes.Ldarg, VMProtect.OpCodes.icLdarg) }, { OpCodes.Ldarg_0.Value, new KeyValuePair(OpCodes.Ldarg_0, VMProtect.OpCodes.icLdarg_0) }, { OpCodes.Ldarg_1.Value, new KeyValuePair(OpCodes.Ldarg_1, VMProtect.OpCodes.icLdarg_1) }, //{ OpCodes.Ldarg_2.Value, new KeyValuePair(OpCodes.Ldarg_2, VMProtect.OpCodes.icLdarg_2) }, //{ OpCodes.Ldarg_3.Value, new KeyValuePair(OpCodes.Ldarg_3, VMProtect.OpCodes.icLdarg_3) }, //{ OpCodes.Ldarg_S.Value, new KeyValuePair(OpCodes.Ldarg_S, VMProtect.OpCodes.icLdarg_S) }, //{ OpCodes.Ldarga.Value, new KeyValuePair(OpCodes.Ldarga, VMProtect.OpCodes.icLdarga) }, { OpCodes.Ldarga_S.Value, new KeyValuePair(OpCodes.Ldarga_S, VMProtect.OpCodes.icLdarga_s) }, { OpCodes.Ldc_I4.Value, new KeyValuePair(OpCodes.Ldc_I4, VMProtect.OpCodes.icLdc_i4) }, { OpCodes.Ldc_I4_0.Value, new KeyValuePair(OpCodes.Ldc_I4_0, VMProtect.OpCodes.icLdc_i4_0) }, { OpCodes.Ldc_I4_1.Value, new KeyValuePair(OpCodes.Ldc_I4_1, VMProtect.OpCodes.icLdc_i4_1) }, { OpCodes.Ldc_I4_2.Value, new KeyValuePair(OpCodes.Ldc_I4_2, VMProtect.OpCodes.icLdc_i4_2) }, //{ OpCodes.Ldc_I4_3.Value, new KeyValuePair(OpCodes.Ldc_I4_3, VMProtect.OpCodes.icLdc_I4_3) }, //{ OpCodes.Ldc_I4_4.Value, new KeyValuePair(OpCodes.Ldc_I4_4, VMProtect.OpCodes.icLdc_I4_4) }, //{ OpCodes.Ldc_I4_5.Value, new KeyValuePair(OpCodes.Ldc_I4_5, VMProtect.OpCodes.icLdc_I4_5) }, //{ OpCodes.Ldc_I4_6.Value, new KeyValuePair(OpCodes.Ldc_I4_6, VMProtect.OpCodes.icLdc_I4_6) }, //{ OpCodes.Ldc_I4_7.Value, new KeyValuePair(OpCodes.Ldc_I4_7, VMProtect.OpCodes.icLdc_I4_7) }, //{ OpCodes.Ldc_I4_8.Value, new KeyValuePair(OpCodes.Ldc_I4_8, VMProtect.OpCodes.icLdc_I4_8) }, //{ OpCodes.Ldc_I4_M1.Value, new KeyValuePair(OpCodes.Ldc_I4_M1, VMProtect.OpCodes.icLdc_I4_M1) }, //{ OpCodes.Ldc_I4_S.Value, new KeyValuePair(OpCodes.Ldc_I4_S, VMProtect.OpCodes.icLdc_I4_S) }, //{ OpCodes.Ldc_I8.Value, new KeyValuePair(OpCodes.Ldc_I8, VMProtect.OpCodes.icLdc_I8) }, //{ OpCodes.Ldc_R4.Value, new KeyValuePair(OpCodes.Ldc_R4, VMProtect.OpCodes.icLdc_R4) }, //{ OpCodes.Ldc_R8.Value, new KeyValuePair(OpCodes.Ldc_R8, VMProtect.OpCodes.icLdc_R8) }, //{ OpCodes.Ldelem.Value, new KeyValuePair(OpCodes.Ldelem, VMProtect.OpCodes.icLdelem) }, //{ OpCodes.Ldelem_I.Value, new KeyValuePair(OpCodes.Ldelem_I, VMProtect.OpCodes.icLdelem_I) }, //{ OpCodes.Ldelem_I1.Value, new KeyValuePair(OpCodes.Ldelem_I1, VMProtect.OpCodes.icLdelem_I1) }, //{ OpCodes.Ldelem_I2.Value, new KeyValuePair(OpCodes.Ldelem_I2, VMProtect.OpCodes.icLdelem_I2) }, //{ OpCodes.Ldelem_I4.Value, new KeyValuePair(OpCodes.Ldelem_I4, VMProtect.OpCodes.icLdelem_I4) }, //{ OpCodes.Ldelem_I8.Value, new KeyValuePair(OpCodes.Ldelem_I8, VMProtect.OpCodes.icLdelem_I8) }, //{ OpCodes.Ldelem_R4.Value, new KeyValuePair(OpCodes.Ldelem_R4, VMProtect.OpCodes.icLdelem_R4) }, //{ OpCodes.Ldelem_R8.Value, new KeyValuePair(OpCodes.Ldelem_R8, VMProtect.OpCodes.icLdelem_R8) }, //{ OpCodes.Ldelem_Ref.Value, new KeyValuePair(OpCodes.Ldelem_Ref, VMProtect.OpCodes.icLdelem_Ref) }, //{ OpCodes.Ldelem_U1.Value, new KeyValuePair(OpCodes.Ldelem_U1, VMProtect.OpCodes.icLdelem_U1) }, //{ OpCodes.Ldelem_U2.Value, new KeyValuePair(OpCodes.Ldelem_U2, VMProtect.OpCodes.icLdelem_U2) }, //{ OpCodes.Ldelem_U4.Value, new KeyValuePair(OpCodes.Ldelem_U4, VMProtect.OpCodes.icLdelem_U4) }, //{ OpCodes.Ldelema.Value, new KeyValuePair(OpCodes.Ldelema, VMProtect.OpCodes.icLdelema) }, //{ OpCodes.Ldfld.Value, new KeyValuePair(OpCodes.Ldfld, VMProtect.OpCodes.icLdfld) }, //{ OpCodes.Ldflda.Value, new KeyValuePair(OpCodes.Ldflda, VMProtect.OpCodes.icLdflda) }, //{ OpCodes.Ldftn.Value, new KeyValuePair(OpCodes.Ldftn, VMProtect.OpCodes.icLdftn) }, //{ OpCodes.Ldind_I.Value, new KeyValuePair(OpCodes.Ldind_I, VMProtect.OpCodes.icLdind_I) }, //{ OpCodes.Ldind_I1.Value, new KeyValuePair(OpCodes.Ldind_I1, VMProtect.OpCodes.icLdind_I1) }, //{ OpCodes.Ldind_I2.Value, new KeyValuePair(OpCodes.Ldind_I2, VMProtect.OpCodes.icLdind_I2) }, //{ OpCodes.Ldind_I4.Value, new KeyValuePair(OpCodes.Ldind_I4, VMProtect.OpCodes.icLdind_I4) }, //{ OpCodes.Ldind_I8.Value, new KeyValuePair(OpCodes.Ldind_I8, VMProtect.OpCodes.icLdind_I8) }, //{ OpCodes.Ldind_R4.Value, new KeyValuePair(OpCodes.Ldind_R4, VMProtect.OpCodes.icLdind_R4) }, //{ OpCodes.Ldind_R8.Value, new KeyValuePair(OpCodes.Ldind_R8, VMProtect.OpCodes.icLdind_R8) }, //{ OpCodes.Ldind_Ref.Value, new KeyValuePair(OpCodes.Ldind_Ref, VMProtect.OpCodes.icLdind_Ref) }, //{ OpCodes.Ldind_U1.Value, new KeyValuePair(OpCodes.Ldind_U1, VMProtect.OpCodes.icLdind_U1) }, //{ OpCodes.Ldind_U2.Value, new KeyValuePair(OpCodes.Ldind_U2, VMProtect.OpCodes.icLdind_U2) }, //{ OpCodes.Ldind_U4.Value, new KeyValuePair(OpCodes.Ldind_U4, VMProtect.OpCodes.icLdind_U4) }, //{ OpCodes.Ldlen.Value, new KeyValuePair(OpCodes.Ldlen, VMProtect.OpCodes.icLdlen) }, //{ OpCodes.Ldloc.Value, new KeyValuePair(OpCodes.Ldloc, VMProtect.OpCodes.icLdloc) }, { OpCodes.Ldloc_0.Value, new KeyValuePair(OpCodes.Ldloc_0, VMProtect.OpCodes.icLdloc_0) }, //{ OpCodes.Ldloc_1.Value, new KeyValuePair(OpCodes.Ldloc_1, VMProtect.OpCodes.icLdloc_1) }, //{ OpCodes.Ldloc_2.Value, new KeyValuePair(OpCodes.Ldloc_2, VMProtect.OpCodes.icLdloc_2) }, //{ OpCodes.Ldloc_3.Value, new KeyValuePair(OpCodes.Ldloc_3, VMProtect.OpCodes.icLdloc_3) }, //{ OpCodes.Ldloc_S.Value, new KeyValuePair(OpCodes.Ldloc_S, VMProtect.OpCodes.icLdloc_S) }, //{ OpCodes.Ldloca.Value, new KeyValuePair(OpCodes.Ldloca, VMProtect.OpCodes.icLdloca) }, //{ OpCodes.Ldloca_S.Value, new KeyValuePair(OpCodes.Ldloca_S, VMProtect.OpCodes.icLdloca_S) }, { OpCodes.Ldnull.Value, new KeyValuePair(OpCodes.Ldnull, VMProtect.OpCodes.icLdnull) }, //{ OpCodes.Ldobj.Value, new KeyValuePair(OpCodes.Ldobj, VMProtect.OpCodes.icLdobj) }, //{ OpCodes.Ldsfld.Value, new KeyValuePair(OpCodes.Ldsfld, VMProtect.OpCodes.icLdsfld) }, //{ OpCodes.Ldsflda.Value, new KeyValuePair(OpCodes.Ldsflda, VMProtect.OpCodes.icLdsflda) }, //{ OpCodes.Ldstr.Value, new KeyValuePair(OpCodes.Ldstr, VMProtect.OpCodes.icLdstr) }, //{ OpCodes.Ldtoken.Value, new KeyValuePair(OpCodes.Ldtoken, VMProtect.OpCodes.icLdtoken) }, //{ OpCodes.Ldvirtftn.Value, new KeyValuePair(OpCodes.Ldvirtftn, VMProtect.OpCodes.icLdvirtftn) }, //{ OpCodes.Leave.Value, new KeyValuePair(OpCodes.Leave, VMProtect.OpCodes.icLeave) }, //{ OpCodes.Leave_S.Value, new KeyValuePair(OpCodes.Leave_S, VMProtect.OpCodes.icLeave_S) }, //{ OpCodes.Localloc.Value, new KeyValuePair(OpCodes.Localloc, VMProtect.OpCodes.icLocalloc) }, //{ OpCodes.Mkrefany.Value, new KeyValuePair(OpCodes.Mkrefany, VMProtect.OpCodes.icMkrefany) }, { OpCodes.Mul.Value, new KeyValuePair(OpCodes.Mul, VMProtect.OpCodes.icMul) }, { OpCodes.Mul_Ovf.Value, new KeyValuePair(OpCodes.Mul_Ovf, VMProtect.OpCodes.icMul_ovf) }, { OpCodes.Mul_Ovf_Un.Value, new KeyValuePair(OpCodes.Mul_Ovf_Un, VMProtect.OpCodes.icMul_ovf_un) }, //{ OpCodes.Neg.Value, new KeyValuePair(OpCodes.Neg, VMProtect.OpCodes.icNeg) }, //{ OpCodes.Newarr.Value, new KeyValuePair(OpCodes.Newarr, VMProtect.OpCodes.icNewarr) }, { OpCodes.Newobj.Value, new KeyValuePair(OpCodes.Newobj, VMProtect.OpCodes.icNewobj) }, { OpCodes.Nop.Value, new KeyValuePair(OpCodes.Nop, VMProtect.OpCodes.icNop) }, { OpCodes.Not.Value, new KeyValuePair(OpCodes.Not, VMProtect.OpCodes.icNot) }, { OpCodes.Or.Value, new KeyValuePair(OpCodes.Or, VMProtect.OpCodes.icOr) }, //{ OpCodes.Pop.Value, new KeyValuePair(OpCodes.Pop, VMProtect.OpCodes.icPop) }, //{ OpCodes.Prefix1.Value, new KeyValuePair(OpCodes.Prefix1, VMProtect.OpCodes.icPrefix1) }, //{ OpCodes.Prefix2.Value, new KeyValuePair(OpCodes.Prefix2, VMProtect.OpCodes.icPrefix2) }, //{ OpCodes.Prefix3.Value, new KeyValuePair(OpCodes.Prefix3, VMProtect.OpCodes.icPrefix3) }, //{ OpCodes.Prefix4.Value, new KeyValuePair(OpCodes.Prefix4, VMProtect.OpCodes.icPrefix4) }, //{ OpCodes.Prefix5.Value, new KeyValuePair(OpCodes.Prefix5, VMProtect.OpCodes.icPrefix5) }, //{ OpCodes.Prefix6.Value, new KeyValuePair(OpCodes.Prefix6, VMProtect.OpCodes.icPrefix6) }, //{ OpCodes.Prefix7.Value, new KeyValuePair(OpCodes.Prefix7, VMProtect.OpCodes.icPrefix7) }, //{ OpCodes.Prefixref.Value, new KeyValuePair(OpCodes.Prefixref, VMProtect.OpCodes.icPrefixref) }, //{ OpCodes.Readonly.Value, new KeyValuePair(OpCodes.Readonly, VMProtect.OpCodes.icReadonly) }, //{ OpCodes.Refanytype.Value, new KeyValuePair(OpCodes.Refanytype, VMProtect.OpCodes.icRefanytype) }, //{ OpCodes.Refanyval.Value, new KeyValuePair(OpCodes.Refanyval, VMProtect.OpCodes.icRefanyval) }, { OpCodes.Rem.Value, new KeyValuePair(OpCodes.Rem, VMProtect.OpCodes.icRem) }, { OpCodes.Rem_Un.Value, new KeyValuePair(OpCodes.Rem_Un, VMProtect.OpCodes.icRem_un) }, { OpCodes.Ret.Value, new KeyValuePair(OpCodes.Ret, VMProtect.OpCodes.icRet) }, //{ OpCodes.Rethrow.Value, new KeyValuePair(OpCodes.Rethrow, VMProtect.OpCodes.icRethrow) }, { OpCodes.Shl.Value, new KeyValuePair(OpCodes.Shl, VMProtect.OpCodes.icShl) }, { OpCodes.Shr.Value, new KeyValuePair(OpCodes.Shr, VMProtect.OpCodes.icShr) }, { OpCodes.Shr_Un.Value, new KeyValuePair(OpCodes.Shr_Un, VMProtect.OpCodes.icShr_un) }, //{ OpCodes.Sizeof.Value, new KeyValuePair(OpCodes.Sizeof, VMProtect.OpCodes.icSizeof) }, //{ OpCodes.Starg.Value, new KeyValuePair(OpCodes.Starg, VMProtect.OpCodes.icStarg) }, //{ OpCodes.Starg_S.Value, new KeyValuePair(OpCodes.Starg_S, VMProtect.OpCodes.icStarg_S) }, //{ OpCodes.Stelem.Value, new KeyValuePair(OpCodes.Stelem, VMProtect.OpCodes.icStelem) }, //{ OpCodes.Stelem_I.Value, new KeyValuePair(OpCodes.Stelem_I, VMProtect.OpCodes.icStelem_I) }, //{ OpCodes.Stelem_I1.Value, new KeyValuePair(OpCodes.Stelem_I1, VMProtect.OpCodes.icStelem_I1) }, { OpCodes.Stelem_I2.Value, new KeyValuePair(OpCodes.Stelem_I2, VMProtect.OpCodes.icStelem_i2) }, //{ OpCodes.Stelem_I4.Value, new KeyValuePair(OpCodes.Stelem_I4, VMProtect.OpCodes.icStelem_I4) }, //{ OpCodes.Stelem_I8.Value, new KeyValuePair(OpCodes.Stelem_I8, VMProtect.OpCodes.icStelem_I8) }, //{ OpCodes.Stelem_R4.Value, new KeyValuePair(OpCodes.Stelem_R4, VMProtect.OpCodes.icStelem_R4) }, //{ OpCodes.Stelem_R8.Value, new KeyValuePair(OpCodes.Stelem_R8, VMProtect.OpCodes.icStelem_R8) }, //{ OpCodes.Stelem_Ref.Value, new KeyValuePair(OpCodes.Stelem_Ref, VMProtect.OpCodes.icStelem_Ref) }, //{ OpCodes.Stfld.Value, new KeyValuePair(OpCodes.Stfld, VMProtect.OpCodes.icStfld) }, //{ OpCodes.Stind_I.Value, new KeyValuePair(OpCodes.Stind_I, VMProtect.OpCodes.icStind_I) }, //{ OpCodes.Stind_I1.Value, new KeyValuePair(OpCodes.Stind_I1, VMProtect.OpCodes.icStind_I1) }, //{ OpCodes.Stind_I2.Value, new KeyValuePair(OpCodes.Stind_I2, VMProtect.OpCodes.icStind_I2) }, //{ OpCodes.Stind_I4.Value, new KeyValuePair(OpCodes.Stind_I4, VMProtect.OpCodes.icStind_I4) }, //{ OpCodes.Stind_I8.Value, new KeyValuePair(OpCodes.Stind_I8, VMProtect.OpCodes.icStind_I8) }, //{ OpCodes.Stind_R4.Value, new KeyValuePair(OpCodes.Stind_R4, VMProtect.OpCodes.icStind_R4) }, //{ OpCodes.Stind_R8.Value, new KeyValuePair(OpCodes.Stind_R8, VMProtect.OpCodes.icStind_R8) }, //{ OpCodes.Stind_Ref.Value, new KeyValuePair(OpCodes.Stind_Ref, VMProtect.OpCodes.icStind_Ref) }, //{ OpCodes.Stloc.Value, new KeyValuePair(OpCodes.Stloc, VMProtect.OpCodes.icStloc) }, { OpCodes.Stloc_0.Value, new KeyValuePair(OpCodes.Stloc_0, VMProtect.OpCodes.icStloc_0) }, //{ OpCodes.Stloc_1.Value, new KeyValuePair(OpCodes.Stloc_1, VMProtect.OpCodes.icStloc_1) }, //{ OpCodes.Stloc_2.Value, new KeyValuePair(OpCodes.Stloc_2, VMProtect.OpCodes.icStloc_2) }, //{ OpCodes.Stloc_3.Value, new KeyValuePair(OpCodes.Stloc_3, VMProtect.OpCodes.icStloc_3) }, //{ OpCodes.Stloc_S.Value, new KeyValuePair(OpCodes.Stloc_S, VMProtect.OpCodes.icStloc_S) }, //{ OpCodes.Stobj.Value, new KeyValuePair(OpCodes.Stobj, VMProtect.OpCodes.icStobj) }, //{ OpCodes.Stsfld.Value, new KeyValuePair(OpCodes.Stsfld, VMProtect.OpCodes.icStsfld) }, { OpCodes.Sub.Value, new KeyValuePair(OpCodes.Sub, VMProtect.OpCodes.icSub) }, { OpCodes.Sub_Ovf.Value, new KeyValuePair(OpCodes.Sub_Ovf, VMProtect.OpCodes.icSub_ovf) }, { OpCodes.Sub_Ovf_Un.Value, new KeyValuePair(OpCodes.Sub_Ovf_Un, VMProtect.OpCodes.icSub_ovf_un) }, //{ OpCodes.Switch.Value, new KeyValuePair(OpCodes.Switch, VMProtect.OpCodes.icSwitch) }, //{ OpCodes.Tailcall.Value, new KeyValuePair(OpCodes.Tailcall, VMProtect.OpCodes.icTailcall) }, //{ OpCodes.Throw.Value, new KeyValuePair(OpCodes.Throw, VMProtect.OpCodes.icThrow) }, //{ OpCodes.Unaligned.Value, new KeyValuePair(OpCodes.Unaligned, VMProtect.OpCodes.icUnaligned) }, //{ OpCodes.Unbox.Value, new KeyValuePair(OpCodes.Unbox, VMProtect.OpCodes.icUnbox) }, //{ OpCodes.Unbox_Any.Value, new KeyValuePair(OpCodes.Unbox_Any, VMProtect.OpCodes.icUnbox_Any) }, //{ OpCodes.Volatile.Value, new KeyValuePair(OpCodes.Volatile, VMProtect.OpCodes.icVolatile) }, { OpCodes.Xor.Value, new KeyValuePair(OpCodes.Xor, VMProtect.OpCodes.icXor) }, }; #endregion private static readonly Dictionary TypeTokenInModule = new Dictionary(); //TypeDefs and TypeRefs private static int GetTypeTokenInModule(Type t) { var tryToken = 0x01000001; //first TypeRef var m = typeof (MsilToVmTestCompilerVmp).Module; while (true) { try { Type t1 = m.ResolveType(tryToken); TypeTokenInModule.Add(t1, tryToken++); } catch (Exception) { break; //until last TypeRef } } if (TypeTokenInModule.ContainsKey(t)) return TypeTokenInModule[t]; if (t.Module == m) { TypeTokenInModule.Add(t, t.MetadataToken); return t.MetadataToken; } Assert.Fail("Bad type {0}: not accessible from this module", t); return 0; } public override Stream CreateVmStream(Type rt, ParameterInfo[] pi, Type[] locals, byte[] ilBytes) { var ret = new MemoryStream(); var wr = new BinaryWriter(ret); var fwdTypeDefs = new Dictionary(); var fwdTypeRefs = new Dictionary(); var deferredBrTargets = new Dictionary(); var srcToDstInstrPositions = new Dictionary(); const int dummy = 0x55555555; fwdTypeDefs.Add(rt, dummy); var pars = pi; foreach (var parameterInfo in pars) { if (!fwdTypeDefs.ContainsKey(parameterInfo.ParameterType)) fwdTypeDefs.Add(parameterInfo.ParameterType, dummy); wr.Write((byte)VMProtect.OpCodes.icInitarg); fwdTypeRefs.Add((int)ret.Position, parameterInfo.ParameterType); wr.Write(dummy); // parTypeId fwd ref } foreach (var lt in locals) { if (!fwdTypeDefs.ContainsKey(lt)) fwdTypeDefs.Add(lt, dummy); // FIXME //wr.Write((byte)VMProtect.OpCodes.icInitloc); fwdTypeRefs.Add((int)ret.Position, lt); wr.Write(dummy); // parTypeId fwd ref } using (var sr = new BinaryReader(new MemoryStream(ilBytes))) { while (sr.BaseStream.Position < sr.BaseStream.Length) { srcToDstInstrPositions[sr.BaseStream.Position] = (uint)ret.Position; short ilByte = sr.ReadByte(); if (ilByte == 0xFE) ilByte = (short)((ilByte << 8) | sr.ReadByte()); Assert.IsTrue(IlToVmInstrInfo.ContainsKey(ilByte), "Extend IlToVmInstrInfo with {0:X} or use short jump", ilByte); var vmInstrInfo = IlToVmInstrInfo[ilByte]; ulong operand = 0; switch (vmInstrInfo.Key.OperandType) { case OperandType.InlineNone: break; case OperandType.InlineI8: case OperandType.InlineR: operand = sr.ReadUInt64(); break; case OperandType.InlineVar: operand = sr.ReadUInt16(); break; case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineVar: operand = sr.ReadByte(); break; default: operand = sr.ReadUInt32(); break; } switch ((short)vmInstrInfo.Value) { case (short)VMProtect.OpCodes.icNop: continue; case (short)VMProtect.OpCodes.icStloc_0: wr.Write((byte)VMProtect.OpCodes.icStloc); wr.Write((ushort)0); break; case (short)VMProtect.OpCodes.icStloc_1: wr.Write((byte)VMProtect.OpCodes.icStloc); wr.Write((ushort)1); break; case (short)VMProtect.OpCodes.icStloc_2: wr.Write((byte)VMProtect.OpCodes.icStloc); wr.Write((ushort)2); break; case (short)VMProtect.OpCodes.icStloc_3: wr.Write((byte)VMProtect.OpCodes.icStloc); wr.Write((ushort)3); break; case (short)VMProtect.OpCodes.icLdloc_0: wr.Write((byte)VMProtect.OpCodes.icLdloc); wr.Write((ushort)0); break; case (short)VMProtect.OpCodes.icLdloc_1: wr.Write((byte)VMProtect.OpCodes.icLdloc); wr.Write((ushort)1); break; case (short)VMProtect.OpCodes.icLdloc_2: wr.Write((byte)VMProtect.OpCodes.icLdloc); wr.Write((ushort)2); break; case (short)VMProtect.OpCodes.icLdloc_3: wr.Write((byte)VMProtect.OpCodes.icLdloc); wr.Write((ushort)3); break; case (short)VMProtect.OpCodes.icLdarg_0: wr.Write((byte)VMProtect.OpCodes.icLdarg); wr.Write((ushort)0); break; case (short)VMProtect.OpCodes.icLdarg_1: wr.Write((byte)VMProtect.OpCodes.icLdarg); wr.Write((ushort)1); break; case (short)VMProtect.OpCodes.icLdarg_2: wr.Write((byte)VMProtect.OpCodes.icLdarg); wr.Write((ushort)2); break; case (short)VMProtect.OpCodes.icLdarg_3: wr.Write((byte)VMProtect.OpCodes.icLdarg); wr.Write((ushort)3); break; case (short)VMProtect.OpCodes.icLdarga_s: wr.Write((byte)VMProtect.OpCodes.icLdarga); wr.Write((ushort)operand); break; case (short)VMProtect.OpCodes.icRet: wr.Write((byte)VMProtect.OpCodes.icRet); fwdTypeRefs.Add((int)ret.Position, rt); wr.Write(dummy); // ReturnTypeId fwd ref break; case (short)VMProtect.OpCodes.icLdc_i4_0: wr.Write((byte)VMProtect.OpCodes.icLdc_i4); wr.Write((uint)0); break; case (short)VMProtect.OpCodes.icLdc_i4_1: wr.Write((byte)VMProtect.OpCodes.icLdc_i4); wr.Write((uint)1); break; case (short)VMProtect.OpCodes.icLdc_i4_2: wr.Write((byte)VMProtect.OpCodes.icLdc_i4); wr.Write((uint)2); break; case (short)VMProtect.OpCodes.icLdc_i4_3: wr.Write((byte)VMProtect.OpCodes.icLdc_i4); wr.Write((uint)3); break; case (short)VMProtect.OpCodes.icBr: wr.Write((byte)VMProtect.OpCodes.icLdc_i4); deferredBrTargets[ret.Position] = (uint)sr.BaseStream.Position + (uint)operand; wr.Write(dummy); wr.Write((byte)VMProtect.OpCodes.icBr); break; case (short)VMProtect.OpCodes.icBeq: case (short)VMProtect.OpCodes.icBne_un: case (short)VMProtect.OpCodes.icBlt: case (short)VMProtect.OpCodes.icBlt_un: case (short)VMProtect.OpCodes.icBle: case (short)VMProtect.OpCodes.icBle_un: case (short)VMProtect.OpCodes.icBgt: case (short)VMProtect.OpCodes.icBgt_un: case (short)VMProtect.OpCodes.icBge: case (short)VMProtect.OpCodes.icBge_un: case (short)VMProtect.OpCodes.icBrtrue: case (short)VMProtect.OpCodes.icBrfalse: switch ((short)vmInstrInfo.Value) { // FIXME /* case (short)VMProtect.OpCodes.icBeq: case (short)VMProtect.OpCodes.icBne_un: wr.Write((byte)VMProtect.OpCodes.icCeq); break; case (short)VMProtect.OpCodes.icBge: wr.Write((byte)VMProtect.OpCodes.icCge); break; case (short)VMProtect.OpCodes.icBge_un: wr.Write((byte)VMProtect.OpCodes.icCge_un); break; case (short)VMProtect.OpCodes.icBlt: wr.Write((byte)VMProtect.OpCodes.icClt); break; case (short)VMProtect.OpCodes.icBlt_un: wr.Write((byte)VMProtect.OpCodes.icClt_un); break; case (short)VMProtect.OpCodes.icBle: wr.Write((byte)VMProtect.OpCodes.icCle); break; case (short)VMProtect.OpCodes.icBle_un: wr.Write((byte)VMProtect.OpCodes.icCle_un); break; case (short)VMProtect.OpCodes.icBgt: wr.Write((byte)VMProtect.OpCodes.icCgt); break; case (short)VMProtect.OpCodes.icBgt_un: wr.Write((byte)VMProtect.OpCodes.icCgt_un); break; */ } // FIXME //wr.Write((byte)VMProtect.OpCodes.icConv_b); wr.Write((byte)VMProtect.OpCodes.icNeg); switch ((short)vmInstrInfo.Value) { case (short)VMProtect.OpCodes.icBne_un: //case (short)VMProtect.OpCodes.icBle: //case (short)VMProtect.OpCodes.icBle_un: //case (short)VMProtect.OpCodes.icBge: //case (short)VMProtect.OpCodes.icBge_un: case (short)VMProtect.OpCodes.icBrfalse: wr.Write((byte)VMProtect.OpCodes.icNot); break; } wr.Write((byte)VMProtect.OpCodes.icLdc_i4); deferredBrTargets[ret.Position] = (uint)sr.BaseStream.Position + (uint)operand; wr.Write(dummy); wr.Write((byte)VMProtect.OpCodes.icAnd); wr.Write((byte)VMProtect.OpCodes.icDup); // FIXME //wr.Write((byte)VMProtect.OpCodes.icConv_b); wr.Write((byte)VMProtect.OpCodes.icNeg); wr.Write((byte)VMProtect.OpCodes.icNot); wr.Write((byte)VMProtect.OpCodes.icLdc_i4); deferredBrTargets[ret.Position] = (uint)sr.BaseStream.Position; wr.Write(dummy); wr.Write((byte)VMProtect.OpCodes.icAnd); wr.Write((byte)VMProtect.OpCodes.icAdd); wr.Write((byte)VMProtect.OpCodes.icBr); break; default: wr.Write((byte)vmInstrInfo.Value); break; } wr.Flush(); } foreach (var t in fwdTypeDefs.Keys.ToArray()) { fwdTypeDefs[t] = GetTypeTokenInModule(t); } foreach (var r in fwdTypeRefs) { ret.Position = r.Key; wr.Write(fwdTypeDefs[r.Value]); wr.Flush(); } foreach (var r in deferredBrTargets) { ret.Position = r.Key; var srcPos = r.Value; wr.Write(srcToDstInstrPositions[srcPos]); wr.Flush(); } ret.Position = 0; return ret; } } public override object Invoke(object[] parameters, Stream vmStream) { var contents = new BinaryReader(vmStream).ReadBytes((int) vmStream.Length); var unmanagedPointer = Marshal.AllocHGlobal(contents.Length); Marshal.Copy(contents, 0, unmanagedPointer, contents.Length); var vm = new VirtualMachine(); // ReSharper disable once PossibleNullReferenceException typeof(VirtualMachine).GetField("_instance", BindingFlags.Instance | BindingFlags.NonPublic) .SetValue(vm, unmanagedPointer.ToInt64()); var vmRet = vm.Invoke(parameters, 0); Marshal.FreeHGlobal(unmanagedPointer); return vmRet; } } public class MsilToVmTestCompilerRefVm : MsilToVmTestCompiler { public static readonly VmInstrCodesDb InstrCodesDb = new VmInstrCodesDb(); #region opcodes public static readonly Dictionary> IlToVmInstrInfo = new Dictionary>() { { OpCodes.Add.Value, new KeyValuePair(OpCodes.Add, InstrCodesDb.Add_) }, { OpCodes.Add_Ovf.Value, new KeyValuePair(OpCodes.Add_Ovf, InstrCodesDb.Add_ovf_) }, { OpCodes.Add_Ovf_Un.Value, new KeyValuePair(OpCodes.Add_Ovf_Un, InstrCodesDb.Add_ovf_un_) }, { OpCodes.And.Value, new KeyValuePair(OpCodes.And, InstrCodesDb.And_) }, //{ OpCodes.Arglist.Value, new KeyValuePair(OpCodes.Arglist, InstrCodesDb.Arglist_) }, { OpCodes.Beq_S.Value, new KeyValuePair(OpCodes.Beq_S, InstrCodesDb.Beq_) }, { OpCodes.Bge_S.Value, new KeyValuePair(OpCodes.Bge_S, InstrCodesDb.Bge_) }, { OpCodes.Bge_Un_S.Value, new KeyValuePair(OpCodes.Bge_Un_S, InstrCodesDb.Bge_un_) }, { OpCodes.Bgt_S.Value, new KeyValuePair(OpCodes.Bgt_S, InstrCodesDb.Bgt_) }, { OpCodes.Bgt_Un_S.Value, new KeyValuePair(OpCodes.Bgt_Un_S, InstrCodesDb.Bgt_un_) }, { OpCodes.Ble_S.Value, new KeyValuePair(OpCodes.Ble_S, InstrCodesDb.Ble_) }, { OpCodes.Ble_Un_S.Value, new KeyValuePair(OpCodes.Ble_Un_S, InstrCodesDb.Ble_un_) }, { OpCodes.Blt_S.Value, new KeyValuePair(OpCodes.Blt_S, InstrCodesDb.Blt_) }, { OpCodes.Blt_Un_S.Value, new KeyValuePair(OpCodes.Blt_Un_S, InstrCodesDb.Blt_un_) }, { OpCodes.Bne_Un_S.Value, new KeyValuePair(OpCodes.Bne_Un_S, InstrCodesDb.Bne_un_) }, //{ OpCodes.Box.Value, new KeyValuePair(OpCodes.Box, InstrCodesDb.Box_) }, { OpCodes.Br_S.Value, new KeyValuePair(OpCodes.Br_S, InstrCodesDb.Br_) }, //{ OpCodes.Break.Value, new KeyValuePair(OpCodes.Break, InstrCodesDb.Break_) }, //{ OpCodes.Brfalse_S.Value, new KeyValuePair(OpCodes.Brfalse_S, InstrCodesDb.Brfalse_S_) }, //{ OpCodes.Brtrue_S.Value, new KeyValuePair(OpCodes.Brtrue_S, InstrCodesDb.Brtrue_S_) }, { OpCodes.Call.Value, new KeyValuePair(OpCodes.Call, InstrCodesDb.Call_) }, //{ OpCodes.Calli.Value, new KeyValuePair(OpCodes.Calli, InstrCodesDb.Calli_) }, //{ OpCodes.Callvirt.Value, new KeyValuePair(OpCodes.Callvirt, InstrCodesDb.Callvirt_) }, //{ OpCodes.Castclass.Value, new KeyValuePair(OpCodes.Castclass, InstrCodesDb.Castclass_) }, { OpCodes.Ceq.Value, new KeyValuePair(OpCodes.Ceq, InstrCodesDb.Ceq_) }, { OpCodes.Cgt.Value, new KeyValuePair(OpCodes.Cgt, InstrCodesDb.Cgt_) }, { OpCodes.Cgt_Un.Value, new KeyValuePair(OpCodes.Cgt_Un, InstrCodesDb.Cgt_un_) }, { OpCodes.Ckfinite.Value, new KeyValuePair(OpCodes.Ckfinite, InstrCodesDb.Ckfinite_) }, { OpCodes.Clt.Value, new KeyValuePair(OpCodes.Clt, InstrCodesDb.Clt_) }, { OpCodes.Clt_Un.Value, new KeyValuePair(OpCodes.Clt_Un, InstrCodesDb.Clt_un_) }, //{ OpCodes.Constrained.Value, new KeyValuePair(OpCodes.Constrained, InstrCodesDb.Constrained_) }, { OpCodes.Conv_I.Value, new KeyValuePair(OpCodes.Conv_I, InstrCodesDb.Conv_i_) }, { OpCodes.Conv_I1.Value, new KeyValuePair(OpCodes.Conv_I1, InstrCodesDb.Conv_i1_) }, { OpCodes.Conv_I2.Value, new KeyValuePair(OpCodes.Conv_I2, InstrCodesDb.Conv_i2_) }, { OpCodes.Conv_I4.Value, new KeyValuePair(OpCodes.Conv_I4, InstrCodesDb.Conv_i4_) }, { OpCodes.Conv_I8.Value, new KeyValuePair(OpCodes.Conv_I8, InstrCodesDb.Conv_i8_) }, { OpCodes.Conv_Ovf_I.Value, new KeyValuePair(OpCodes.Conv_Ovf_I, InstrCodesDb.Conv_ovf_i_) }, { OpCodes.Conv_Ovf_I_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I_Un, InstrCodesDb.Conv_ovf_i_un_) }, { OpCodes.Conv_Ovf_I1.Value, new KeyValuePair(OpCodes.Conv_Ovf_I1, InstrCodesDb.Conv_ovf_i1_) }, { OpCodes.Conv_Ovf_I1_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I1_Un, InstrCodesDb.Conv_ovf_i1_un_) }, { OpCodes.Conv_Ovf_I2.Value, new KeyValuePair(OpCodes.Conv_Ovf_I2, InstrCodesDb.Conv_ovf_i2_) }, { OpCodes.Conv_Ovf_I2_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I2_Un, InstrCodesDb.Conv_ovf_i2_un_) }, { OpCodes.Conv_Ovf_I4.Value, new KeyValuePair(OpCodes.Conv_Ovf_I4, InstrCodesDb.Conv_ovf_i4_) }, { OpCodes.Conv_Ovf_I4_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I4_Un, InstrCodesDb.Conv_ovf_i4_un_) }, { OpCodes.Conv_Ovf_I8.Value, new KeyValuePair(OpCodes.Conv_Ovf_I8, InstrCodesDb.Conv_ovf_i8_) }, { OpCodes.Conv_Ovf_I8_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_I8_Un, InstrCodesDb.Conv_ovf_i8_un_) }, { OpCodes.Conv_Ovf_U.Value, new KeyValuePair(OpCodes.Conv_Ovf_U, InstrCodesDb.Conv_ovf_u_) }, { OpCodes.Conv_Ovf_U_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U_Un, InstrCodesDb.Conv_ovf_u_un_) }, { OpCodes.Conv_Ovf_U1.Value, new KeyValuePair(OpCodes.Conv_Ovf_U1, InstrCodesDb.Conv_ovf_u1_) }, { OpCodes.Conv_Ovf_U1_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U1_Un, InstrCodesDb.Conv_ovf_u1_un_) }, { OpCodes.Conv_Ovf_U2.Value, new KeyValuePair(OpCodes.Conv_Ovf_U2, InstrCodesDb.Conv_ovf_u2_) }, { OpCodes.Conv_Ovf_U2_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U2_Un, InstrCodesDb.Conv_ovf_u2_un_) }, { OpCodes.Conv_Ovf_U4.Value, new KeyValuePair(OpCodes.Conv_Ovf_U4, InstrCodesDb.Conv_ovf_u4_) }, { OpCodes.Conv_Ovf_U4_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U4_Un, InstrCodesDb.Conv_ovf_u4_un_) }, { OpCodes.Conv_Ovf_U8.Value, new KeyValuePair(OpCodes.Conv_Ovf_U8, InstrCodesDb.Conv_ovf_u8_) }, { OpCodes.Conv_Ovf_U8_Un.Value, new KeyValuePair(OpCodes.Conv_Ovf_U8_Un, InstrCodesDb.Conv_ovf_u8_un_) }, { OpCodes.Conv_R_Un.Value, new KeyValuePair(OpCodes.Conv_R_Un, InstrCodesDb.Conv_r_un_) }, { OpCodes.Conv_R4.Value, new KeyValuePair(OpCodes.Conv_R4, InstrCodesDb.Conv_r4_) }, { OpCodes.Conv_R8.Value, new KeyValuePair(OpCodes.Conv_R8, InstrCodesDb.Conv_r8_) }, { OpCodes.Conv_U.Value, new KeyValuePair(OpCodes.Conv_U, InstrCodesDb.Conv_u_) }, { OpCodes.Conv_U1.Value, new KeyValuePair(OpCodes.Conv_U1, InstrCodesDb.Conv_u1_) }, { OpCodes.Conv_U2.Value, new KeyValuePair(OpCodes.Conv_U2, InstrCodesDb.Conv_u2_) }, { OpCodes.Conv_U4.Value, new KeyValuePair(OpCodes.Conv_U4, InstrCodesDb.Conv_u4_) }, { OpCodes.Conv_U8.Value, new KeyValuePair(OpCodes.Conv_U8, InstrCodesDb.Conv_u8_) }, //{ OpCodes.Cpblk.Value, new KeyValuePair(OpCodes.Cpblk, InstrCodesDb.Cpblk_) }, //{ OpCodes.Cpobj.Value, new KeyValuePair(OpCodes.Cpobj, InstrCodesDb.Cpobj_) }, { OpCodes.Div.Value, new KeyValuePair(OpCodes.Div, InstrCodesDb.Div_) }, { OpCodes.Div_Un.Value, new KeyValuePair(OpCodes.Div_Un, InstrCodesDb.Div_un_) }, //{ OpCodes.Dup.Value, new KeyValuePair(OpCodes.Dup, InstrCodesDb.Dup_) }, //{ OpCodes.Endfilter.Value, new KeyValuePair(OpCodes.Endfilter, InstrCodesDb.Endfilter_) }, //{ OpCodes.Endfinally.Value, new KeyValuePair(OpCodes.Endfinally, InstrCodesDb.Endfinally_) }, //{ OpCodes.Initblk.Value, new KeyValuePair(OpCodes.Initblk, InstrCodesDb.Initblk_) }, //{ OpCodes.Initobj.Value, new KeyValuePair(OpCodes.Initobj, InstrCodesDb.Initobj_) }, //{ OpCodes.Isinst.Value, new KeyValuePair(OpCodes.Isinst, InstrCodesDb.Isinst_) }, //{ OpCodes.Jmp.Value, new KeyValuePair(OpCodes.Jmp, InstrCodesDb.Jmp_) }, //{ OpCodes.Ldarg.Value, new KeyValuePair(OpCodes.Ldarg, InstrCodesDb.Ldarg_) }, { OpCodes.Ldarg_0.Value, new KeyValuePair(OpCodes.Ldarg_0, InstrCodesDb.Ldarg_0_) }, { OpCodes.Ldarg_1.Value, new KeyValuePair(OpCodes.Ldarg_1, InstrCodesDb.Ldarg_1_) }, //{ OpCodes.Ldarg_2.Value, new KeyValuePair(OpCodes.Ldarg_2, InstrCodesDb.Ldarg_2_) }, //{ OpCodes.Ldarg_3.Value, new KeyValuePair(OpCodes.Ldarg_3, InstrCodesDb.Ldarg_3_) }, //{ OpCodes.Ldarg_S.Value, new KeyValuePair(OpCodes.Ldarg_S, InstrCodesDb.Ldarg_S_) }, //{ OpCodes.Ldarga.Value, new KeyValuePair(OpCodes.Ldarga, InstrCodesDb.Ldarga_) }, { OpCodes.Ldarga_S.Value, new KeyValuePair(OpCodes.Ldarga_S, InstrCodesDb.Ldarga_s_) }, //{ OpCodes.Ldc_I4.Value, new KeyValuePair(OpCodes.Ldc_I4, InstrCodesDb.Ldc_i4_) }, { OpCodes.Ldc_I4_0.Value, new KeyValuePair(OpCodes.Ldc_I4_0, InstrCodesDb.Ldc_i4_0_) }, { OpCodes.Ldc_I4_1.Value, new KeyValuePair(OpCodes.Ldc_I4_1, InstrCodesDb.Ldc_i4_1_) }, //{ OpCodes.Ldc_I4_2.Value, new KeyValuePair(OpCodes.Ldc_I4_2, InstrCodesDb.Ldc_i4_2_) }, //{ OpCodes.Ldc_I4_3.Value, new KeyValuePair(OpCodes.Ldc_I4_3, InstrCodesDb.Ldc_I4_3_) }, //{ OpCodes.Ldc_I4_4.Value, new KeyValuePair(OpCodes.Ldc_I4_4, InstrCodesDb.Ldc_I4_4_) }, //{ OpCodes.Ldc_I4_5.Value, new KeyValuePair(OpCodes.Ldc_I4_5, InstrCodesDb.Ldc_I4_5_) }, //{ OpCodes.Ldc_I4_6.Value, new KeyValuePair(OpCodes.Ldc_I4_6, InstrCodesDb.Ldc_I4_6_) }, //{ OpCodes.Ldc_I4_7.Value, new KeyValuePair(OpCodes.Ldc_I4_7, InstrCodesDb.Ldc_I4_7_) }, //{ OpCodes.Ldc_I4_8.Value, new KeyValuePair(OpCodes.Ldc_I4_8, InstrCodesDb.Ldc_I4_8_) }, //{ OpCodes.Ldc_I4_M1.Value, new KeyValuePair(OpCodes.Ldc_I4_M1, InstrCodesDb.Ldc_I4_M1_) }, //{ OpCodes.Ldc_I4_S.Value, new KeyValuePair(OpCodes.Ldc_I4_S, InstrCodesDb.Ldc_I4_S_) }, //{ OpCodes.Ldc_I8.Value, new KeyValuePair(OpCodes.Ldc_I8, InstrCodesDb.Ldc_I8_) }, //{ OpCodes.Ldc_R4.Value, new KeyValuePair(OpCodes.Ldc_R4, InstrCodesDb.Ldc_R4_) }, //{ OpCodes.Ldc_R8.Value, new KeyValuePair(OpCodes.Ldc_R8, InstrCodesDb.Ldc_R8_) }, //{ OpCodes.Ldelem.Value, new KeyValuePair(OpCodes.Ldelem, InstrCodesDb.Ldelem_) }, //{ OpCodes.Ldelem_I.Value, new KeyValuePair(OpCodes.Ldelem_I, InstrCodesDb.Ldelem_I_) }, //{ OpCodes.Ldelem_I1.Value, new KeyValuePair(OpCodes.Ldelem_I1, InstrCodesDb.Ldelem_I1_) }, //{ OpCodes.Ldelem_I2.Value, new KeyValuePair(OpCodes.Ldelem_I2, InstrCodesDb.Ldelem_I2_) }, //{ OpCodes.Ldelem_I4.Value, new KeyValuePair(OpCodes.Ldelem_I4, InstrCodesDb.Ldelem_I4_) }, //{ OpCodes.Ldelem_I8.Value, new KeyValuePair(OpCodes.Ldelem_I8, InstrCodesDb.Ldelem_I8_) }, //{ OpCodes.Ldelem_R4.Value, new KeyValuePair(OpCodes.Ldelem_R4, InstrCodesDb.Ldelem_R4_) }, //{ OpCodes.Ldelem_R8.Value, new KeyValuePair(OpCodes.Ldelem_R8, InstrCodesDb.Ldelem_R8_) }, //{ OpCodes.Ldelem_Ref.Value, new KeyValuePair(OpCodes.Ldelem_Ref, InstrCodesDb.Ldelem_Ref_) }, //{ OpCodes.Ldelem_U1.Value, new KeyValuePair(OpCodes.Ldelem_U1, InstrCodesDb.Ldelem_U1_) }, //{ OpCodes.Ldelem_U2.Value, new KeyValuePair(OpCodes.Ldelem_U2, InstrCodesDb.Ldelem_U2_) }, //{ OpCodes.Ldelem_U4.Value, new KeyValuePair(OpCodes.Ldelem_U4, InstrCodesDb.Ldelem_U4_) }, //{ OpCodes.Ldelema.Value, new KeyValuePair(OpCodes.Ldelema, InstrCodesDb.Ldelema_) }, //{ OpCodes.Ldfld.Value, new KeyValuePair(OpCodes.Ldfld, InstrCodesDb.Ldfld_) }, //{ OpCodes.Ldflda.Value, new KeyValuePair(OpCodes.Ldflda, InstrCodesDb.Ldflda_) }, //{ OpCodes.Ldftn.Value, new KeyValuePair(OpCodes.Ldftn, InstrCodesDb.Ldftn_) }, //{ OpCodes.Ldind_I.Value, new KeyValuePair(OpCodes.Ldind_I, InstrCodesDb.Ldind_I_) }, //{ OpCodes.Ldind_I1.Value, new KeyValuePair(OpCodes.Ldind_I1, InstrCodesDb.Ldind_I1_) }, //{ OpCodes.Ldind_I2.Value, new KeyValuePair(OpCodes.Ldind_I2, InstrCodesDb.Ldind_I2_) }, //{ OpCodes.Ldind_I4.Value, new KeyValuePair(OpCodes.Ldind_I4, InstrCodesDb.Ldind_I4_) }, //{ OpCodes.Ldind_I8.Value, new KeyValuePair(OpCodes.Ldind_I8, InstrCodesDb.Ldind_I8_) }, //{ OpCodes.Ldind_R4.Value, new KeyValuePair(OpCodes.Ldind_R4, InstrCodesDb.Ldind_R4_) }, //{ OpCodes.Ldind_R8.Value, new KeyValuePair(OpCodes.Ldind_R8, InstrCodesDb.Ldind_R8_) }, //{ OpCodes.Ldind_Ref.Value, new KeyValuePair(OpCodes.Ldind_Ref, InstrCodesDb.Ldind_Ref_) }, //{ OpCodes.Ldind_U1.Value, new KeyValuePair(OpCodes.Ldind_U1, InstrCodesDb.Ldind_U1_) }, //{ OpCodes.Ldind_U2.Value, new KeyValuePair(OpCodes.Ldind_U2, InstrCodesDb.Ldind_U2_) }, //{ OpCodes.Ldind_U4.Value, new KeyValuePair(OpCodes.Ldind_U4, InstrCodesDb.Ldind_U4_) }, //{ OpCodes.Ldlen.Value, new KeyValuePair(OpCodes.Ldlen, InstrCodesDb.Ldlen_) }, //{ OpCodes.Ldloc.Value, new KeyValuePair(OpCodes.Ldloc, InstrCodesDb.Ldloc_) }, //{ OpCodes.Ldloc_0.Value, new KeyValuePair(OpCodes.Ldloc_0, InstrCodesDb.Ldloc_0_) }, //{ OpCodes.Ldloc_1.Value, new KeyValuePair(OpCodes.Ldloc_1, InstrCodesDb.Ldloc_1_) }, //{ OpCodes.Ldloc_2.Value, new KeyValuePair(OpCodes.Ldloc_2, InstrCodesDb.Ldloc_2_) }, //{ OpCodes.Ldloc_3.Value, new KeyValuePair(OpCodes.Ldloc_3, InstrCodesDb.Ldloc_3_) }, //{ OpCodes.Ldloc_S.Value, new KeyValuePair(OpCodes.Ldloc_S, InstrCodesDb.Ldloc_S_) }, //{ OpCodes.Ldloca.Value, new KeyValuePair(OpCodes.Ldloca, InstrCodesDb.Ldloca_) }, //{ OpCodes.Ldloca_S.Value, new KeyValuePair(OpCodes.Ldloca_S, InstrCodesDb.Ldloca_S_) }, //{ OpCodes.Ldnull.Value, new KeyValuePair(OpCodes.Ldnull, InstrCodesDb.Ldnull_) }, //{ OpCodes.Ldobj.Value, new KeyValuePair(OpCodes.Ldobj, InstrCodesDb.Ldobj_) }, //{ OpCodes.Ldsfld.Value, new KeyValuePair(OpCodes.Ldsfld, InstrCodesDb.Ldsfld_) }, //{ OpCodes.Ldsflda.Value, new KeyValuePair(OpCodes.Ldsflda, InstrCodesDb.Ldsflda_) }, //{ OpCodes.Ldstr.Value, new KeyValuePair(OpCodes.Ldstr, InstrCodesDb.Ldstr_) }, //{ OpCodes.Ldtoken.Value, new KeyValuePair(OpCodes.Ldtoken, InstrCodesDb.Ldtoken_) }, //{ OpCodes.Ldvirtftn.Value, new KeyValuePair(OpCodes.Ldvirtftn, InstrCodesDb.Ldvirtftn_) }, //{ OpCodes.Leave.Value, new KeyValuePair(OpCodes.Leave, InstrCodesDb.Leave_) }, //{ OpCodes.Leave_S.Value, new KeyValuePair(OpCodes.Leave_S, InstrCodesDb.Leave_S_) }, //{ OpCodes.Localloc.Value, new KeyValuePair(OpCodes.Localloc, InstrCodesDb.Localloc_) }, //{ OpCodes.Mkrefany.Value, new KeyValuePair(OpCodes.Mkrefany, InstrCodesDb.Mkrefany_) }, { OpCodes.Mul.Value, new KeyValuePair(OpCodes.Mul, InstrCodesDb.Mul_) }, { OpCodes.Mul_Ovf.Value, new KeyValuePair(OpCodes.Mul_Ovf, InstrCodesDb.Mul_ovf_) }, { OpCodes.Mul_Ovf_Un.Value, new KeyValuePair(OpCodes.Mul_Ovf_Un, InstrCodesDb.Mul_ovf_un_) }, //{ OpCodes.Neg.Value, new KeyValuePair(OpCodes.Neg, InstrCodesDb.Neg_) }, //{ OpCodes.Newarr.Value, new KeyValuePair(OpCodes.Newarr, InstrCodesDb.Newarr_) }, { OpCodes.Newobj.Value, new KeyValuePair(OpCodes.Newobj, InstrCodesDb.Newobj_) }, //{ OpCodes.Nop.Value, new KeyValuePair(OpCodes.Nop, InstrCodesDb.Nop_) }, { OpCodes.Not.Value, new KeyValuePair(OpCodes.Not, InstrCodesDb.Not_) }, { OpCodes.Or.Value, new KeyValuePair(OpCodes.Or, InstrCodesDb.Or_) }, //{ OpCodes.Pop.Value, new KeyValuePair(OpCodes.Pop, InstrCodesDb.Pop_) }, //{ OpCodes.Prefix1.Value, new KeyValuePair(OpCodes.Prefix1, InstrCodesDb.Prefix1_) }, //{ OpCodes.Prefix2.Value, new KeyValuePair(OpCodes.Prefix2, InstrCodesDb.Prefix2_) }, //{ OpCodes.Prefix3.Value, new KeyValuePair(OpCodes.Prefix3, InstrCodesDb.Prefix3_) }, //{ OpCodes.Prefix4.Value, new KeyValuePair(OpCodes.Prefix4, InstrCodesDb.Prefix4_) }, //{ OpCodes.Prefix5.Value, new KeyValuePair(OpCodes.Prefix5, InstrCodesDb.Prefix5_) }, //{ OpCodes.Prefix6.Value, new KeyValuePair(OpCodes.Prefix6, InstrCodesDb.Prefix6_) }, //{ OpCodes.Prefix7.Value, new KeyValuePair(OpCodes.Prefix7, InstrCodesDb.Prefix7_) }, //{ OpCodes.Prefixref.Value, new KeyValuePair(OpCodes.Prefixref, InstrCodesDb.Prefixref_) }, //{ OpCodes.Readonly.Value, new KeyValuePair(OpCodes.Readonly, InstrCodesDb.Readonly_) }, //{ OpCodes.Refanytype.Value, new KeyValuePair(OpCodes.Refanytype, InstrCodesDb.Refanytype_) }, //{ OpCodes.Refanyval.Value, new KeyValuePair(OpCodes.Refanyval, InstrCodesDb.Refanyval_) }, { OpCodes.Rem.Value, new KeyValuePair(OpCodes.Rem, InstrCodesDb.Rem_) }, { OpCodes.Rem_Un.Value, new KeyValuePair(OpCodes.Rem_Un, InstrCodesDb.Rem_un_) }, { OpCodes.Ret.Value, new KeyValuePair(OpCodes.Ret, InstrCodesDb.Ret_) }, //{ OpCodes.Rethrow.Value, new KeyValuePair(OpCodes.Rethrow, InstrCodesDb.Rethrow_) }, { OpCodes.Shl.Value, new KeyValuePair(OpCodes.Shl, InstrCodesDb.Shl_) }, { OpCodes.Shr.Value, new KeyValuePair(OpCodes.Shr, InstrCodesDb.Shr_) }, { OpCodes.Shr_Un.Value, new KeyValuePair(OpCodes.Shr_Un, InstrCodesDb.Shr_un_) }, //{ OpCodes.Sizeof.Value, new KeyValuePair(OpCodes.Sizeof, InstrCodesDb.Sizeof_) }, //{ OpCodes.Starg.Value, new KeyValuePair(OpCodes.Starg, InstrCodesDb.Starg_) }, //{ OpCodes.Starg_S.Value, new KeyValuePair(OpCodes.Starg_S, InstrCodesDb.Starg_S_) }, //{ OpCodes.Stelem.Value, new KeyValuePair(OpCodes.Stelem, InstrCodesDb.Stelem_) }, //{ OpCodes.Stelem_I.Value, new KeyValuePair(OpCodes.Stelem_I, InstrCodesDb.Stelem_I_) }, //{ OpCodes.Stelem_I1.Value, new KeyValuePair(OpCodes.Stelem_I1, InstrCodesDb.Stelem_I1_) }, //{ OpCodes.Stelem_I2.Value, new KeyValuePair(OpCodes.Stelem_I2, InstrCodesDb.Stelem_i2_) }, //{ OpCodes.Stelem_I4.Value, new KeyValuePair(OpCodes.Stelem_I4, InstrCodesDb.Stelem_I4_) }, //{ OpCodes.Stelem_I8.Value, new KeyValuePair(OpCodes.Stelem_I8, InstrCodesDb.Stelem_I8_) }, //{ OpCodes.Stelem_R4.Value, new KeyValuePair(OpCodes.Stelem_R4, InstrCodesDb.Stelem_R4_) }, //{ OpCodes.Stelem_R8.Value, new KeyValuePair(OpCodes.Stelem_R8, InstrCodesDb.Stelem_R8_) }, //{ OpCodes.Stelem_Ref.Value, new KeyValuePair(OpCodes.Stelem_Ref, InstrCodesDb.Stelem_Ref_) }, //{ OpCodes.Stfld.Value, new KeyValuePair(OpCodes.Stfld, InstrCodesDb.Stfld_) }, //{ OpCodes.Stind_I.Value, new KeyValuePair(OpCodes.Stind_I, InstrCodesDb.Stind_I_) }, //{ OpCodes.Stind_I1.Value, new KeyValuePair(OpCodes.Stind_I1, InstrCodesDb.Stind_I1_) }, //{ OpCodes.Stind_I2.Value, new KeyValuePair(OpCodes.Stind_I2, InstrCodesDb.Stind_I2_) }, //{ OpCodes.Stind_I4.Value, new KeyValuePair(OpCodes.Stind_I4, InstrCodesDb.Stind_I4_) }, //{ OpCodes.Stind_I8.Value, new KeyValuePair(OpCodes.Stind_I8, InstrCodesDb.Stind_I8_) }, //{ OpCodes.Stind_R4.Value, new KeyValuePair(OpCodes.Stind_R4, InstrCodesDb.Stind_R4_) }, //{ OpCodes.Stind_R8.Value, new KeyValuePair(OpCodes.Stind_R8, InstrCodesDb.Stind_R8_) }, //{ OpCodes.Stind_Ref.Value, new KeyValuePair(OpCodes.Stind_Ref, InstrCodesDb.Stind_Ref_) }, //{ OpCodes.Stloc.Value, new KeyValuePair(OpCodes.Stloc, InstrCodesDb.Stloc_) }, //{ OpCodes.Stloc_0.Value, new KeyValuePair(OpCodes.Stloc_0, InstrCodesDb.Stloc_0_) }, //{ OpCodes.Stloc_1.Value, new KeyValuePair(OpCodes.Stloc_1, InstrCodesDb.Stloc_1_) }, //{ OpCodes.Stloc_2.Value, new KeyValuePair(OpCodes.Stloc_2, InstrCodesDb.Stloc_2_) }, //{ OpCodes.Stloc_3.Value, new KeyValuePair(OpCodes.Stloc_3, InstrCodesDb.Stloc_3_) }, //{ OpCodes.Stloc_S.Value, new KeyValuePair(OpCodes.Stloc_S, InstrCodesDb.Stloc_S_) }, //{ OpCodes.Stobj.Value, new KeyValuePair(OpCodes.Stobj, InstrCodesDb.Stobj_) }, //{ OpCodes.Stsfld.Value, new KeyValuePair(OpCodes.Stsfld, InstrCodesDb.Stsfld_) }, { OpCodes.Sub.Value, new KeyValuePair(OpCodes.Sub, InstrCodesDb.Sub_) }, { OpCodes.Sub_Ovf.Value, new KeyValuePair(OpCodes.Sub_Ovf, InstrCodesDb.Sub_ovf_) }, { OpCodes.Sub_Ovf_Un.Value, new KeyValuePair(OpCodes.Sub_Ovf_Un, InstrCodesDb.Sub_ovf_un_) }, //{ OpCodes.Switch.Value, new KeyValuePair(OpCodes.Switch, InstrCodesDb.Switch_) }, //{ OpCodes.Tailcall.Value, new KeyValuePair(OpCodes.Tailcall, InstrCodesDb.Tailcall_) }, //{ OpCodes.Throw.Value, new KeyValuePair(OpCodes.Throw, InstrCodesDb.Throw_) }, //{ OpCodes.Unaligned.Value, new KeyValuePair(OpCodes.Unaligned, InstrCodesDb.Unaligned_) }, //{ OpCodes.Unbox.Value, new KeyValuePair(OpCodes.Unbox, InstrCodesDb.Unbox_) }, //{ OpCodes.Unbox_Any.Value, new KeyValuePair(OpCodes.Unbox_Any, InstrCodesDb.Unbox_Any_) }, //{ OpCodes.Volatile.Value, new KeyValuePair(OpCodes.Volatile, InstrCodesDb.Volatile_) }, { OpCodes.Xor.Value, new KeyValuePair(OpCodes.Xor, InstrCodesDb.Xor_) }, }; #endregion public override Stream CreateVmStream(Type rt, ParameterInfo[] pi, Type[] locals, byte [] ilBytes /*GetIlBytes(src)*/) { var ret = new MemoryStream(); var wr = new BinaryWriter(ret); var fwdTypeDefs = new Dictionary(); var fwdTypeRefs = new Dictionary(); var fwdMethodTokenDefs = new Dictionary(); var fwdMethodTokenRefs = new Dictionary(); var deferredBrTargets = new Dictionary(); var srcToDstInstrPositions = new Dictionary(); wr.Write(0); // ClassId wr.Flush(); const int dummy = 0x55555555; fwdTypeDefs.Add(rt, dummy); fwdTypeRefs.Add((int)ret.Position, rt); wr.Write(dummy); // ReturnTypeId fwd ref wr.Write((ushort)0); // LocalVarTypes wr.Write((byte)2); // Flags - static wr.Write((byte)0); // Name var pars = pi; wr.Write((ushort)pars.Length); // ArgsTypeToOutput foreach (var parameterInfo in pars) { if (!fwdTypeDefs.ContainsKey(parameterInfo.ParameterType)) fwdTypeDefs.Add(parameterInfo.ParameterType, dummy); fwdTypeRefs.Add((int)ret.Position, parameterInfo.ParameterType); wr.Write(dummy); // parTypeId fwd ref wr.Write(false); } wr.Write((ushort)locals.Length); // LocalVarTypes foreach (var lt in locals) { if (!fwdTypeDefs.ContainsKey(lt)) fwdTypeDefs.Add(lt, dummy); fwdTypeRefs.Add((int)ret.Position, lt); wr.Write(dummy); // parTypeId fwd ref } var methodLengthPos = ret.Position; wr.Write(dummy); // methodLength using (var sr = new BinaryReader(new MemoryStream(ilBytes))) { while (sr.BaseStream.Position < sr.BaseStream.Length) { srcToDstInstrPositions[sr.BaseStream.Position] = (uint)ret.Position; short ilByte = sr.ReadByte(); if (ilByte == 0xFE) ilByte = (short)((ilByte << 8) | sr.ReadByte()); Assert.IsTrue(IlToVmInstrInfo.ContainsKey(ilByte), "Extend IlToVmInstrInfo with {0:X} or use short jump", ilByte); var vmInstrInfo = IlToVmInstrInfo[ilByte]; var id = vmInstrInfo.Value.Id; wr.Write((ushort)(id >> 16)); wr.Write((ushort)(id & 0xFFFF)); wr.Flush(); ulong operand = 0; switch (vmInstrInfo.Key.OperandType) { case OperandType.InlineNone: break; case OperandType.InlineI8: case OperandType.InlineR: operand = sr.ReadUInt64(); break; case OperandType.InlineVar: operand = sr.ReadUInt16(); break; case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineVar: operand = sr.ReadByte(); break; default: operand = sr.ReadUInt32(); break; } if (vmInstrInfo.Key.OperandType == OperandType.ShortInlineBrTarget) { deferredBrTargets[wr.BaseStream.Position] = (uint)sr.BaseStream.Position + (uint)operand; } if (vmInstrInfo.Key.Value == OpCodes.Newobj.Value || vmInstrInfo.Key.Value == OpCodes.Call.Value) { var token = (uint)operand; if (!fwdMethodTokenDefs.ContainsKey(token)) fwdMethodTokenDefs.Add(token, dummy); fwdMethodTokenRefs[wr.BaseStream.Position] = token; } switch (vmInstrInfo.Value.OperandType) { case VmOperandType.Ot11Nope: break; case VmOperandType.Ot2Byte: case VmOperandType.Ot6SByte: case VmOperandType.Ot8Byte: wr.Write((byte)operand); break; case VmOperandType.Ot1UShort: case VmOperandType.Ot3UShort: wr.Write((ushort)operand); break; case VmOperandType.Ot0UInt: case VmOperandType.Ot12Int: case VmOperandType.Ot5Int: case VmOperandType.Ot10Float: wr.Write((uint)operand); break; case VmOperandType.Ot7Long: case VmOperandType.Ot4Double: wr.Write(operand); break; default: throw new InvalidDataException("OperandType"); } } ret.Position = methodLengthPos; wr.Write((int)(ret.Length - methodLengthPos - 4)); wr.Flush(); ret.Position = ret.Length; foreach (var t in fwdTypeDefs.Keys.ToArray()) { fwdTypeDefs[t] = (int)ret.Position; wr.Write(true); wr.Write((byte)0); wr.Write(-1); wr.Write(-1); wr.Write(false); // ReSharper disable once AssignNullToNotNullAttribute wr.Write(t.AssemblyQualifiedName); wr.Write(false); wr.Write((ushort)0); wr.Flush(); } foreach (var t in fwdMethodTokenDefs.Keys.ToArray()) { fwdMethodTokenDefs[t] = (int)ret.Position; wr.Write((byte)0); wr.Write(t); wr.Flush(); } foreach (var r in fwdTypeRefs) { ret.Position = r.Key; wr.Write(fwdTypeDefs[r.Value]); wr.Flush(); } foreach (var t in fwdMethodTokenRefs) { ret.Position = t.Key; wr.Write((ushort)(fwdMethodTokenDefs[t.Value]>>16)); wr.Write((ushort)fwdMethodTokenDefs[t.Value]); wr.Flush(); } foreach (var r in deferredBrTargets) { ret.Position = r.Key; var srcPos = r.Value; wr.Write(srcToDstInstrPositions[srcPos] - (uint)methodLengthPos - 4); wr.Flush(); } ret.Position = 0; return ret; } } public override object Invoke(object[] parameters, Stream vmStream) { var vmStreamWrapper = new VmStreamWrapper(vmStream, VmExecutor.VmXorKey()); var callees = new object[] { Assembly.GetCallingAssembly() }; var vm = new VmExecutor(InstrCodesDb, vmStreamWrapper); vm.Seek(0, vmStreamWrapper, null); var vmRet = vm.Invoke(parameters, null, null, callees); return vmRet; } } internal static class ExtendedEcma335 { internal static object AsStackedValue(object v, bool signedComparison) // как это значение будет лежать на стеке { Type t = v.GetType(); if (IsFloatingType(t)) return v; //остальное приводится к Int32 или Int64 if (t.IsEnum) t = t.GetEnumUnderlyingType(); if (t == typeof (byte)) return signedComparison ? (object) (Int32) (byte) v : (UInt32) (byte)v; if (t == typeof (sbyte)) return signedComparison ? (object) (Int32) (sbyte) v : (UInt32) (sbyte)v; if (t == typeof (short)) return signedComparison ? (object) (Int32) (short) v : (UInt32) (short)v; if (t == typeof (ushort)) return signedComparison ? (object) (Int32) (ushort)v : (UInt32)(ushort) v; if (t == typeof (Char)) return signedComparison ? (object) (Int32) (Char)v : (UInt32) (Char) v; if (t == typeof (Int32)) return signedComparison ? (object) (Int32) v : (UInt32) (Int32)v; if (t == typeof (UInt32)) return signedComparison ? (object) (Int32) (UInt32) v : (UInt32)v; if (t == typeof(Int64)) return signedComparison ? (object) (Int64)v : (UInt64) (Int64)v; if (t == typeof (UInt64)) return signedComparison ? (object) (Int64) (UInt64) v : (UInt64)v; if (t == typeof(bool)) return signedComparison ? (object) ((bool)v ? 1 : 0) : (UInt32) ((bool)v ? 1 : 0); if (t == typeof(IntPtr)) { if (IntPtr.Size == 4) return signedComparison ? (object)((IntPtr)v).ToInt32() : (UInt32)((IntPtr)v).ToInt32(); return signedComparison ? (object)((IntPtr)v).ToInt64() : (UInt64)((IntPtr)v).ToInt64(); } if (t == typeof(UIntPtr)) { if (UIntPtr.Size == 4) return signedComparison ? (object)(Int32)((UIntPtr)v).ToUInt32() : ((UIntPtr)v).ToUInt32(); return signedComparison ? (object)(Int64)((UIntPtr)v).ToUInt64() : ((UIntPtr)v).ToUInt64(); } return v; } [SuppressMessage("ReSharper", "RedundantCast")] internal static bool Check(KeyValuePair op, object[] parameters, object vmRet) { try { if (parameters.Length == 2 && op.Value == UnitTestCombine.CodeTemplate.TwoOpAny && (op.Key.Value == OpCodes.Shl.Value || op.Key.Value == OpCodes.Shr.Value || op.Key.Value == OpCodes.Shr_Un.Value)) { var t0 = parameters[0].GetType(); var t1 = parameters[1].GetType(); if (t0 == typeof (object) || t1 == typeof (object)) return true; // TODO понять бы, почему нет совпадения с фреймфорком if (IsFloatingType(t0) || IsFloatingType(t1)) return true; // в зависимости от разрядности фреймворк дурит по-разному bool sign = op.Key.Value != OpCodes.Shr_Un.Value; var commonType = UnitTestCombine.CompatibleType(t0, t1, sign); if (commonType == typeof (Int64) || commonType == typeof (UInt64)) { if (sign) { var p0 = Convert.ToInt64(AsStackedValue(parameters[0], true)); var p1 = Convert.ToInt64(AsStackedValue(parameters[1], true)); return Convert.ToInt64(AsStackedValue(vmRet, true)) == ((op.Key.Value == OpCodes.Shl.Value) ? (p1 << (int)p0) : (p1 >> (int)p0)); } else { var p0 = Convert.ToUInt64(AsStackedValue(parameters[0], false)); var p1 = Convert.ToUInt64(AsStackedValue(parameters[1], false)); return Convert.ToUInt64(AsStackedValue(vmRet, false)) == (p1 >> (int) p0); } } } if (parameters.Length == 2 && op.Value == UnitTestCombine.CodeTemplate.TwoOpAny && (op.Key.Value == OpCodes.And.Value || op.Key.Value == OpCodes.Or.Value || op.Key.Value == OpCodes.Xor.Value)) { var t0 = parameters[0].GetType(); var t1 = parameters[1].GetType(); if (t0 == typeof (object) || t1 == typeof (object)) return true; // TODO понять бы, почему нет совпадения с фреймфорком if (IntPtr.Size == 8) { if (t0 == typeof (double) || t1 == typeof (double)) // ReSharper disable once CompareOfFloatsByEqualityOperator return Convert.ToDouble(vmRet) == ((4 == IntPtr.Size) ? Double.NaN : (double) 0); if (t0 == typeof (float) || t1 == typeof (float)) // ReSharper disable once CompareOfFloatsByEqualityOperator return Convert.ToSingle(vmRet) == ((4 == IntPtr.Size) ? Single.NaN : (float) 0); } //x64, как более точный в фреймворке, не даёт сюда срабатываний if (IntPtr.Size == 4 && t0 != t1) { var p0 = Convert.ToInt64(AsStackedValue(parameters[0], true)); var p1 = Convert.ToInt64(AsStackedValue(parameters[1], true)); Int64 check = 0; if (op.Key.Value == OpCodes.And.Value) check = p0 & p1; if (op.Key.Value == OpCodes.Or.Value) check = p0 | p1; if (op.Key.Value == OpCodes.Xor.Value) check = p0 ^ p1; return Convert.ToInt64(AsStackedValue(vmRet, true)) == check; } } bool bAdd = op.Key.Value == OpCodes.Add.Value || op.Key.Value == OpCodes.Add_Ovf.Value || op.Key.Value == OpCodes.Add_Ovf_Un.Value; bool bSub = op.Key.Value == OpCodes.Sub.Value || op.Key.Value == OpCodes.Sub_Ovf.Value || op.Key.Value == OpCodes.Sub_Ovf_Un.Value; bool bMul = op.Key.Value == OpCodes.Mul.Value || op.Key.Value == OpCodes.Mul_Ovf.Value || op.Key.Value == OpCodes.Mul_Ovf_Un.Value; bool bDiv = op.Key.Value == OpCodes.Div.Value || op.Key.Value == OpCodes.Div_Un.Value; bool bRem = op.Key.Value == OpCodes.Rem.Value || op.Key.Value == OpCodes.Rem_Un.Value; if (parameters.Length == 2 && op.Value == UnitTestCombine.CodeTemplate.TwoOpAny && (bAdd || bSub || bMul || bDiv || bRem)) { var t0 = parameters[0].GetType(); var t1 = parameters[1].GetType(); if ((t0 == typeof (object) || t1 == typeof (object)) && (!(vmRet is Exception) || (op.Key.Value == OpCodes.Mul_Ovf.Value) || (op.Key.Value == OpCodes.Mul_Ovf_Un.Value) || (op.Key.Value == OpCodes.Sub_Ovf_Un.Value))) return true; // TODO понять бы, почему нет совпадения с фреймфорком // баг фреймворка в x64 Mul_Ovf_Un для плавающих if (t0 == t1 && !(IntPtr.Size == 8 && op.Key.Value == OpCodes.Mul_Ovf_Un.Value && IsFloatingType(t0) && t0==t1)) return false; bool sign = op.Key.Value != OpCodes.Add_Ovf_Un.Value && op.Key.Value != OpCodes.Sub_Ovf_Un.Value && op.Key.Value != OpCodes.Mul_Ovf_Un.Value && op.Key.Value != OpCodes.Div_Un.Value && op.Key.Value != OpCodes.Rem_Un.Value; var commonType = UnitTestCombine.CompatibleType(t0, t1, sign); if (commonType == typeof (Int64) || commonType == typeof (UInt64)) { if (sign) { var p0 = Convert.ToInt64(AsStackedValue(parameters[0], true)); var p1 = Convert.ToInt64(AsStackedValue(parameters[1], true)); if (vmRet is OverflowException && (op.Key.Value == OpCodes.Add_Ovf.Value || op.Key.Value == OpCodes.Sub_Ovf.Value || op.Key.Value == OpCodes.Mul_Ovf.Value)) { decimal res = bAdd ? ((decimal)p0 + (decimal)p1) : bSub ? ((decimal)p1 - (decimal)p0) : ((decimal)p1 * (decimal)p0); if (commonType == typeof(Int64)) return res > (decimal)Int64.MaxValue || res < (decimal)Int64.MinValue; if (commonType == typeof(UInt64)) return res > (decimal)UInt64.MaxValue || res < 0; } else { if (p0 == 0 && (bDiv || bRem)) return vmRet is DivideByZeroException; try { return (bAdd ? (p0 + p1) : bSub ? (p1 - p0) : bMul ? (p1 * p0) : bDiv ? (p1 / p0) : (p1 % p0)) == Convert.ToInt64(AsStackedValue(vmRet, true)); } catch (Exception e) { return e.GetType() == vmRet.GetType(); } } } else { var p0 = Convert.ToUInt64(AsStackedValue(parameters[0], false)); var p1 = Convert.ToUInt64(AsStackedValue(parameters[1], false)); if (vmRet is OverflowException && op.Key.Value == OpCodes.Sub_Ovf_Un.Value && 4 == IntPtr.Size) { decimal res = (decimal)p1 - (decimal)p0; if (commonType == typeof(UInt64)) return res > (decimal)UInt64.MaxValue || res < 0; } else { if (p0 == 0 && (bDiv || bRem)) return vmRet is DivideByZeroException; return Convert.ToUInt64(AsStackedValue(vmRet, false)) == (bAdd ? (p0 + p1) : bSub ? (p1 - p0) : bMul ? (p1 * p0) : bDiv ? (p1 / p0) : (p1 % p0)); } } } else if (commonType == typeof(float)) { var p0 = Convert.ToSingle(AsStackedValue(parameters[0], sign)); var p1 = Convert.ToSingle(AsStackedValue(parameters[1], sign)); // ReSharper disable once CompareOfFloatsByEqualityOperator if (p0 == 0 && (bDiv || bRem)) return vmRet is DivideByZeroException; var vm = Convert.ToSingle(AsStackedValue(vmRet, sign)); if (float.IsNaN(p0) || float.IsNaN(p1) || float.IsNaN(vm)) return true; // ReSharper disable once RedundantCast // ReSharper disable once CompareOfFloatsByEqualityOperator return vm == (float)(bAdd ? (p0 + p1) : bSub ? (p1 - p0) : bMul ? (p1 * p0) : bDiv ? (p1 / p0) : (p1 % p0)); } else if (commonType == typeof(double)) { var p0 = Convert.ToDouble(AsStackedValue(parameters[0], sign)); var p1 = Convert.ToDouble(AsStackedValue(parameters[1], sign)); // ReSharper disable once CompareOfFloatsByEqualityOperator if (p0 == 0 && (bDiv || bRem)) return vmRet is DivideByZeroException; var vm = Convert.ToDouble(AsStackedValue(vmRet, sign)); if (double.IsNaN(p0) || double.IsNaN(p1) || double.IsNaN(vm)) return true; // ReSharper disable once CompareOfFloatsByEqualityOperator return vm == (bAdd ? (p0 + p1) : bSub ? (p1 - p0) : bMul ? (p1 * p0) : bDiv ? (p1 / p0) : (p1 % p0)); } } if (parameters.Length == 1 && op.Value == UnitTestCombine.CodeTemplate.SingleOpAny && op.Key.Value == OpCodes.Conv_U.Value) { if (IsFloatingType(parameters[0].GetType()) && !(vmRet is Exception)) { // Framework использует мусор, мы возврвщаем 0 // ReSharper disable once CompareOfFloatsByEqualityOperator return Convert.ToDouble(vmRet) == 0.0; } } if (parameters.Length == 1 && op.Value == UnitTestCombine.CodeTemplate.SingleOpAny && op.Key.Value == OpCodes.Ckfinite.Value) { if (!IsFloatingType(parameters[0].GetType()) && !(vmRet is Exception)) { double d = Double.NaN; if (parameters[0] is IConvertible) { d = Convert.ToDouble(AsStackedValue(parameters[0], true)); } return Convert.ToDouble(vmRet).Equals(d); } } if (parameters.Length == 2 && (op.Value == UnitTestCombine.CodeTemplate.BranchTwoOpBool || op.Value == UnitTestCombine.CodeTemplate.TwoOpBool)) { var signedComparison = (op.Key.Value == OpCodes.Bgt_S.Value || op.Key.Value == OpCodes.Ble_S.Value || op.Key.Value == OpCodes.Bge_S.Value || op.Key.Value == OpCodes.Blt_S.Value || op.Key.Value == OpCodes.Beq_S.Value || op.Key.Value == OpCodes.Cgt.Value || op.Key.Value == OpCodes.Clt.Value || op.Key.Value == OpCodes.Ceq.Value); var unsignedUnorderedComparison = (op.Key.Value == OpCodes.Bgt_Un_S.Value || op.Key.Value == OpCodes.Ble_Un_S.Value || op.Key.Value == OpCodes.Bge_Un_S.Value || op.Key.Value == OpCodes.Blt_Un_S.Value || op.Key.Value == OpCodes.Cgt_Un.Value || op.Key.Value == OpCodes.Clt_Un.Value || op.Key.Value == OpCodes.Bne_Un_S.Value); if (signedComparison || unsignedUnorderedComparison) { var isFloat = parameters.Select(o => IsFloatingType(o.GetType())).ToArray(); // разрешаем сравнивать такие типы if (isFloat[0] != isFloat[1]) { //F and int32/64 var vStacked = parameters.Select(o => AsStackedValue(o, true)).ToArray(); if (vStacked.Any(o => !(o is IConvertible))) { return (bool)vmRet == (op.Key.Value == OpCodes.Bne_Un_S.Value); } double a = Convert.ToDouble(vStacked[1]), b = Convert.ToDouble(vStacked[0]); return Compare(op, vmRet, a, b, unsignedUnorderedComparison); } else if (isFloat.All(o => o == false)) { var vStacked = parameters.Select(o => AsStackedValue(o, signedComparison)).ToArray(); if (vStacked.Any(o => !(o is IConvertible))) { return (bool)vmRet == false; } var vStackSize = vStacked.Select(o => Marshal.SizeOf(o.GetType())).ToArray(); if (vStackSize[0] != vStackSize[1]) { //32 bit and 64 bit ints if (signedComparison) { Int64 a = (vStackSize[1] == 8) ? (Int64)vStacked[1] : (Int32)vStacked[1]; Int64 b = (vStackSize[0] == 8) ? (Int64)vStacked[0] : (Int32)vStacked[0]; return Compare(op, vmRet, a, b); } else { UInt64 a = (vStackSize[1] == 8) ? (UInt64)vStacked[1] : (UInt32)vStacked[1]; UInt64 b = (vStackSize[0] == 8) ? (UInt64)vStacked[0] : (UInt32)vStacked[0]; return Compare(op, vmRet, a, b); } } } } } } catch (Exception exc) { Console.Error.WriteLine(exc); } return false; } private static bool Compare(KeyValuePair op, object vmRet, Double a, Double b, bool unordered) { if (unordered && (Double.IsNaN(a) || Double.IsNaN(b))) { return true; } if (op.Key.Value == OpCodes.Bgt_S.Value || op.Key.Value == OpCodes.Bgt_Un_S.Value || op.Key.Value == OpCodes.Cgt.Value || op.Key.Value == OpCodes.Cgt_Un.Value) return ((a > b) == (bool)vmRet); if (op.Key.Value == OpCodes.Ble_S.Value || op.Key.Value == OpCodes.Ble_Un_S.Value) return ((a <= b) == (bool)vmRet); if (op.Key.Value == OpCodes.Bge_S.Value || op.Key.Value == OpCodes.Bge_Un_S.Value) return ((a >= b) == (bool)vmRet); if (op.Key.Value == OpCodes.Blt_S.Value || op.Key.Value == OpCodes.Blt_Un_S.Value || op.Key.Value == OpCodes.Clt.Value || op.Key.Value == OpCodes.Clt_Un.Value) return ((a < b) == (bool)vmRet); if (op.Key.Value == OpCodes.Ceq.Value || op.Key.Value == OpCodes.Beq_S.Value) // ReSharper disable once CompareOfFloatsByEqualityOperator return ((a == b) == (bool)vmRet); if (op.Key.Value == OpCodes.Bne_Un_S.Value) // ReSharper disable once CompareOfFloatsByEqualityOperator return ((a != b) == (bool)vmRet); Assert.Fail("Bad op for Compare"); return false; } private static bool Compare(KeyValuePair op, object vmRet, T a, T b) where T : IComparable { if (op.Key.Value == OpCodes.Bgt_S.Value || op.Key.Value == OpCodes.Bgt_Un_S.Value || op.Key.Value == OpCodes.Cgt.Value || op.Key.Value == OpCodes.Cgt_Un.Value) return ((a.CompareTo(b) > 0) == (bool)vmRet); if (op.Key.Value == OpCodes.Ble_S.Value || op.Key.Value == OpCodes.Ble_Un_S.Value) return ((a.CompareTo(b) <= 0) == (bool)vmRet); if (op.Key.Value == OpCodes.Bge_S.Value || op.Key.Value == OpCodes.Bge_Un_S.Value) return ((a.CompareTo(b) >= 0) == (bool)vmRet); if (op.Key.Value == OpCodes.Blt_S.Value || op.Key.Value == OpCodes.Blt_Un_S.Value || op.Key.Value == OpCodes.Clt.Value || op.Key.Value == OpCodes.Clt_Un.Value) return ((a.CompareTo(b) < 0) == (bool)vmRet); if (op.Key.Value == OpCodes.Ceq.Value || op.Key.Value == OpCodes.Beq_S.Value) return (a.Equals(b) == (bool)vmRet); if (op.Key.Value == OpCodes.Bne_Un_S.Value) return ((!a.Equals(b)) == (bool)vmRet); Assert.Fail("Bad op for Compare"); return false; } private static bool IsFloatingType(Type t) { return t == typeof (Single) || t == typeof (Double); } } }