예제 #1
0
        private static void EmitNullableBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
        {
            // a.GetValueOrDefault() == b.GetValueOrDefault() && a.HasValue == b.HasValue;
            var type = getMethod.ReturnType;
            var getValueOrDefault = type.GetMethod("GetValueOrDefault", new Type[0]);
            var hasValue          = type.GetMethod("get_HasValue");
            var a = il.DeclareLocal(type);
            var b = il.DeclareLocal(type);

            il.Ldarg(0);
            il.Call(getMethod);
            il.Stloc(a);
            il.Ldarg(1);
            il.Call(getMethod);
            il.Stloc(b);

            il.Ldloca(a);
            il.Call(getValueOrDefault);
            il.Ldloca(b);
            il.Call(getValueOrDefault);
            il.Bne_Un(returnFalse);

            il.Ldloca(a);
            il.Call(hasValue);
            il.Ldloca(b);
            il.Call(hasValue);
            il.Bne_Un(returnFalse);
        }
예제 #2
0
        private static Func <IntPtr, long, long> EmitRelJmpHooker()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(long), new[] { typeof(IntPtr), typeof(long) }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.VerificationKind = TypesAssignabilityVerificationKind.LowLevelOnly;
                var cycleLabel = il.DefineLabel("cycle");
                il.MarkLabel(cycleLabel);
                il.Ldarg(0);            // stack: [ptr]
                il.Dup();               // stack: [ptr, ptr]
                var x = il.DeclareLocal(typeof(long));
                il.Ldind(typeof(long)); // stack: [ptr, *ptr]
                il.Dup();
                il.Stloc(x);            // x = *ptr; stack: [ptr, newCode]
                il.Ldc_I8(unchecked ((long)0xFFFFFF0000000000));
                il.And();               // stack: [ptr, x & 0xFFFFFF0000000000]
                il.Ldarg(1);            // stack: [ptr, x & 0xFFFFFF0000000000, code]
                il.Or();                // stack: [ptr, (x & 0xFFFFFF0000000000) | code]
                il.Ldloc(x);            // stack: [ptr, (x & 0xFFFFFF0000000000) | code, newCode]
                var methodInfo = typeof(Interlocked).GetMethod("CompareExchange", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(long).MakeByRefType(), typeof(long), typeof(long) }, null);
                il.Call(methodInfo);    // stack: [Interlocked.CompareExchange(ptr, (x & 0xFFFFFF0000000000) | code, newCode)]
                il.Ldloc(x);            // stack: [Interlocked.CompareExchange(ptr, (x & 0xFFFFFF0000000000) | code, newCode), newCode]
                il.Bne_Un(cycleLabel);  // if(Interlocked.CompareExchange(ptr, (x & 0xFFFFFF0000000000) | code, newCode) != newCode) goto cycle; stack: []
                il.Ldloc(x);
                il.Ret();
            }
            return((Func <IntPtr, long, long>)method.CreateDelegate(typeof(Func <IntPtr, long, long>)));
        }
예제 #3
0
 private static void EmitBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
 {
     // a.Property == b.Property
     il.Ldarg(0);
     il.Call(getMethod);
     il.Ldarg(1);
     il.Call(getMethod);
     il.Bne_Un(returnFalse);
 }
예제 #4
0
        private Func <int, string> BuildSwitch2()
        {
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(string), new[] { typeof(int) }, Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                var zzzLabel = il.DefineLabel("zzz");
                var qxxLabel = il.DefineLabel("qxx");
                var qzzLabel = il.DefineLabel("qzz");
                var xxxLabel = il.DefineLabel("xxx");
                var index    = il.DeclareLocal(typeof(uint));
                il.Ldfld(typeof(TestPerformance).GetField("testValues"));
                il.Ldarg(0);
                il.Ldc_I4(14);
                il.Rem(true);
                il.Stloc(index);
                il.Ldloc(index);
                il.Ldelem(typeof(int));
                il.Ldarg(0);
                il.Bne_Un(xxxLabel);
                il.Ldfld(typeof(TestPerformance).GetField("indexes"));
                il.Ldloc(index);
                il.Ldelem(typeof(int));
                il.Switch(zzzLabel, zzzLabel, qxxLabel, qzzLabel, qzzLabel, qxxLabel);
                il.Br(xxxLabel);
                il.MarkLabel(zzzLabel);
                il.Ldstr("zzz");
                il.Ret();
                il.MarkLabel(qxxLabel);
                il.Ldstr("qxx");
                il.Ret();
                il.MarkLabel(qzzLabel);
                il.Ldstr("qzz");
                il.Ret();
                il.MarkLabel(xxxLabel);
                il.Ldstr("xxx");
                il.Ret();
            }
            return((Func <int, string>)dynamicMethod.CreateDelegate(typeof(Func <int, string>)));
        }
