예제 #1
0
        private Func <IInternalContainer, IInjectionContext, object[], object> EmitConstruct(ConstructorInfo constructorInfo, int[] parametersInfo, Type wrapperType)
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), TypeArray <IInternalContainer, IInjectionContext, object[]> .Instance, typeof(ClassCreator), true);

            using (var il = new GroboIL(method))
            {
                var constructorParameters = constructorInfo.GetParameters();
                for (var i = 0; i < constructorParameters.Length; i++)
                {
                    ProcessParameter(constructorParameters[i], il, parametersInfo != null ? parametersInfo[i] : -1);
                }
                il.Newobj(constructorInfo);

                if (wrapperType != null)
                {
                    var wrapperConstructor = wrapperType.GetConstructor(TypeArray <object> .Instance);
                    if (wrapperConstructor == null)
                    {
                        throw new NoConstructorException(wrapperType);
                    }
                    il.Newobj(wrapperConstructor);
                }

                il.Ret();
            }
            var @delegate =
                (Func <IInternalContainer, IInjectionContext, object[], object>)
                method.CreateDelegate(typeof(Func <IInternalContainer, IInjectionContext, object[], object>));

            return(@delegate);
        }
예제 #2
0
        private Func <TestClassA, int> Build1()
        {
            var typeBuilder = Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class | TypeAttributes.Public);
            var method      = typeBuilder.DefineMethod("zzz", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new[] { typeof(TestClassA) });

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                il.Ldfld(typeof(TestClassA).GetField("Y"));
                var y = il.DeclareLocal(typeof(int));
                il.Stloc(y);
                il.Ldarg(0);
                il.Ldfld(typeof(TestClassA).GetField("Z"));
                var z = il.DeclareLocal(typeof(int));
                il.Stloc(z);
                il.Ldloc(y);
                il.Ldloc(z);
                il.Add();
                il.Ret();
            }
            var type          = typeBuilder.CreateType();
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(Func <TestClassA, int>), Type.EmptyTypes, Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldnull();
                il.Ldftn(type.GetMethod("zzz"));
                il.Newobj(typeof(Func <TestClassA, int>).GetConstructor(new[] { typeof(object), typeof(IntPtr) }));
                il.Ret();
            }
            return(((Func <Func <TestClassA, int> >)dynamicMethod.CreateDelegate(typeof(Func <Func <TestClassA, int> >)))());
        }
예제 #3
0
        private static TryParseDelegate EmitTryParseDelegate()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool),
                                           new[] { typeof(string), typeof(DateTimeTypeCode), typeof(object).MakeByRefType() }, typeof(string), true);
            var xsdDateTimeType = typeof(XmlReader).Assembly.GetTypes().FirstOrDefault(type => type.Name == "XsdDateTime");

            if (xsdDateTimeType == null)
            {
                throw new InvalidOperationException("The type 'XsdDateTime' is not found");
            }
            var tryParseMethod = xsdDateTimeType.GetMethod("TryParse", BindingFlags.Static | BindingFlags.NonPublic);

            if (tryParseMethod == null)
            {
                throw new InvalidOperationException("The method 'XsdDateTime.TryParse' is not found");
            }
            using (var il = new GroboIL(method))
            {
                il.Ldarg(0); // stack: [value]
                il.Ldarg(1); // stack: [value, typeCode]
                var strongBoxType = typeof(StrongBox <>).MakeGenericType(xsdDateTimeType);
                var strongBox     = il.DeclareLocal(strongBoxType);
                il.Ldarg(2);                                                                             // stack: [value, typeCode, ref result]
                il.Newobj(strongBoxType.GetConstructor(Type.EmptyTypes));                                // stack: [value, typeCode, ref result, new StrongBox<XsdDateTime>()]
                il.Dup();
                il.Stloc(strongBox);                                                                     // strongBox = new StrongBox<XsdDateTime>(); stack: [value, typeCode, ref result, strongBox]
                il.Stind(typeof(object));                                                                // result = strongBox; stack: [value, typeCode]
                il.Ldloc(strongBox);                                                                     // stack: [value, typeCode, strongBox]
                il.Ldflda(strongBoxType.GetField("Value", BindingFlags.Instance | BindingFlags.Public)); // stack: [value, typeCode, ref strongBox.Value]
                il.Call(tryParseMethod);                                                                 // stack: [XsdDateTime.TryParse(value, typeCode, ref strongBox.Value]
                il.Ret();
            }
            return((TryParseDelegate)method.CreateDelegate(typeof(TryParseDelegate)));
        }
        protected override bool EmitInternal(NewExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            context.EmitLoadArguments(node.Arguments.ToArray());
            // note ich: баг решарпера
            // ReSharper disable ConditionIsAlwaysTrueOrFalse
            // ReSharper disable HeuristicUnreachableCode
            GroboIL il = context.Il;

            if (node.Constructor != null)
            {
                il.Newobj(node.Constructor);
            }
            else
            {
                if (node.Type.IsValueType)
                {
                    using (var temp = context.DeclareLocal(node.Type))
                    {
                        il.Ldloca(temp);
                        il.Initobj(node.Type);
                        il.Ldloc(temp);
                    }
                }
                else
                {
                    throw new InvalidOperationException("Missing constructor for type '" + node.Type + "'");
                }
            }
            resultType = node.Type;
            // ReSharper restore ConditionIsAlwaysTrueOrFalse
            // ReSharper restore HeuristicUnreachableCode
            return(false);
        }
