/// <summary>
 /// Not Equals
 /// </summary>
 /// <param name="il"></param>
 /// <returns></returns>
 public static ILGenerator Cne(this ILGenerator il)
 {
     return il.Ceq().Cfalse();
 }
        /// <summary>
        /// Emit Equality Compare for 2 arguments in top of stack
        /// </summary>
        /// <param name="il"></param>
        /// <param name="argType"></param>
        /// <returns></returns>
        public static ILGenerator IsEquals(this ILGenerator il, Type argType)
        {
            if (argType.IsPrimitive)
            {
                return il.Ceq();
            }

            var nulType = Nullable.GetUnderlyingType(argType);
            if (nulType != null)
            {
                var miGetValue = argType.GetProperty("Value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).GetGetMethod();
                var miHasValue = argType.GetProperty("HasValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).GetGetMethod();
                var locVar1 = il.DeclareLocal(argType);
                var locVar2 = il.DeclareLocal(argType);
                var lblHasValues = il.DefineLabel();
                var lblExit = il.DefineLabel();

                il
                    .Stloc(locVar2)
                    .Stloc(locVar1)
                    .Ldloca(locVar1)
                    .Call(miHasValue)
                    .Ldloca(locVar2)
                    .Call(miHasValue)
                    .Add()
                    .Dup()
                    .Ldc_I4(2)
                    .Beq(lblHasValues)
                    .Ldtrue()
                    .Xor()
                    .Br(lblExit)
                    .Label(lblHasValues)
                    .Pop()
                    .Ldloca(locVar1)
                    .Call(miGetValue)
                    .Ldloca(locVar2)
                    .Call(miGetValue)
                    .IsEquals(nulType)
                    .Label(lblExit);
                return il;
            }

            var eqMethod = argType.GetMethod("op_Equality",
                BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly,
                null, new Type[] { argType, argType }, null);
            if (eqMethod != null)
            {
                return il.Call(eqMethod);
            }
            var eqType = typeof(IEquatable<>).MakeGenericType(argType);
            var lblEnd = il.DefineLabel();
            if (!argType.IsValueType)
            {
                if (eqType.IsAssignableFrom(argType))
                {
                    var lblHasValue1 = il.DefineLabel();
                    var locVar2 = il.DeclareLocal(argType);

                    il
                        .Stloc(locVar2)
                        .Dup()
                        .Brtrue(lblHasValue1)
                        .Ldloc(locVar2) //                  if arg1 == 0
                        .Ceq() //                           Сравниваем refernces
                        .Br(lblEnd)
                        .Label(lblHasValue1)
                        .Ldloc(locVar2)
                        .Callvirt(eqType.GetMethod("Equals"));
                }
                else
                {
                    il.Ceq();
                }
            }
            else
            {
                if (eqType.IsAssignableFrom(argType))
                {
                    var var1 = il.DeclareLocal(argType);
                    il.Stloc(var1).Ldloca(var1);
                    il.Callvirt(eqType.GetMethod("Equals"));
                }
            }

            il.MarkLabel(lblEnd);
            return il;
        }
 /// <summary>
 /// Compare
 /// </summary>
 /// <param name="il"></param>
 /// <param name="pred"></param>
 /// <returns></returns>
 public static ILGenerator Cmp(this ILGenerator il, PredicateType pred)
 {
     switch (pred)
     {
         case PredicateType.Equal:
             return il.Ceq();
         case PredicateType.GreaterThan:
             return il.Cgt();
         case PredicateType.GreaterThanOrEqual:
             return il.Cge();
         case PredicateType.LessThan:
             return il.Clt();
         case PredicateType.LessThanOrEqual:
             return il.Cle();
         case PredicateType.NotEqual:
             return il.Cne();
         case PredicateType.IsFalse:
             return il.Cfalse();
         case PredicateType.IsTrue:
             return il.Ctrue();
         default:
             throw new ArgumentException(@"Invalid Predicate Type", "pred");
     }
 }