예제 #5
0
        public static TryGetValueDelegate <T> Build <T>(char[] keys, T[] values)
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool),
                                           new[] { typeof(T[]), typeof(char), typeof(T).MakeByRefType() }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                for (int i = 0; i < keys.Length; ++i)
                {
                    il.Ldarg(1);             // stack: [key]
                    il.Ldc_I4(keys[i]);      // stack: [key, keys[i]]
                    var nextKeyLabel = il.DefineLabel("nextKey");
                    il.Bne_Un(nextKeyLabel); // if(key != keys[i]) goto nextKey; stack: []
                    il.Ldarg(2);             // stack: [ref value]
                    il.Ldarg(0);             // stack: [ref value, values]
                    il.Ldc_I4(i);            // stack: [ref value, values, i]
                    il.Ldelem(typeof(T));    // stack: [ref value, values[i]]
                    il.Stind(typeof(T));     // value = values[i]; stack: []
                    il.Ldc_I4(1);            // stack: [true]
                    il.Ret();
                    il.MarkLabel(nextKeyLabel);
                }
                il.Ldarg(2); // stack: [ref value]
                if (typeof(T).IsValueType)
                {
                    il.Initobj(typeof(T)); // value = default(T); stack: []
                }
                else
                {
                    il.Ldnull();         // stack: [ref value, null]
                    il.Stind(typeof(T)); // value = null; stack: []
                }
                il.Ldc_I4(0);            // stack: [false]
                il.Ret();
            }
            return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), values));
        }