예제 #5
0
        public static Func <Dictionary <string, object>, object> GenerateMethod(Type type)
        {
            var da = AppDomain.CurrentDomain.DefineDynamicAssembly(
                new AssemblyName("dyn"),                 // call it whatever you want
                AssemblyBuilderAccess.RunAndSave);

            var dm = da.DefineDynamicModule("dyn_mod", "dyn.dll");
            var dt = dm.DefineType("dyn_type");



            var emiter = Emit <Func <int> > .NewDynamicMethod("MyMethod");

            var method = dt.DefineMethod(
                "Foo",
                MethodAttributes.Public | MethodAttributes.Static, typeof(object),
                new[] { typeof(Dictionary <string, object>) });

            method.DefineParameter(1, ParameterAttributes.None, "dictionary");


            using (var il = new GroboIL(method))
            {
                var target = il.DeclareLocal(type);
                var value  = il.DeclareLocal(typeof(object));

                il.Newobj(type.GetConstructor(Type.EmptyTypes)); // [Person]
                il.Stloc(target);                                // []
                foreach (var property in type.GetProperties())
                {
                    var label = il.DefineLabel("ifLabel");

                    il.Ldarg(0);                          // [Dictionary<String, Object>]
                    il.Ldstr(property.Name);              // [Dictionary<String, Object>, String]
                    il.Ldloca(value);                     // [Dictionary<String, Object>, String, Object&]
                    il.Call(typeof(Dictionary <string, object>)
                            .GetMethod("TryGetValue"));   // [Boolean]

                    il.Brfalse(label);                    // []

                    il.Ldloc(target);                     // [Person]
                    il.Ldloc(value);                      // [Person, Object]
                    il.Castclass(typeof(string));         // [Dictionary<String, Object>, String]
                    il.Call(property.GetSetMethod(true)); // []

                    il.MarkLabel(label);
                }

                il.Ldloc(target);
                il.Ret();
                Console.WriteLine(il.GetILCode());
            }


            dt.CreateType();
            da.Save("dyn.dll");


            return((dic) => dt.GetMethod("Foo").Invoke(null, new object[] { dic }));
        }
예제 #6
0
        private static Func <object, MethodBase, SignatureHelper, uint> BuildGetTokenFor()
        {
            var parameterTypes = new[] { typeof(object), typeof(MethodBase), typeof(SignatureHelper) };
            var method         = new DynamicMethod(Guid.NewGuid().ToString(), typeof(uint), parameterTypes, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);                         // stack: [scope]
                il.Castclass(dynamicScopeType);
                il.Ldarg(1);                         // stack: [scope, method]
                il.Castclass(runtimeMethodInfoType); // stack: [scope, (RuntimeMethodInfo)method]
                il.Ldarg(2);                         // stack: [scope, (RuntimeMethodInfo)method, signature]

                var constructor = varArgsMethodType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { runtimeMethodInfoType, typeof(SignatureHelper) }, null);
                if (constructor == null)
                {
                    throw new MissingMethodException("VarArgsMethod", ".ctor");
                }
                var getTokenForMethod = dynamicScopeType.GetMethod("GetTokenFor", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { varArgsMethodType }, null);
                if (getTokenForMethod == null)
                {
                    throw new MissingMethodException("DynamicScope", "GetTokenFor");
                }

                il.Newobj(constructor);     // stack: [scope, new VarArgsMethod((RuntimeMethodInfo)method, signature)]
                il.Call(getTokenForMethod); // stack: [scope.GetTokenFor(new VarArgsMethod((RuntimeMethodInfo)method, signature))]

                il.Ret();
            }

            return((Func <object, MethodBase, SignatureHelper, uint>)method.CreateDelegate(typeof(Func <object, MethodBase, SignatureHelper, uint>)));
        }
예제 #7
0
        public static Type GenerateClass(ClassDescription description)
        {
            var             name            = new AssemblyName("MyAssembly");
            AssemblyBuilder assemblyBuilder =
                Thread.GetDomain().DefineDynamicAssembly(
                    name, AssemblyBuilderAccess.RunAndSave);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(
                name.Name, name.Name + ".dll");
            TypeBuilder typeBuilder = moduleBuilder.DefineType(
                description.TypeName, TypeAttributes.Class | TypeAttributes.Public);

            foreach (var constructorDescr in description.Constructors)
            {
                var staticOrDynamicAttr =
                    constructorDescr.StaticOrDynamic == StaticOrDynamic.Static ?
                    MethodAttributes.Static : MethodAttributes.Public;
                // второй вариант по сути ничего не добавляет, но атрибута Dynamic нет

                var inTypes = constructorDescr.InputTypes
                              .Select(typeName => description.AllTypes[typeName].RealType)
                              .ToArray();

                typeBuilder.DefineConstructor(
                    MethodAttributes.Public | staticOrDynamicAttr,
                    CallingConventions.Standard,
                    inTypes);
            }


            foreach (var methodDescr in description.Methods)
            {
                var staticOrDynamicAttr =
                    methodDescr.StaticOrDynamic == StaticOrDynamic.Static ?
                    MethodAttributes.Static : MethodAttributes.Public;

                var outType = description.AllTypes[methodDescr.OutputType].RealType;
                var inTypes = methodDescr.InputTypes
                              .Select(typeName => description.AllTypes[typeName].RealType)
                              .ToArray();

                var method = typeBuilder.DefineMethod(
                    methodDescr.MethodName,
                    MethodAttributes.Public | staticOrDynamicAttr,
                    outType,
                    inTypes);


                GroboIL iLgenerator = new GroboIL(method);
                iLgenerator.Newobj(new NotImplementedException()
                                   .GetType()
                                   .GetConstructors()[0]);
                iLgenerator.Throw();
            }

            var type = typeBuilder.CreateType();

            assemblyBuilder.Save(name.Name + ".dll");
            return(type);
        }
예제 #8
0
        private GroboIL.Local EmitDictDeclaration(GroboIL il)
        {
            il.Newobj(typeof(Dictionary <string, object>).GetConstructor(new Type[0]));
            var dict = il.DeclareLocal(typeof(Dictionary <string, object>), "dict");

            il.Stloc(dict);
            return(dict);
        }
예제 #9
0
        public void Test_ldvirtftn3()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), Type.EmptyTypes, typeof(string), true);
            var il     = new GroboIL(method);

            il.Newobj(typeof(C2).GetConstructor(Type.EmptyTypes));
            Assert.Throws <InvalidOperationException>(() => il.Ldvirtftn(typeof(I1).GetMethod("Zzz")));
        }