예제 #6
0
        public void BuildReader(ReaderTypeBuilderContext readerTypeBuilderContext)
        {
            var method = new DynamicMethod("Read_" + Type.Name + "_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext)
            }, readerTypeBuilderContext.Module, true);

            readerTypeBuilderContext.SetReaderMethod(Type, method);
            using (var il = new GroboIL(method))
            {
                var context = new ReaderMethodBuilderContext(readerTypeBuilderContext, il, !Type.IsValueType && IsReference);

                ReadTypeCodeAndCheck(context); // Read TypeCode and check

                if (!Type.IsValueType && IsReference)
                {
                    // Read reference
                    context.LoadContext();                // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
                    var notReadLabel = il.DefineLabel("notRead");
                    il.Brfalse(notReadLabel);
                    context.LoadIndex();                  // stack: [external index]
                    context.LoadContext();                // stack: [external index, context]
                    il.Ldfld(ReaderContext.StartField);   // stack: [external index, context.start]
                    il.Sub();                             // stack: [external index - context.start]
                    il.Stloc(context.Index);              // index = external index - context.start; stack: []

                    context.LoadContext();                // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
                    il.Ldloc(context.Index);              // stack: [context.objects, index]
                    var obj = il.DeclareLocal(typeof(object));
                    il.Ldloca(obj);
                    object dummy;
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(index, out obj)]
                    il.Brfalse(notReadLabel);                                                                                     // if(!context.objects.TryGetValue(index, out obj)) goto notRead;
                    context.LoadResultByRef();                                                                                    // stack: [ref result]
                    il.Ldloc(obj);                                                                                                // stack: [ref result, obj]
                    il.Castclass(Type);                                                                                           // stack: [ref result, (Type)obj]
                    il.Stind(Type);                                                                                               // result = (Type)obj; stack: []
                    context.IncreaseIndexBy1();                                                                                   // Skip type code
                    context.SkipValue();                                                                                          // Skip value - it has already been read
                    il.Ret();
                    il.MarkLabel(notReadLabel);
                    il.Ldloc(context.TypeCode);               // stack: [typeCode]
                    il.Ldc_I4((int)GroBufTypeCode.Reference); // stack: [typeCode, GroBufTypeCode.Reference]
                    var readUsualLabel = il.DefineLabel("readUsual");
                    il.Bne_Un(readUsualLabel);                // if(typeCode != GroBufTypeCode.Reference) goto readUsual; stack: []

                    context.LoadContext();                    // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField);     // stack: [context.objects]
                    var objectsIsNotNullLabel = il.DefineLabel("objectsIsNotNull");
                    il.Brtrue(objectsIsNotNullLabel);         // if(context.objects != null) goto objectsIsNotNull; stack: [context.objects]
                    il.Ldstr("Reference is not valid at this point");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(objectsIsNotNullLabel);

                    context.IncreaseIndexBy1(); // index = index + 1; stack: []
                    il.Ldc_I4(4);
                    context.AssertLength();
                    context.GoToCurrentLocation();
                    var reference = il.DeclareLocal(typeof(int));
                    il.Ldind(typeof(int));             // stack: [*(int*)data[index]]
                    il.Stloc(reference);               // reference = *(int*)data[index]; stack: []
                    context.IncreaseIndexBy4();        // index = index + 4; stack: []
                    il.Ldloc(context.Index);           // stack: [index]
                    il.Ldloc(reference);               // stack: [index, reference]
                    var goodReferenceLabel = il.DefineLabel("goodReference");
                    il.Bgt(goodReferenceLabel, false); // if(index > reference) goto goodReference; stack: []
                    il.Ldstr("Bad reference");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(goodReferenceLabel);
                    context.LoadContext();                                                                                        // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField);                                                                         // stack: [context.objects]
                    il.Ldloc(reference);                                                                                          // stack: [context.objects, reference]
                    il.Ldloca(obj);                                                                                               // stack: [context.objects, reference, ref obj]
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(reference, out obj)]
                    var readObjectLabel = il.DefineLabel("readObject");
                    il.Brfalse(readObjectLabel);                                                                                  // if(!context.objects.TryGetValue(reference, out obj)) goto readObjects; stack: []
                    context.LoadResultByRef();                                                                                    // stack: [ref result]
                    il.Ldloc(obj);                                                                                                // stack: [ref result, obj]
                    il.Castclass(Type);                                                                                           // stack: [ref result, (Type)obj]
                    il.Stind(Type);                                                                                               // result = (Type)obj; stack: []
                    il.Ret();
                    il.MarkLabel(readObjectLabel);

                    // Referenced object has not been read - this means that the object reference belongs to is a property that had been deleted
                    context.LoadData();                 // stack: [data]
                    il.Ldloc(reference);                // stack: [data, reference]
                    context.LoadContext();              // stack: [data, reference, context]
                    il.Ldfld(ReaderContext.StartField); // stack: [data, reference, context.start]
                    il.Add();                           // stack: [data, reference + context.start]
                    il.Stloc(reference);                // reference += context.start; stack: [data]
                    il.Ldloca(reference);               // stack: [data, ref reference]
                    context.LoadResultByRef();          // stack: [data, ref reference, ref result]
                    context.LoadContext();              // stack: [data, ref reference, ref result, context]
                    context.CallReader(Type);
                    il.Ret();
                    il.MarkLabel(readUsualLabel);
                }

                ReadNotEmpty(context); // Read obj
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type));
            var pointer   = GroBufHelpers.ExtractDynamicMethodPointer(method);

            readerTypeBuilderContext.SetReaderPointer(Type, pointer, @delegate);
        }
        protected override bool EmitInternal(BinaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            Expression left = node.Left;
            Expression right = node.Right;
            Type       leftType, rightType;

            context.EmitLoadArgument(left, false, out leftType);
            context.EmitLoadArgument(right, false, out rightType);
            GroboIL il = context.Il;

            if (!leftType.IsNullable() && !rightType.IsNullable())
            {
                if (node.Method != null)
                {
                    il.Call(node.Method);
                }
                else
                {
                    if (leftType.IsStruct() || rightType.IsStruct())
                    {
                        throw new InvalidOperationException("Cannot compare structs");
                    }
                    il.Ceq();
                    if (node.NodeType == ExpressionType.NotEqual)
                    {
                        il.Ldc_I4(1);
                        il.Xor();
                    }
                }
            }
            else
            {
                var type = leftType;
                if (type != rightType)
                {
                    throw new InvalidOperationException("Cannot compare objects of different types '" + leftType + "' and '" + rightType + "'");
                }
                using (var localLeft = context.DeclareLocal(type))
                    using (var localRight = context.DeclareLocal(type))
                    {
                        il.Stloc(localRight);
                        il.Stloc(localLeft);
                        if (node.Method != null)
                        {
                            il.Ldloca(localLeft);             // stack: [&left]
                            context.EmitHasValueAccess(type); // stack: [left.HasValue]
                            il.Dup();                         // stack: [left.HasValue, left.HasValue]
                            il.Ldloca(localRight);            // stack: [left.HasValue, left.HasValue, &right]
                            context.EmitHasValueAccess(type); // stack: [left.HasValue, left.HasValue, right.HasValue]
                            var notEqualLabel = il.DefineLabel("notEqual");
                            il.Bne_Un(notEqualLabel);         // stack: [left.HasValue]
                            var equalLabel = il.DefineLabel("equal");
                            il.Brfalse(equalLabel);
                            il.Ldloca(localLeft);
                            context.EmitValueAccess(type);
                            il.Ldloca(localRight);
                            context.EmitValueAccess(type);
                            il.Call(node.Method);
                            var doneLabel = il.DefineLabel("done");
                            il.Br(doneLabel);
                            context.MarkLabelAndSurroundWithSP(notEqualLabel);
                            il.Pop();
                            il.Ldc_I4(node.NodeType == ExpressionType.Equal ? 0 : 1);
                            il.Br(doneLabel);
                            context.MarkLabelAndSurroundWithSP(equalLabel);
                            il.Ldc_I4(node.NodeType == ExpressionType.Equal ? 1 : 0);
                            context.MarkLabelAndSurroundWithSP(doneLabel);
                        }
                        else
                        {
                            il.Ldloca(localLeft);
                            context.EmitValueAccess(type);
                            il.Ldloca(localRight);
                            context.EmitValueAccess(type);
                            var notEqualLabel = il.DefineLabel("notEqual");
                            il.Bne_Un(notEqualLabel);
                            il.Ldloca(localLeft);
                            context.EmitHasValueAccess(type);
                            il.Ldloca(localRight);
                            context.EmitHasValueAccess(type);
                            il.Ceq();
                            var doneLabel = il.DefineLabel("done");
                            il.Br(doneLabel);
                            context.MarkLabelAndSurroundWithSP(notEqualLabel);
                            il.Ldc_I4(0);
                            context.MarkLabelAndSurroundWithSP(doneLabel);
                            if (node.NodeType == ExpressionType.NotEqual)
                            {
                                il.Ldc_I4(1);
                                il.Xor();
                            }
                        }
                    }
            }
            resultType = typeof(bool);
            return(false);
        }
예제 #8
0
 private static void EmitBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
 {
     // a.Property == b.Property
     il.Ldarg(0);
     il.Call(getMethod);
     il.Ldarg(1);
     il.Call(getMethod);
     il.Bne_Un(returnFalse);
 }
예제 #9
0
        private static void EmitNullableBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
        {
            // a.GetValueOrDefault() == b.GetValueOrDefault() && a.HasValue == b.HasValue;
            var type = getMethod.ReturnType;
            var getValueOrDefault = type.GetMethod("GetValueOrDefault", new Type[0]);
            var hasValue = type.GetMethod("get_HasValue");
            var a = il.DeclareLocal(type);
            var b = il.DeclareLocal(type);

            il.Ldarg(0);
            il.Call(getMethod);
            il.Stloc(a);
            il.Ldarg(1);
            il.Call(getMethod);
            il.Stloc(b);

            il.Ldloca(a);
            il.Call(getValueOrDefault);
            il.Ldloca(b);
            il.Call(getValueOrDefault);
            il.Bne_Un(returnFalse);

            il.Ldloca(a);
            il.Call(hasValue);
            il.Ldloca(b);
            il.Call(hasValue);
            il.Bne_Un(returnFalse);
        }