예제 #10
0
        private void CompileReader()
        {
            DynamicMethod dm = new DynamicMethod(Guid.NewGuid().ToString(), typeof(Tuple <int, object>), new[] { typeof(byte[]), typeof(BinaryStruct), typeof(int) });

            using (var il = new GroboIL(dm))
            {
                var offset = il.DeclareLocal(typeof(int));

                var result = il.DeclareLocal(this.Type);

                var typeSize = il.DeclareLocal(typeof(int));
                var buffer   = il.DeclareLocal(typeof(byte[]));


                var binaryStruct = il.DeclareLocal(typeof(BinaryStruct));

                il.Ldarg(1);
                il.Stloc(binaryStruct);

                var constr = GetConstructor(result.Type, null);
                if (constr == null)
                {
                    throw new Exception($"Type {result.Type} not have constructor with not parameters");
                }

                il.Ldarg(0);
                il.Stloc(buffer);

                il.Ldarg(2);
                il.Stloc(offset);

                il.Newobj(constr);
                il.Stloc(result);

                CompileReader(this, il, binaryStruct, buffer, offset, result, typeSize);

                il.Ldloc(offset);
                il.Ldloc(result);
                il.Newobj(typeof(Tuple <int, object>).GetConstructor(new Type[] { typeof(int), typeof(object) }));
                il.Ret();
                IlReadCode = il.GetILCode();
            }

            //ReadMethod = (ReadMethodDelegate)dm.CreateDelegate(typeof(ReadMethodDelegate));
            ReadMethod = CreateReader(dm);
        }
예제 #11
0
        public void Test_ldvirtftn2()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), Type.EmptyTypes, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Newobj(typeof(C1).GetConstructor(Type.EmptyTypes));
                il.Ldvirtftn(typeof(I1).GetMethod("Zzz"));
                il.Pop();
                il.Ret();
            }
        }
예제 #12
0
        private static void EmitCrashIfValueIsNull(GroboIL il)
        {
            var box = il.DefineLabel("box");

            il.Dup();
            il.Brtrue(box);
            var crashConstructor = typeof(ArgumentException).GetConstructor(new[] { typeof(string) });

            il.Ldstr("bad parameter");
            il.Newobj(crashConstructor);
            il.Throw();
            il.MarkLabel(box);
        }
예제 #13
0
        private static MethodBuilder DefineMethodInterceptingDelegate(TypeBuilder typeBuilder, MethodInfo overridedMethod, Dictionary <Type, FieldInfo> interceptorFields, MethodInfo genericInterceptionAction, MethodInfo voidInterceptionAction, Type[] genericParameterTypes, MethodBuilder @delegate, int index, Type interceptor)
        {
            ConstructorInfo delegateConstructor;
            MethodInfo      interceptorMethod;

            // Define the method
            var method = typeBuilder.DefineMethod($"{overridedMethod.Name}-{interceptor.Name}_{index}_Interceptor",
                                                  MethodAttributes.Private | MethodAttributes.HideBySig,
                                                  overridedMethod.ReturnType,
                                                  new[] { typeof(ParamInfo[]) });

            SetupGenericMethodArguments(overridedMethod, method);

            using (var il = new GroboIL(method))
            {
                if (overridedMethod.ReturnType != typeof(void))
                {
                    interceptorMethod   = genericInterceptionAction.MakeGenericMethod(overridedMethod.ReturnType);
                    delegateConstructor = typeof(TDelegate <>).MakeGenericType(overridedMethod.ReturnType).GetConstructor(new[] { typeof(object), typeof(IntPtr) });
                }
                else
                {
                    interceptorMethod   = voidInterceptionAction;
                    delegateConstructor = typeof(VoidDelegate).GetConstructor(new[] { typeof(object), typeof(IntPtr) });
                }

                il.Ldarg(0);
                il.Ldfld(interceptorFields[interceptor]);
                il.Ldarg(0);

                if (overridedMethod.IsGenericMethodDefinition)
                {
                    il.Ldftn(@delegate.MakeGenericMethod(genericParameterTypes));
                }
                else
                {
                    il.Ldftn(@delegate);
                }

                il.Newobj(delegateConstructor);
                il.Ldarg(1);
                il.Call(interceptorMethod);
                il.Ret();

                @delegate = method;
            }

            return(@delegate);
        }
예제 #14
0
        private static Func <IntPtr, RuntimeTypeHandle> EmitRuntimeTypeHandleCreator()
        {
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(RuntimeTypeHandle), new[] { typeof(IntPtr) }, typeof(string), true);

            using (var il = new GroboIL(dynamicMethod))
            {
                var GetTypeFromHandleUnsafe_m = typeof(Type).GetMethod("GetTypeFromHandleUnsafe", BindingFlags.Static | BindingFlags.NonPublic);
                il.Ldarg(0);                        // stack: [ptr]
                il.Call(GetTypeFromHandleUnsafe_m); // stack: [Type.GetTypeFromHandleUnsafe(ptr)]
                var runtimeType = typeof(Type).Assembly.GetType("System.RuntimeType");
                var constructor = typeof(RuntimeTypeHandle).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { runtimeType }, null);
                il.Newobj(constructor);
                il.Ret();
            }
            return((Func <IntPtr, RuntimeTypeHandle>)dynamicMethod.CreateDelegate(typeof(Func <IntPtr, RuntimeTypeHandle>)));
        }
        private static LambdaCreateDelegate BuildLambdaFactory(Type delegateType)
        {
            var resultType     = typeof(Expression <>).MakeGenericType(delegateType);
            var parameterTypes = new[] { typeof(Expression), typeof(string), typeof(bool), typeof(ReadOnlyCollection <ParameterExpression>) };
            var method         = new DynamicMethod(Guid.NewGuid().ToString(), typeof(LambdaExpression), parameterTypes, typeof(LambdaExpressionCreator), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                il.Ldarg(1);
                il.Ldarg(2);
                il.Ldarg(3);
                il.Newobj(resultType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).Single());
                il.Ret();
            }
            return((LambdaCreateDelegate)method.CreateDelegate(typeof(LambdaCreateDelegate)));
        }
        protected override bool EmitInternal(UnaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            if (node.Type != typeof(bool) && node.Type != typeof(bool?))
            {
                return(ExpressionEmittersCollection.Emit(Expression.OnesComplement(node.Operand, node.Method), context, returnDefaultValueLabel, whatReturn, extend, out resultType));
            }
            GroboIL il = context.Il;

            if (node.Method != null)
            {
                throw new NotSupportedException("Custom operator '" + node.NodeType + "' is not supported");
            }
            var operand = node.Operand;

            context.EmitLoadArgument(operand, false, out resultType);
            if (resultType == typeof(bool))
            {
                il.Ldc_I4(1);
                il.Xor();
            }
            else if (resultType == typeof(bool?))
            {
                using (var value = context.DeclareLocal(typeof(bool?)))
                {
                    il.Stloc(value);
                    il.Ldloca(value);
                    context.EmitHasValueAccess(typeof(bool?));
                    var returnLabel = il.DefineLabel("return");
                    il.Brfalse(returnLabel);
                    il.Ldloca(value);
                    context.EmitValueAccess(typeof(bool?));
                    il.Ldc_I4(1);
                    il.Xor();
                    il.Newobj(nullableBoolConstructor);
                    il.Stloc(value);
                    context.MarkLabelAndSurroundWithSP(returnLabel);
                    il.Ldloc(value);
                }
            }
            else
            {
                throw new InvalidOperationException("Cannot perform '" + node.NodeType + "' operator on type '" + resultType + "'");
            }
            return(false);
        }
예제 #17
0
        public static Func <int[], MethodCallNode[], MethodCallNodeEdges> Build(int n)
        {
            var typeBuilder = module.DefineType("MCNE_UnrolledBinarySearch_" + n, TypeAttributes.Public | TypeAttributes.Class, typeof(MethodCallNodeEdges));
            var context     = new Context
            {
                keys   = new FieldInfo[n],
                values = new FieldInfo[n],
            };

            for (int i = 0; i < n; ++i)
            {
                context.keys[i]   = typeBuilder.DefineField("key_" + i, typeof(int), FieldAttributes.Private);
                context.values[i] = typeBuilder.DefineField("value_" + i, typeof(MethodCallNode), FieldAttributes.Private);
            }

            BuildConstructor(typeBuilder, n, context);
            BuildCount(typeBuilder, n);
            BuildMethodIds(typeBuilder, n, context);
            BuildChildren(typeBuilder, n, context);
            BuildJump(typeBuilder, n, context);

            var type          = typeBuilder.CreateType();
            var constructor   = type.GetConstructor(new[] { typeof(int[]), typeof(MethodCallNode[]) });
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(MethodCallNodeEdges), new[] { typeof(int[]), typeof(MethodCallNode[]) }, typeof(string), true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldarg(0);
                il.Ldarg(1);
                il.Newobj(constructor);
                il.Ret();
            }
            var creator = (Func <int[], MethodCallNode[], MethodCallNodeEdges>)dynamicMethod.CreateDelegate(typeof(Func <int[], MethodCallNode[], MethodCallNodeEdges>));

            return((keys, values) =>
            {
                var indexes = new int[n];
                for (int i = 0; i < n; ++i)
                {
                    indexes[i] = i;
                }
                Array.Sort(indexes, (i, j) => keys[i].CompareTo(keys[j]));
                return creator(indexes.Select(i => keys[i]).ToArray(), indexes.Select(i => values[i]).ToArray());
            });
        }
예제 #18
0
        protected TDelegate CompileToMethod <TDelegate>(Expression <TDelegate> lambda, CompilerOptions options) where TDelegate : class
        {
            var typeBuilder = TestPerformance.Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Public);
            var method      = typeBuilder.DefineMethod("lambda", MethodAttributes.Public | MethodAttributes.Static, lambda.ReturnType, lambda.Parameters.Select(parameter => parameter.Type).ToArray());

            LambdaCompiler.CompileToMethod(lambda, method, options);
            var type          = typeBuilder.CreateType();
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(TDelegate), null, TestPerformance.Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldnull();
                il.Ldftn(type.GetMethod("lambda"));
                il.Newobj(typeof(TDelegate).GetConstructor(new[] { typeof(object), typeof(IntPtr) }));
                il.Ret();
            }
            return(((Func <TDelegate>)dynamicMethod.CreateDelegate(typeof(Func <TDelegate>)))());
        }
예제 #19
0
        public void GetReadILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local buffer, GroboIL.Local result, GroboIL.Local typeSize, GroboIL.Local offset, bool listValue)
        {
            var exitLabel = il.DefineLabel("exit");

            BinaryStruct.ReadObjectNull(il, exitLabel, buffer, offset, typeSize);

            var val = il.DeclareLocal(typeof(TType));


            (new T()).GetReadILCode(prop, currentStruct, il, binaryStruct, buffer, val, typeSize, offset, true);

            il.Ldloc(result);
            il.Ldloc(val);
            il.Newobj(Setter);
            il.Call(prop.Setter);

            il.MarkLabel(exitLabel);
        }
예제 #20
0
        private static void BuildFactoryByDynamicILInfo()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { dynamicILInfoType }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                var constructor = dynamicResolverType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { dynamicILInfoType }, null);
                if (constructor == null)
                {
                    throw new MissingMethodException("DynamicResolver", ".ctor");
                }
                il.Newobj(constructor);
                il.Ret();
            }

            factoryByDynamicILInfo = (Func <DynamicILInfo, object>)method.CreateDelegate(typeof(Func <DynamicILInfo, object>));
        }
예제 #21
0
        private static Func <ValidationResultTreeNode, ValidationResultTreeNode> BuildFactoryInternal(Type type)
        {
            var parameterTypes = new[] { typeof(ValidationResultTreeNode) };
            var method         = new DynamicMethod(Guid.NewGuid().ToString(), typeof(ValidationResultTreeNode), parameterTypes, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                var constructor = type.GetConstructor(parameterTypes);
                if (constructor == null)
                {
                    throw new InvalidOperationException(string.Format("The type '{0}' has no constructor accepting one parameter of type '{1}'", type, typeof(ValidationResultTreeNode)));
                }
                il.Ldarg(0);
                il.Newobj(constructor);
                il.Ret();
            }

            return((Func <ValidationResultTreeNode, ValidationResultTreeNode>)method.CreateDelegate(typeof(Func <ValidationResultTreeNode, ValidationResultTreeNode>)));
        }
예제 #22
0
        public static void CompileReader(BinaryStruct bs, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local buffer, GroboIL.Local offset, GroboIL.Local result, GroboIL.Local typeSize)
        {
            if (bs.PropertyList.Count > 0)
            {
                foreach (var item in bs.PropertyList)
                {
                    if (item.IsBaseType)
                    {
                        item.BinaryType.GetReadILCode(item, bs, il, binaryStruct, buffer, result, typeSize, offset, false);
                        continue;
                    }
                    var methodBreak = il.DefineLabel("breakReadMethod");

                    ReadObjectNull(il, methodBreak, buffer, offset, typeSize);

                    var in_value = il.DeclareLocal(item.PropertyInfo.PropertyType);

                    var constr = BinaryStruct.GetConstructor(item.PropertyInfo.PropertyType, null);

                    if (constr == null)
                    {
                        throw new Exception($"Type {item.PropertyInfo.PropertyType} not have constructor with not parameters");
                    }

                    il.Newobj(constr);
                    il.Stloc(in_value);


                    CompileReader(item.BinaryStruct, il, binaryStruct, buffer, offset, in_value, typeSize);

                    il.Ldloc(result);
                    il.Ldloc(in_value);
                    il.Call(item.Setter, isVirtual: true);

                    il.MarkLabel(methodBreak);
                    //il.Pop();
                }
            }
        }
예제 #23
0
        private void CompileWriter()
        {
            DynamicMethod dm = new DynamicMethod(Guid.NewGuid().ToString(), typeof(Tuple <int, byte[]>), new[] { Type, typeof(BinaryStruct) });

            using (var il = new GroboIL(dm))
            {
                var buffer = il.DeclareLocal(typeof(byte[]));

                var offset = il.DeclareLocal(typeof(int));

                var typeSize = il.DeclareLocal(typeof(int));

                var value = il.DeclareLocal(Type);

                var binaryStruct = il.DeclareLocal(typeof(BinaryStruct));

                il.Ldarg(1);
                il.Stloc(binaryStruct);

                il.Ldarg(0);
                //il.Castclass(Type);
                il.Stloc(value);

                il.Ldc_I4(InitLen);
                il.Newarr(typeof(byte));
                il.Stloc(buffer);

                CompileWriter(this, il, binaryStruct, value, buffer, offset, typeSize);

                il.Ldloc(offset);
                il.Ldloc(buffer);
                il.Newobj(typeof(Tuple <int, byte[]>).GetConstructor(new Type[] { typeof(int), typeof(byte[]) }));
                il.Ret();
                IlWriteCode = il.GetILCode();
            }

            WriteMethod = CreateWriter(dm);
        }
예제 #24
0
        public static void EmitConstructionOfType(Type type, GroboIL il)
        {
            ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);

            if (constructor != null)
            {
                il.Newobj(constructor);
            }
            else
            {
                il.Ldtoken(type);
                il.Call(getTypeFromHandle);
                il.Call(getUninitializedObject);
                if (type.IsValueType)
                {
                    il.Unbox_Any(type);
                }
                else
                {
                    il.Castclass(type);
                }
            }
        }
        protected override bool EmitInternal(UnaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            Type    operandType;
            var     result = ExpressionEmittersCollection.Emit(node.Operand, context, returnDefaultValueLabel, ResultType.Value, extend, out operandType);
            GroboIL il     = context.Il;

            if (node.NodeType == ExpressionType.IsTrue || node.NodeType == ExpressionType.IsFalse)
            {
                if (!operandType.IsNullable())
                {
                    if (node.Method != null)
                    {
                        il.Call(node.Method);
                    }
                    else if (operandType == typeof(bool))
                    {
                        if (node.NodeType == ExpressionType.IsFalse)
                        {
                            il.Ldc_I4(1);
                            il.Xor();
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a type '" + operandType + "'");
                    }
                }
                else
                {
                    using (var temp = context.DeclareLocal(operandType))
                    {
                        il.Stloc(temp);
                        il.Ldloca(temp);
                        context.EmitHasValueAccess(operandType);
                        var returnFalseLabel = il.DefineLabel("returnFalse");
                        il.Brfalse(returnFalseLabel);
                        il.Ldloca(temp);
                        context.EmitValueAccess(operandType);
                        if (node.Method != null)
                        {
                            il.Call(node.Method);
                        }
                        else if (operandType == typeof(bool?))
                        {
                            if (node.NodeType == ExpressionType.IsFalse)
                            {
                                il.Ldc_I4(1);
                                il.Xor();
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a type '" + operandType + "'");
                        }
                        var doneLabel = il.DefineLabel("done");
                        il.Br(doneLabel);
                        context.MarkLabelAndSurroundWithSP(returnFalseLabel);
                        il.Ldc_I4(0);
                        context.MarkLabelAndSurroundWithSP(doneLabel);
                    }
                }
            }
            else
            {
                if (!operandType.IsNullable())
                {
                    if (node.Method != null)
                    {
                        il.Call(node.Method);
                    }
                    else
                    {
                        if (operandType.IsStruct())
                        {
                            throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a struct '" + operandType + "'");
                        }
                        switch (node.NodeType)
                        {
                        case ExpressionType.UnaryPlus:
                            break;

                        case ExpressionType.Negate:
                            il.Neg();
                            break;

                        case ExpressionType.NegateChecked:
                            using (var temp = context.DeclareLocal(operandType))
                            {
                                il.Stloc(temp);
                                il.Ldc_I4(0);
                                context.EmitConvert(typeof(int), operandType);
                                il.Ldloc(temp);
                                il.Sub_Ovf(operandType.Unsigned());
                            }
                            break;

                        case ExpressionType.Increment:
                            il.Ldc_I4(1);
                            context.EmitConvert(typeof(int), operandType);
                            il.Add();
                            break;

                        case ExpressionType.Decrement:
                            il.Ldc_I4(1);
                            context.EmitConvert(typeof(int), operandType);
                            il.Sub();
                            break;

                        case ExpressionType.OnesComplement:
                            il.Not();
                            break;

                        default:
                            throw new InvalidOperationException("Node type '" + node.NodeType + "' invalid at this point");
                        }
                    }
                }
                else
                {
                    using (var temp = context.DeclareLocal(operandType))
                    {
                        il.Stloc(temp);
                        il.Ldloca(temp);
                        context.EmitHasValueAccess(operandType);
                        var returnNullLabel = il.DefineLabel("returnLabel");
                        il.Brfalse(returnNullLabel);
                        Type argumentType = operandType.GetGenericArguments()[0];
                        if (node.Method != null)
                        {
                            il.Ldloca(temp);
                            context.EmitValueAccess(operandType);
                            il.Call(node.Method);
                        }
                        else
                        {
                            switch (node.NodeType)
                            {
                            case ExpressionType.UnaryPlus:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                break;

                            case ExpressionType.Negate:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Neg();
                                break;

                            case ExpressionType.NegateChecked:
                                il.Ldc_I4(0);
                                context.EmitConvert(typeof(int), argumentType);
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Sub_Ovf(argumentType.Unsigned());
                                break;

                            case ExpressionType.Increment:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Ldc_I4(1);
                                context.EmitConvert(typeof(int), argumentType);
                                il.Add();
                                break;

                            case ExpressionType.Decrement:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Ldc_I4(1);
                                context.EmitConvert(typeof(int), argumentType);
                                il.Sub();
                                break;

                            case ExpressionType.OnesComplement:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Not();
                                break;

                            default:
                                throw new InvalidOperationException("Node type '" + node.NodeType + "' invalid at this point");
                            }
                        }
                        il.Newobj(operandType.GetConstructor(new[] { argumentType }));
                        var doneLabel = il.DefineLabel("done");
                        il.Br(doneLabel);
                        context.MarkLabelAndSurroundWithSP(returnNullLabel);
                        context.EmitLoadDefaultValue(operandType);
                        context.MarkLabelAndSurroundWithSP(doneLabel);
                    }
                }
            }
            resultType = node.Type;
            return(result);
        }
예제 #26
0
        private static void EmitConvertValue(GroboIL il, GroBufTypeCode typeCode, GroBufTypeCode expectedTypeCode)
        {
            if (expectedTypeCode == typeCode)
            {
                return;
            }
            switch (expectedTypeCode)
            {
            case GroBufTypeCode.Int8:
                il.Conv <sbyte>();
                break;

            case GroBufTypeCode.UInt8:
            case GroBufTypeCode.Boolean:
                il.Conv <byte>();
                break;

            case GroBufTypeCode.Int16:
                il.Conv <short>();
                break;

            case GroBufTypeCode.UInt16:
                il.Conv <ushort>();
                break;

            case GroBufTypeCode.Int32:
                if (typeCode == GroBufTypeCode.Int64 || typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.Double || typeCode == GroBufTypeCode.Single || typeCode == GroBufTypeCode.DateTimeNew)
                {
                    il.Conv <int>();
                }
                break;

            case GroBufTypeCode.UInt32:
                if (typeCode == GroBufTypeCode.Int64 || typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.Double || typeCode == GroBufTypeCode.Single || typeCode == GroBufTypeCode.DateTimeNew)
                {
                    il.Conv <uint>();
                }
                break;

            case GroBufTypeCode.Int64:
                if (typeCode != GroBufTypeCode.UInt64)
                {
                    if (typeCode == GroBufTypeCode.UInt8 || typeCode == GroBufTypeCode.UInt16 || typeCode == GroBufTypeCode.UInt32)
                    {
                        il.Conv <ulong>();
                    }
                    else
                    {
                        il.Conv <long>();
                    }
                }
                break;

            case GroBufTypeCode.UInt64:
                if (typeCode != GroBufTypeCode.Int64 && typeCode != GroBufTypeCode.DateTimeNew)
                {
                    if (typeCode == GroBufTypeCode.Int8 || typeCode == GroBufTypeCode.Int16 || typeCode == GroBufTypeCode.Int32)
                    {
                        il.Conv <long>();
                    }
                    else
                    {
                        il.Conv <ulong>();
                    }
                }
                break;

            case GroBufTypeCode.Single:
                if (typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.UInt32)
                {
                    il.Conv_R_Un();
                }
                il.Conv <float>();
                break;

            case GroBufTypeCode.Double:
                if (typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.UInt32)
                {
                    il.Conv_R_Un();
                }
                il.Conv <double>();
                break;

            case GroBufTypeCode.Decimal:
                switch (typeCode)
                {
                case GroBufTypeCode.Boolean:
                case GroBufTypeCode.Int8:
                case GroBufTypeCode.Int16:
                case GroBufTypeCode.Int32:
                case GroBufTypeCode.UInt8:
                case GroBufTypeCode.UInt16:
                    il.Newobj(decimalByIntConstructor);
                    break;

                case GroBufTypeCode.UInt32:
                    il.Newobj(decimalByUIntConstructor);
                    break;

                case GroBufTypeCode.Int64:
                case GroBufTypeCode.DateTimeNew:
                    il.Newobj(decimalByLongConstructor);
                    break;

                case GroBufTypeCode.UInt64:
                    il.Newobj(decimalByULongConstructor);
                    break;

                case GroBufTypeCode.Single:
                    il.Call(decimalByFloatMethod);
                    break;

                case GroBufTypeCode.Double:
                    il.Call(decimalByDoubleMethod);
                    break;

                default:
                    throw new NotSupportedException("Type with type code '" + typeCode + "' is not supported");
                }
                break;

            default:
                throw new NotSupportedException("Type with type code '" + expectedTypeCode + "' is not supported");
            }
        }
예제 #27
0
        public void GetReadILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local buffer, GroboIL.Local result, GroboIL.Local typeSize, GroboIL.Local offset, bool listValue)
        {
            var exitLabel = il.DefineLabel("exit");

            BinaryStruct.ReadObjectNull(il, exitLabel, buffer, offset, typeSize);

            var len  = il.DeclareLocal(typeof(int));
            var list = il.DeclareLocal(prop.PropertyInfo.PropertyType);

            il.Ldloc(buffer);
            il.Ldloc(offset);
            il.Call(readBitConverterMethodInfo);
            il.Stloc(len);

            BinaryStruct.WriteOffsetAppend(il, offset, 4);

            il.Newobj(BinaryStruct.GetConstructor(prop.PropertyInfo.PropertyType, null));

            il.Stloc(list);
            il.Ldloc(result);
            il.Ldloc(list);
            il.Call(prop.Setter, isVirtual: true);

            il.Ldloc(len);
            il.Ldc_I4(0);
            il.Ceq();
            il.Brtrue(exitLabel);

            var typeKey   = prop.PropertyInfo.PropertyType.GetGenericArguments()[0];
            var typeValue = prop.PropertyInfo.PropertyType.GetGenericArguments()[1];

            var ivar             = il.DeclareLocal(typeof(int));
            var currentItemKey   = il.DeclareLocal(typeKey);
            var currentItemValue = il.DeclareLocal(typeValue);

            var point = il.DefineLabel("for_label");

            il.Ldc_I4(0);
            il.Stloc(ivar);

            il.MarkLabel(point);

            //body


            //key
            if (typeof(IBasicType).IsAssignableFrom(prop.BinaryAttr.Type.GetGenericArguments()[0]))
            {
                IBasicType t = (IBasicType)Activator.CreateInstance(prop.BinaryAttr.Type.GetGenericArguments()[0]);
                t.GetReadILCode(prop, currentStruct, il, binaryStruct, buffer, currentItemKey, typeSize, offset, true);
            }
            else
            {
                var constr = BinaryStruct.GetConstructor(typeKey, null);
                if (constr == null)
                {
                    throw new Exception($"Type {typeKey} not have constructor with not parameters");
                }

                il.Newobj(constr);
                il.Stloc(currentItemKey);

                BinaryStruct.CompileReader(currentStruct.CurrentStorage.GetTypeInfo(typeKey, currentStruct.Scheme), il, binaryStruct, buffer, offset, currentItemKey, typeSize);
            }

            //value
            if (typeof(IBasicType).IsAssignableFrom(prop.BinaryAttr.Type.GetGenericArguments()[1]))
            {
                IBasicType t = (IBasicType)Activator.CreateInstance(prop.BinaryAttr.Type.GetGenericArguments()[1]);
                t.GetReadILCode(prop, currentStruct, il, binaryStruct, buffer, currentItemValue, typeSize, offset, true);
            }
            else
            {
                var constr = BinaryStruct.GetConstructor(typeValue, null);
                if (constr == null)
                {
                    throw new Exception($"Type {typeValue} not have constructor with not parameters");
                }

                il.Newobj(constr);
                il.Stloc(currentItemValue);

                BinaryStruct.CompileReader(currentStruct.CurrentStorage.GetTypeInfo(typeValue, currentStruct.Scheme), il, binaryStruct, buffer, offset, currentItemValue, typeSize);
            }

            il.Ldloc(list);
            il.Ldloc(currentItemKey);
            il.Ldloc(currentItemValue);
            il.Call(prop.PropertyInfo.PropertyType.GetMethod("Add"), isVirtual: true);

            //end body

            il.Ldc_I4(1);
            il.Ldloc(ivar);
            il.Add();
            il.Stloc(ivar);

            il.Ldloc(ivar);
            il.Ldloc(len);

            il.Clt(false);
            il.Brtrue(point);

            il.MarkLabel(exitLabel);
        }
예제 #28
0
        private Func <object> BuildConstants(Type type, ClosureSubstituter closureSubstituter)
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(object[]) },
                                           typeof(ExpressionClosureBuilder), true);
            var root   = Expression.Parameter(type);
            var consts = new object[hashtable.Count];

            using (var il = new GroboIL(method))
            {
                il.Newobj(type.GetConstructor(Type.EmptyTypes)); // stack: [new Constants()]
                var result = il.DeclareLocal(type, "result");
                il.Stloc(result);                                // result = new Constants(); stack: []
                int index = 0;
                foreach (DictionaryEntry entry in hashtable)
                {
                    var pair      = (Tuple <Type, object>)entry.Key;
                    var constType = pair.Item1;
                    consts[index] = pair.Item2 is Expression?closureSubstituter.Visit((Expression)pair.Item2) : pair.Item2;

                    var fieldAccessor = constantsBuilder.MakeAccess(root, ((int?)entry.Value).Value);
                    var pathToField   = new List <FieldInfo>();
                    while (fieldAccessor.NodeType != ExpressionType.Parameter)
                    {
                        var memberExpression = (MemberExpression)fieldAccessor;
                        pathToField.Add((FieldInfo)memberExpression.Member);
                        fieldAccessor = memberExpression.Expression;
                    }
                    pathToField.Reverse();
                    il.Ldloc(result);
                    for (int i = 0; i < pathToField.Count - 1; ++i)
                    {
                        il.Ldflda(pathToField[i]);                            // stack: [ref result.field]
                        il.Dup();                                             // stack: [ref result.field, ref result.field]
                        var fieldType = pathToField[i].FieldType;
                        il.Ldind(fieldType);                                  // stack: [ref result.field, result.field]
                        var notNullLabel = il.DefineLabel("notNull");
                        il.Brtrue(notNullLabel);                              // if(result.field != null) goto notNull; stack: [ref result.field]
                        il.Dup();                                             // stack: [ref result.field, ref result.field]
                        il.Newobj(fieldType.GetConstructor(Type.EmptyTypes)); // stack: [ref result.field, ref result.field, new field()]
                        il.Stind(fieldType);                                  // result.field = new field(); stack: [ref result.field]
                        il.MarkLabel(notNullLabel);
                        il.Ldind(fieldType);                                  // stack: [result.field]
                    }
                    il.Ldarg(0);                                              // stack: [path, args]
                    il.Ldc_I4(index++);                                       // stack: [path, args, index]
                    il.Ldelem(typeof(object));                                // stack: [path, args[index]]
                    var field = pathToField.Last();
                    if (!constType.IsValueType)
                    {
                        il.Castclass(field.FieldType); // stack: [path, (FieldType)args[index]]
                    }
                    else
                    {
                        il.Unbox_Any(constType);
                        if (field.FieldType != constType)
                        {
                            var constructor = field.FieldType.GetConstructor(new[] { constType });
                            if (constructor == null)
                            {
                                throw new InvalidOperationException(string.Format("Missing constructor of type '{0}' with parameter of type '{1}'",
                                                                                  Formatter.Format(field.FieldType), Formatter.Format(constType)));
                            }
                            il.Newobj(constructor);
                        }
                    }
                    il.Stfld(field); // path.field = (FieldType)args[index]; stack: []
                }
                il.Ldloc(result);
                il.Ret();
            }
            var func = (Func <object[], object>)method.CreateDelegate(typeof(Func <object[], object>));

            return(() => func(consts));
        }
예제 #29
0
 private void NumberToBitsValue(bool takeLength = false)
 {
     Generator.Newobj(takeLength ? BitsValueCtorLength : BitsValueCtor);
     ValueToReference();
 }
예제 #30
0
        public void Test1()
        {
            var overflow    = typeof(OverflowException);
            var exCtorInfo  = overflow.GetConstructor(new[] { typeof(string) });
            var exToStrMI   = overflow.GetMethod("ToString");
            var writeLineMI = typeof(Console).GetMethod("WriteLine",
                                                        new[]
            {
                typeof(string),
                typeof(object)
            });

            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(int), typeof(int) }, typeof(TestTryCatch));

            using (var il = new GroboIL(method))
            {
                GroboIL.Local tmp1 = il.DeclareLocal(typeof(int));
                GroboIL.Local tmp2 = il.DeclareLocal(overflow);

                // In order to successfully branch, we need to create labels
                // representing the offset IL instruction block to branch to.
                // These labels, when the MarkLabel(Label) method is invoked,
                // will specify the IL instruction to branch to.
                //
                GroboIL.Label failed    = il.DefineLabel("failed");
                GroboIL.Label endOfMthd = il.DefineLabel("end");

                // Begin the try block.
                il.BeginExceptionBlock();

                // First, load argument 0 and the integer value of "100" onto the
                // stack. If arg0 > 100, branch to the label "failed", which is marked
                // as the address of the block that throws an exception.
                //
                il.Ldarg(0);
                il.Ldc_I4(100);
                il.Bgt(failed, false);

                // Now, check to see if argument 1 was greater than 100. If it was,
                // branch to "failed." Otherwise, fall through and perform the addition,
                // branching unconditionally to the instruction at the label "endOfMthd".
                //
                il.Ldarg(1);
                il.Ldc_I4(100);
                il.Bgt(failed, false);

                il.Ldarg(0);
                il.Ldarg(1);
                il.Add_Ovf(true);
                // Store the result of the addition.
                il.Stloc(tmp1);
                il.Leave(endOfMthd);

                // If one of the arguments was greater than 100, we need to throw an
                // exception. We'll use "OverflowException" with a customized message.
                // First, we load our message onto the stack, and then create a new
                // exception object using the constructor overload that accepts a
                // string message.
                //
                il.MarkLabel(failed);
                il.Ldstr("Cannot accept values over 100 for add.");
                il.Newobj(exCtorInfo);

                // We're going to need to refer to that exception object later, so let's
                // store it in a temporary variable. Since the store function pops the
                // the value/reference off the stack, and we'll need it to throw the
                // exception, we will subsequently load it back onto the stack as well.

                il.Stloc(tmp2);
                il.Ldloc(tmp2);

                // Throw the exception now on the stack.

                il.Throw();

                // Start the catch block for OverflowException.
                //
                il.BeginCatchBlock(overflow);

                // When we enter the catch block, the thrown exception
                // is on the stack. Store it, then load the format string
                // for WriteLine.
                //
                il.Stloc(tmp2);
                il.Ldstr("Caught {0}");

                // Push the thrown exception back on the stack, then
                // call its ToString() method. Note that if this catch block
                // were for a more general exception type, like Exception,
                // it would be necessary to use the ToString for that type.
                //
                il.Ldloc(tmp2);
                il.Call(exToStrMI);

                // The format string and the return value from ToString() are
                // now on the stack. Call WriteLine(string, object).
                //
                il.Call(writeLineMI);

                // Since our function has to return an integer value, we'll load -1 onto
                // the stack to indicate an error, and store it in local variable tmp1.
                //
                il.Ldc_I4(-1);
                il.Stloc(tmp1);

                // End the exception handling block.

                il.EndExceptionBlock();

                // The end of the method. If no exception was thrown, the correct value
                // will be saved in tmp1. If an exception was thrown, tmp1 will be equal
                // to -1. Either way, we'll load the value of tmp1 onto the stack and return.
                //
                il.MarkLabel(endOfMthd);
                il.Ldloc(tmp1);
                il.Ret();

                Console.WriteLine(il.GetILCode());
            }
        }