public IFluentILGenerator BeginExceptFilterBlock()
 {
     _logger?.LogMeta("filter");
     _logger?.LogMeta("{");
     _generator.BeginExceptFilterBlock();
     return(this);
 }
        /// <summary>
        /// Try to emit something like that:
        ///
        /// .method public static bool TestFilter (bool execute_handler)
        /// {
        ///     .locals init(bool)
        ///     try {
        ///         newobj  instance void [mscorlib]System.Exception::.ctor()
        ///         throw
        ///     } filter {
        ///         pop
        ///         ldarg.0
        ///         endfilter
        ///     } {
        ///         ldc.i4.1
        ///         stloc.0
        ///         leave quit
        ///     }
        ///     ldc.i4.0
        ///     stloc.0
        /// quit:
        ///     ldloc.0
        ///     ret
        /// }
        ///
        /// It should return true if the handler has been executed
        /// Otherwise, the exception should not be catched
        /// </summary>
        void DefineTestFilterMethod()
        {
            MethodBuilder mb = tb.DefineMethod("TestFilter",
                                               MethodAttributes.Public | MethodAttributes.Static, typeof(bool), new Type [] { typeof(bool) });

            ConstructorInfo exCtor = typeof(Exception).GetConstructor(new Type [0]);

            il_gen = mb.GetILGenerator();
            il_gen.DeclareLocal(typeof(bool));
            Label quit = il_gen.DefineLabel();

            il_gen.BeginExceptionBlock();
            il_gen.Emit(OpCodes.Newobj, exCtor);
            il_gen.Emit(OpCodes.Throw);
            il_gen.BeginExceptFilterBlock();
            il_gen.Emit(OpCodes.Pop);
            il_gen.Emit(OpCodes.Ldarg_0);
            il_gen.BeginCatchBlock(null);
            il_gen.Emit(OpCodes.Ldc_I4_1);
            il_gen.Emit(OpCodes.Stloc_0);
            il_gen.Emit(OpCodes.Leave, quit);
            il_gen.EndExceptionBlock();
            il_gen.Emit(OpCodes.Ldc_I4_0);
            il_gen.Emit(OpCodes.Stloc_0);
            il_gen.MarkLabel(quit);
            il_gen.Emit(OpCodes.Ldloc_0);
            il_gen.Emit(OpCodes.Ret);
        }
Exemple #3
0
        public static void MarkBlockBefore(ILGenerator il, ExceptionBlock block, out Label?label)
        {
            label = null;
            switch (block.blockType)
            {
            case ExceptionBlockType.BeginExceptionBlock:
                label = il.BeginExceptionBlock();
                return;

            case ExceptionBlockType.BeginCatchBlock:
                il.BeginCatchBlock(block.catchType);
                return;

            case ExceptionBlockType.BeginExceptFilterBlock:
                il.BeginExceptFilterBlock();
                return;

            case ExceptionBlockType.BeginFaultBlock:
                il.BeginFaultBlock();
                return;

            case ExceptionBlockType.BeginFinallyBlock:
                il.BeginFinallyBlock();
                return;
            }
        }
Exemple #4
0
        private void EmitILForExceptionHandlers(ILGenerator ilGenerator, Instruction instruction, List <ExceptionHandler> handlers)
        {
            var tryBlocks = handlers.Where(h => h.TryStart == instruction.Offset).GroupBy(h => h.TryEnd);

            foreach (var tryBlock in tryBlocks)
            {
                ilGenerator.BeginExceptionBlock();
                m_exceptionBlockLevel++;
            }

            var filterBlock = handlers.FirstOrDefault(h => h.FilterStart == instruction.Offset);

            if (filterBlock != null)
            {
                ilGenerator.BeginExceptFilterBlock();
            }

            var handler = handlers.FirstOrDefault(h => h.HandlerEnd == instruction.Offset);

            if (handler != null)
            {
                if (handler.Flags == ExceptionHandlingClauseOptions.Finally)
                {
                    // Finally blocks are always the last handler
                    ilGenerator.EndExceptionBlock();
                    m_exceptionBlockLevel--;
                }
                else if (handler.HandlerEnd == handlers.Where(h => h.TryStart == handler.TryStart && h.TryEnd == handler.TryEnd).Max(h => h.HandlerEnd))
                {
                    // We're dealing with the last catch block
                    ilGenerator.EndExceptionBlock();
                    m_exceptionBlockLevel--;
                }
            }

            var catchOrFinallyBlock = handlers.FirstOrDefault(h => h.HandlerStart == instruction.Offset);

            if (catchOrFinallyBlock != null)
            {
                if (catchOrFinallyBlock.Flags == ExceptionHandlingClauseOptions.Clause)
                {
                    ilGenerator.BeginCatchBlock(catchOrFinallyBlock.CatchType);
                }
                else if (catchOrFinallyBlock.Flags == ExceptionHandlingClauseOptions.Filter)
                {
                    ilGenerator.BeginCatchBlock(null);
                }
                else if (catchOrFinallyBlock.Flags == ExceptionHandlingClauseOptions.Finally)
                {
                    ilGenerator.BeginFinallyBlock();
                }
                else
                {
                    // No support for fault blocks
                    throw new NotSupportedException();
                }
            }
        }
        internal void BeginExceptFilterBlock()
        {
            _ilg.BeginExceptFilterBlock();

            _exceptionState.Pop();
            _exceptionState.Push(ExceptionState.Filter);

            AssertOffsetMatches();
        }
        public void InvalidFilterBlock1()
        {
            DefineBasicMethod();
            ILGenerator il = il_gen;

            il.BeginExceptionBlock();
            il.BeginExceptFilterBlock();
            il.EndExceptionBlock();
        }
        [Test]         // bug #81431
        public void FilterAndCatchBlock()
        {
            DefineBasicMethod();
            ILGenerator il = il_gen;

            il.BeginExceptionBlock();
            il.BeginExceptFilterBlock();
            il.BeginCatchBlock(null);
            il.BeginCatchBlock(typeof(SystemException));
        }
        public CatchBlock CatchBlock(Type exceptionType, Action <ILGenerator> filter)
        {
            EnsureTryBlockEnded();

            if (hasFinallyBlock)
            {
                throw new InvalidOperationException(
                          "Exception block already has a finally block - cannot start new catch block");
            }

            if (hasFaultBlock)
            {
                throw new InvalidOperationException(
                          "Exception block already has a fault block - cannot have both catch and fault blocks");
            }

            if (filter != null)
            {
                generator.BeginExceptFilterBlock();

                if (exceptionType != null)
                {
                    var filterBlockEnd = generator.DefineLabel();
                    var customFilter   = generator.DefineLabel();

                    generator
                    .Duplicate()
                    .IsInstanceOfType(exceptionType)
                    .BranchIfTrue(customFilter)

                    .Pop()
                    .LoadConstant(false)
                    .BranchTo(filterBlockEnd);

                    generator.MarkLabel(customFilter);
                    filter(generator);

                    generator.MarkLabel(filterBlockEnd);
                }
                else
                {
                    filter(generator);
                }

                generator.BeginCatchBlock(null);
            }
            else
            {
                generator.BeginCatchBlock(exceptionType);
            }

            hasCatchBlocks = true;

            return(new CatchBlock(generator, endLabel));
        }
 public void DefineFilterBodyWithTypeNotNull()
 {
     DefineBasicMethod();
     il_gen.BeginExceptionBlock();
     il_gen.EmitWriteLine("in try");
     il_gen.BeginExceptFilterBlock();
     il_gen.EmitWriteLine("in filter head");
     il_gen.BeginCatchBlock(typeof(Exception));
     il_gen.EmitWriteLine("in filter body");
     il_gen.EndExceptionBlock();
 }
Exemple #10
0
        private void MarkExceptionHandlers(ExceptionHandlerCollection exceptionHandlers)
        {
            foreach (ExceptionHandler exceptionHandler in exceptionHandlers)
            {
                AddActionAfter(exceptionHandler.TryStart, delegate
                {
                    generator.BeginExceptionBlock();
                });

                if (exceptionHandler.Type == ExceptionHandlerType.Filter)
                {
                    AddActionAfter(exceptionHandler.FilterStart, delegate
                    {
                        generator.BeginExceptFilterBlock();
                    });
                }

                AddActionAfter(exceptionHandler.HandlerStart, delegate
                {
                    switch (exceptionHandler.Type)
                    {
                    case ExceptionHandlerType.Catch:
                        generator.BeginCatchBlock(outer.ResolveType(exceptionHandler.CatchType));
                        break;

                    case ExceptionHandlerType.Fault:
                        generator.BeginFaultBlock();
                        break;

                    case ExceptionHandlerType.Finally:
                        generator.BeginFinallyBlock();
                        break;
                    }
                });

                AddActionBefore(exceptionHandler.HandlerEnd, delegate
                {
                    generator.EndExceptionBlock();
                });
            }
        }
#pragma warning restore

        protected virtual void MarkExceptionBlock(ILGenerator il, ExceptionBlockInfo info)
        {
            ExceptionBlockType btype = info.blockType;

            if ((btype & ExceptionBlockType.End) != 0)
            {
                il.EndExceptionBlock();
            }
            else // begin
            {
                switch (btype & flagValue)
                {
                case ExceptionBlockType.BigBlock:
                    il.BeginExceptionBlock();
                    return;

                case ExceptionBlockType.FilterBlock:
                    il.BeginExceptFilterBlock();
                    return;

                case ExceptionBlockType.FinallyBlock:
                    il.BeginFinallyBlock();
                    return;

                case ExceptionBlockType.CatchBlock:
                    il.BeginCatchBlock(info.catchType);
                    return;

                case ExceptionBlockType.FaultBlock:
                    il.BeginFaultBlock();
                    return;

                default:
#if DEBUG
                    System.Diagnostics.Debug.WriteLine($"[ERROR] {btype}");
#endif
                    return;
                }
            }
        }
        static OperationCallbacks()
        {
            AssemblyName    name    = new AssemblyName("Microsoft.Management.Infrastructure.UserFilteredExceptionHandling");
            AssemblyBuilder builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);

            Type[]   types           = new Type[] { typeof(DebuggableAttribute.DebuggingModes) };
            object[] constructorArgs = new object[] { DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints };
            builder.SetCustomAttribute(new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(types), constructorArgs));
            PropertyInfo[] namedProperties = new PropertyInfo[] { typeof(RuntimeCompatibilityAttribute).GetProperty("WrapNonExceptionThrows") };
            object[]       propertyValues  = new object[] { true };
            builder.SetCustomAttribute(new CustomAttributeBuilder(typeof(RuntimeCompatibilityAttribute).GetConstructor(new Type[0]), new object[0], namedProperties, propertyValues));
            TypeBuilder builder2 = builder.DefineDynamicModule(name.Name).DefineType("UserFilteredExceptionHandling", TypeAttributes.Public);

            Type[]      parameterTypes = new Type[] { typeof(Action), typeof(Func <Exception, bool>), typeof(Action <Exception>) };
            ILGenerator iLGenerator    = builder2.DefineMethod("InvokeWithUserFilteredExceptionHandler", MethodAttributes.Static | MethodAttributes.Public, null, parameterTypes).GetILGenerator();

            iLGenerator.DeclareLocal(typeof(Exception));
            iLGenerator.BeginExceptionBlock();
            iLGenerator.Emit(OpCodes.Ldarg_0);
            iLGenerator.EmitCall(OpCodes.Callvirt, typeof(Action).GetMethod("Invoke"), null);
            iLGenerator.BeginExceptFilterBlock();
            iLGenerator.Emit(OpCodes.Castclass, typeof(Exception));
            iLGenerator.Emit(OpCodes.Stloc_0);
            iLGenerator.Emit(OpCodes.Ldarg_1);
            iLGenerator.Emit(OpCodes.Ldloc_0);
            iLGenerator.EmitCall(OpCodes.Callvirt, typeof(Func <Exception, bool>).GetMethod("Invoke"), null);
            iLGenerator.BeginCatchBlock(null);
            iLGenerator.Emit(OpCodes.Castclass, typeof(Exception));
            iLGenerator.Emit(OpCodes.Stloc_0);
            iLGenerator.Emit(OpCodes.Ldarg_2);
            iLGenerator.Emit(OpCodes.Ldloc_0);
            iLGenerator.EmitCall(OpCodes.Callvirt, typeof(Action <Exception>).GetMethod("Invoke"), null);
            iLGenerator.EndExceptionBlock();
            iLGenerator.Emit(OpCodes.Ret);
            MethodInfo method = builder2.CreateType().GetMethod("InvokeWithUserFilteredExceptionHandler");

            userFilteredExceptionHandler = (Action <Action, Func <Exception, bool>, Action <Exception> >)Delegate.CreateDelegate(typeof(Action <Action, Func <Exception, bool>, Action <Exception> >), method);
        }
Exemple #13
0
        internal void MarkBlockBefore(ExceptionBlock block, out Label?label)
        {
            label = null;
            switch (block.blockType)
            {
            case ExceptionBlockType.BeginExceptionBlock:
                if (debug)
                {
                    FileLog.LogBuffered(".try");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                label = il.BeginExceptionBlock();
                return;

            case ExceptionBlockType.BeginCatchBlock:
                if (debug)
                {
                    // fake log a LEAVE code since BeginCatchBlock() does add it
                    LogIL(OpCodes.Leave, new LeaveTry(), true);

                    FileLog.ChangeIndent(-1);
                    FileLog.LogBuffered("} // end try");

                    FileLog.LogBuffered($".catch {block.catchType}");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                il.BeginCatchBlock(block.catchType);
                return;

            case ExceptionBlockType.BeginExceptFilterBlock:
                if (debug)
                {
                    // fake log a LEAVE code since BeginCatchBlock() does add it
                    LogIL(OpCodes.Leave, new LeaveTry(), true);

                    FileLog.ChangeIndent(-1);
                    FileLog.LogBuffered("} // end try");

                    FileLog.LogBuffered(".filter");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                il.BeginExceptFilterBlock();
                return;

            case ExceptionBlockType.BeginFaultBlock:
                if (debug)
                {
                    // fake log a LEAVE code since BeginCatchBlock() does add it
                    LogIL(OpCodes.Leave, new LeaveTry(), true);

                    FileLog.ChangeIndent(-1);
                    FileLog.LogBuffered("} // end try");

                    FileLog.LogBuffered(".fault");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                il.BeginFaultBlock();
                return;

            case ExceptionBlockType.BeginFinallyBlock:
                if (debug)
                {
                    // fake log a LEAVE code since BeginCatchBlock() does add it
                    LogIL(OpCodes.Leave, new LeaveTry(), true);

                    FileLog.ChangeIndent(-1);
                    FileLog.LogBuffered("} // end try");

                    FileLog.LogBuffered(".finally");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                il.BeginFinallyBlock();
                return;
            }
        }
Exemple #14
0
 public void BeginExceptFilterBlock()
 {
     sb.Append("\r\n\t\tBeginExceptFilterBlock"); gen.BeginExceptFilterBlock();
 }
        public static Delegate CreateDelegate(Delegate dlg)
        {
            if (dlg == null)
            {
                throw new ArgumentNullException();
            }
            if (dlg.Target != null)
            {
                throw new ArgumentException();
            }
            if (dlg.Method == null)
            {
                throw new ArgumentException();
            }
            get_runtime_types();
            Type returnType = dlg.Method.ReturnType;

            ParameterInfo[] parameters     = dlg.Method.GetParameters();
            Type[]          parameterTypes = new Type[parameters.Length];
            for (int index = 0; index < parameters.Length; ++index)
            {
                parameterTypes[index] = parameters[index].ParameterType;
            }
            DynamicMethod dynamicMethod = new DynamicMethod(DynamicMethodNameCounter.GetUniqueName(), returnType, parameterTypes, typeof(DynamicMethodNameCounter), true);
            ILGenerator   ilGenerator   = dynamicMethod.GetILGenerator();
            LocalBuilder  local         = null;

            if (returnType != typeof(void))
            {
                local = ilGenerator.DeclareLocal(returnType);
            }
            ilGenerator.Emit(OpCodes.Call, wait_for_bridge_processing_method);
            Label label = ilGenerator.BeginExceptionBlock();

            for (int index = 0; index < parameterTypes.Length; ++index)
            {
                ilGenerator.Emit(OpCodes.Ldarg, index);
            }
            ilGenerator.Emit(OpCodes.Call, dlg.Method);
            if (local != null)
            {
                ilGenerator.Emit(OpCodes.Stloc, local);
            }
            ilGenerator.Emit(OpCodes.Leave, label);
            bool flag = Debugger.IsAttached;// || !JNIEnv.PropagateExceptions;

            if (flag)
            {
                ilGenerator.BeginExceptFilterBlock();
                ilGenerator.Emit(OpCodes.Call, mono_unhandled_exception_method);
                ilGenerator.Emit(OpCodes.Ldc_I4_1);
                ilGenerator.BeginCatchBlock(null);
            }
            else
            {
                ilGenerator.BeginCatchBlock(typeof(Exception));
            }

            ilGenerator.Emit(OpCodes.Dup);
            ilGenerator.Emit(OpCodes.Call, exception_handler_method);
            if (flag)
            {
                ilGenerator.Emit(OpCodes.Throw);
            }
            ilGenerator.EndExceptionBlock();
            if (local != null)
            {
                ilGenerator.Emit(OpCodes.Ldloc, local);
            }
            ilGenerator.Emit(OpCodes.Ret);
            return(dynamicMethod.CreateDelegate(dlg.GetType()));
        }
Exemple #16
0
        internal static void MarkBlockBefore(ILGenerator il, ExceptionBlock block, out Label?label)
        {
            label = null;
            switch (block.blockType)
            {
            case ExceptionBlockType.BeginExceptionBlock:
                if (HarmonyInstance.DEBUG)
                {
                    FileLog.LogBuffered(".try");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                label = il.BeginExceptionBlock();
                return;

            case ExceptionBlockType.BeginCatchBlock:
                if (HarmonyInstance.DEBUG)
                {
                    // fake log a LEAVE code since BeginCatchBlock() does add it
                    LogIL(il, OpCodes.Leave, new LeaveTry());

                    FileLog.ChangeIndent(-1);
                    FileLog.LogBuffered("} // end try");

                    FileLog.LogBuffered(".catch " + block.catchType);
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                il.BeginCatchBlock(block.catchType);
                return;

            case ExceptionBlockType.BeginExceptFilterBlock:
                if (HarmonyInstance.DEBUG)
                {
                    // fake log a LEAVE code since BeginCatchBlock() does add it
                    LogIL(il, OpCodes.Leave, new LeaveTry());

                    FileLog.ChangeIndent(-1);
                    FileLog.LogBuffered("} // end try");

                    FileLog.LogBuffered(".filter");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                il.BeginExceptFilterBlock();
                return;

            case ExceptionBlockType.BeginFaultBlock:
                if (HarmonyInstance.DEBUG)
                {
                    // fake log a LEAVE code since BeginCatchBlock() does add it
                    LogIL(il, OpCodes.Leave, new LeaveTry());

                    FileLog.ChangeIndent(-1);
                    FileLog.LogBuffered("} // end try");

                    FileLog.LogBuffered(".fault");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                il.BeginFaultBlock();
                return;

            case ExceptionBlockType.BeginFinallyBlock:
                if (HarmonyInstance.DEBUG)
                {
                    // fake log a LEAVE code since BeginCatchBlock() does add it
                    LogIL(il, OpCodes.Leave, new LeaveTry());

                    FileLog.ChangeIndent(-1);
                    FileLog.LogBuffered("} // end try");

                    FileLog.LogBuffered(".finally");
                    FileLog.LogBuffered("{");
                    FileLog.ChangeIndent(1);
                }
                il.BeginFinallyBlock();
                return;
            }
        }
Exemple #17
0
 public void BeginExceptFilterBlock() => generator.BeginExceptFilterBlock();
 public virtual void BeginExceptFilterBlock()
 {
     il.BeginExceptFilterBlock();
 }
        public DynamicMethod Generate()
        {
            MethodDefinition def = Definition;

            // Fix up any mistakes which might accidentally pop up.
            def.ConvertShortLongOps();

            Type[] genericArgsType   = Method.DeclaringType.GetTypeInfo().IsGenericType ? Method.DeclaringType.GetGenericArguments() : null;
            Type[] genericArgsMethod = Method.IsGenericMethod ? Method.GetGenericArguments() : null;

            ParameterInfo[] args = Method.GetParameters();
            Type[]          argTypes;
            if (!Method.IsStatic)
            {
                argTypes    = new Type[args.Length + 1];
                argTypes[0] = Method.GetThisParamType();
                for (int i = 0; i < args.Length; i++)
                {
                    argTypes[i + 1] = args[i].ParameterType;
                }
            }
            else
            {
                argTypes = new Type[args.Length];
                for (int i = 0; i < args.Length; i++)
                {
                    argTypes[i] = args[i].ParameterType;
                }
            }

            DynamicMethod dm = new DynamicMethod(
                $"DynamicMethodDefinition<{Method}>",
                (Method as MethodInfo)?.ReturnType ?? typeof(void), argTypes,
                Method.DeclaringType,
                true // If any random errors pop up, try setting this to false first.
                );
            ILGenerator il = dm.GetILGenerator();

            LocalBuilder[] locals = def.Body.Variables.Select(
                var => il.DeclareLocal(var.VariableType.ResolveReflection(), var.IsPinned)
                ).ToArray();

            // Pre-pass - Set up label map.
            Dictionary <int, Label> labelMap = new Dictionary <int, Label>();

            foreach (Instruction instr in def.Body.Instructions)
            {
                if (instr.Operand is Instruction[] targets)
                {
                    foreach (Instruction target in targets)
                    {
                        if (!labelMap.ContainsKey(target.Offset))
                        {
                            labelMap[target.Offset] = il.DefineLabel();
                        }
                    }
                }
                else if (instr.Operand is Instruction target)
                {
                    if (!labelMap.ContainsKey(target.Offset))
                    {
                        labelMap[target.Offset] = il.DefineLabel();
                    }
                }
            }

            object[] emitArgs = new object[2];
            foreach (Instruction instr in def.Body.Instructions)
            {
                if (labelMap.TryGetValue(instr.Offset, out Label label))
                {
                    il.MarkLabel(label);
                }

                // TODO: This can be improved perf-wise!
                foreach (ExceptionHandler handler in def.Body.ExceptionHandlers)
                {
                    if (handler.TryStart == instr)
                    {
                        il.BeginExceptionBlock();
                    }
                    else if (handler.FilterStart == instr)
                    {
                        il.BeginExceptFilterBlock();
                    }
                    else if (handler.HandlerStart == instr)
                    {
                        switch (handler.HandlerType)
                        {
                        case ExceptionHandlerType.Filter:
                            // Handled by FilterStart
                            break;

                        case ExceptionHandlerType.Catch:
                            il.BeginCatchBlock(handler.CatchType.ResolveReflection());
                            break;

                        case ExceptionHandlerType.Finally:
                            il.BeginFinallyBlock();
                            break;

                        case ExceptionHandlerType.Fault:
                            il.BeginFaultBlock();
                            break;
                        }
                    }
                }

                if (instr.OpCode.OperandType == Mono.Cecil.Cil.OperandType.InlineNone)
                {
                    il.Emit(_ReflOpCodes[instr.OpCode.Value]);
                }
                else
                {
                    object operand = instr.Operand;

                    if (operand is Instruction[] targets)
                    {
                        operand = targets.Select(target => labelMap[target.Offset]).ToArray();
                    }
                    else if (operand is Instruction target)
                    {
                        operand = labelMap[target.Offset];
                    }
                    else if (operand is VariableDefinition var)
                    {
                        operand = locals[var.Index];
                    }
                    else if (operand is ParameterDefinition param)
                    {
                        operand = param.Index;
                    }
                    else if (operand is MemberReference mref)
                    {
                        operand = mref.ResolveReflection();
                    }
                    else if (operand is CallSite csite)
                    {
                        // SignatureHelper in unmanaged contexts cannot be fully made use of for DynamicMethods.
                        EmitCallSite(dm, il, _ReflOpCodes[instr.OpCode.Value], csite);
                        continue;
                    }

                    if (operand == null)
                    {
                        throw new NullReferenceException($"Unexpected null in {def} @ {instr}");
                    }

                    Type operandType = operand.GetType();
                    if (!_Emitters.TryGetValue(operandType, out MethodInfo emit))
                    {
                        emit = _Emitters.FirstOrDefault(kvp => kvp.Key.IsAssignableFrom(operandType)).Value;
                    }
                    if (emit == null)
                    {
                        throw new InvalidOperationException($"Unexpected unemittable {operand.GetType().FullName} in {def} @ {instr}");
                    }

                    emitArgs[0] = _ReflOpCodes[instr.OpCode.Value];
                    emitArgs[1] = operand;
                    emit.Invoke(il, emitArgs);
                }

                // TODO: This can be improved perf-wise!
                foreach (ExceptionHandler handler in def.Body.ExceptionHandlers)
                {
                    if (handler.HandlerEnd == instr.Next)
                    {
                        il.EndExceptionBlock();
                    }
                }
            }

            return(dm);
        }
        internal override void TranslateToIL(ILGenerator il, Type rtype)
        {
            //This assumes that rtype == Void.class.
            bool savedInsideProtectedRegion = compilerGlobals.InsideProtectedRegion;

            compilerGlobals.InsideProtectedRegion = true;
            compilerGlobals.BreakLabelStack.Push(compilerGlobals.BreakLabelStack.Peek(0));
            compilerGlobals.ContinueLabelStack.Push(compilerGlobals.ContinueLabelStack.Peek(0));
            il.BeginExceptionBlock();
            if (this.finally_block != null)
            {
                if (this.finallyHasControlFlowOutOfIt)
                {
                    il.BeginExceptionBlock();
                }
                if (this.handler != null)
                {
                    il.BeginExceptionBlock();
                }
            }
            this.body.TranslateToIL(il, Typeob.Void);
            if (this.tryEndContext != null)
            {
                this.tryEndContext.EmitLineInfo(il);
            }
            if (this.handler != null)
            {
                if (this.type == null)
                {
                    il.BeginCatchBlock(Typeob.Exception);
                    this.handler.context.EmitLineInfo(il);
                    this.EmitILToLoadEngine(il);
                    il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
                }
                else
                {
                    Type filterType = this.type.ToType();
                    if (Typeob.Exception.IsAssignableFrom(filterType))
                    {
                        il.BeginCatchBlock(filterType);
                        this.handler.context.EmitLineInfo(il);
                    }
                    else
                    {
                        il.BeginExceptFilterBlock();
                        this.handler.context.EmitLineInfo(il);
                        this.EmitILToLoadEngine(il);
                        il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
                        il.Emit(OpCodes.Isinst, filterType);
                        il.Emit(OpCodes.Ldnull);
                        il.Emit(OpCodes.Cgt_Un);
                        il.BeginCatchBlock(null);
                        this.EmitILToLoadEngine(il);
                        il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
                        Convert.Emit(this, il, Typeob.Object, filterType);
                    }
                }
                Object tok = this.field is JSVariableField ? ((JSVariableField)this.field).GetMetaData() : this.field;
                if (tok is LocalBuilder)
                {
                    il.Emit(OpCodes.Stloc, (LocalBuilder)tok);
                }
                else if (tok is FieldInfo)
                {
                    il.Emit(OpCodes.Stsfld, (FieldInfo)tok);
                }
                else
                {
                    Convert.EmitLdarg(il, (short)tok);
                }

                if (this.handler_scope != null)
                {
                    if (!this.handler_scope.isKnownAtCompileTime) //I.e. eval or nested func
                    {
                        this.EmitILToLoadEngine(il);
                        il.Emit(OpCodes.Ldstr, this.fieldName);
                        ConstantWrapper.TranslateToILInt(il, this.handler_scope.scopeId);
                        il.Emit(OpCodes.Call, Typeob.Try.GetMethod("PushHandlerScope"));
                        Globals.ScopeStack.Push(this.handler_scope);
                        il.BeginExceptionBlock();
                    }
                    il.BeginScope(); // so that we can emit local scoped information for the handler variable
                    if (this.context.document.debugOn)
                    {
                        this.handler_scope.EmitLocalInfoForFields(il);
                    }
                }
                this.handler.TranslateToIL(il, Typeob.Void);
                if (this.handler_scope != null)
                {
                    il.EndScope();
                    if (!this.handler_scope.isKnownAtCompileTime) //I.e. eval or nested func
                    {
                        il.BeginFinallyBlock();
                        this.EmitILToLoadEngine(il);
                        il.Emit(OpCodes.Call, CompilerGlobals.popScriptObjectMethod);
                        il.Emit(OpCodes.Pop);
                        Globals.ScopeStack.Pop();
                        il.EndExceptionBlock();
                    }
                }
                il.EndExceptionBlock();
            }
            if (this.finally_block != null)
            {
                bool savedInsideFinally   = compilerGlobals.InsideFinally;
                int  savedFinallyStackTop = compilerGlobals.FinallyStackTop;
                compilerGlobals.InsideFinally   = true;
                compilerGlobals.FinallyStackTop = compilerGlobals.BreakLabelStack.Size();
                il.BeginFinallyBlock();
                this.finally_block.TranslateToIL(il, Typeob.Void);
                il.EndExceptionBlock();
                compilerGlobals.InsideFinally   = savedInsideFinally;
                compilerGlobals.FinallyStackTop = savedFinallyStackTop;
                if (this.finallyHasControlFlowOutOfIt)
                {
                    il.BeginCatchBlock(Typeob.BreakOutOfFinally);
                    il.Emit(OpCodes.Ldfld, Typeob.BreakOutOfFinally.GetField("target"));
                    // don't need to go to 0 in the loop because 0 is the outmost block (i.e. function body)
                    // and that would generate a JIT assert because the jump is sometimes outside the function
                    for (int i = compilerGlobals.BreakLabelStack.Size() - 1, n = i; i > 0; i--)
                    {
                        il.Emit(OpCodes.Dup);
                        ConstantWrapper.TranslateToILInt(il, i);
                        Label lab = il.DefineLabel();
                        il.Emit(OpCodes.Blt_S, lab);
                        il.Emit(OpCodes.Pop);
                        if (savedInsideFinally && i < savedFinallyStackTop)
                        {
                            il.Emit(OpCodes.Rethrow);
                        }
                        else
                        {
                            il.Emit(OpCodes.Leave, (Label)compilerGlobals.BreakLabelStack.Peek(n - i));
                        }
                        il.MarkLabel(lab);
                    }
                    il.Emit(OpCodes.Pop);
                    il.BeginCatchBlock(Typeob.ContinueOutOfFinally);
                    il.Emit(OpCodes.Ldfld, Typeob.ContinueOutOfFinally.GetField("target"));
                    // don't need to go to 0 in the loop because 0 is the outmost block (i.e. function body)
                    for (int i = compilerGlobals.ContinueLabelStack.Size() - 1, n = i; i > 0; i--)
                    {
                        il.Emit(OpCodes.Dup);
                        ConstantWrapper.TranslateToILInt(il, i);
                        Label lab = il.DefineLabel();
                        il.Emit(OpCodes.Blt_S, lab);
                        il.Emit(OpCodes.Pop);
                        if (savedInsideFinally && i < savedFinallyStackTop)
                        {
                            il.Emit(OpCodes.Rethrow);
                        }
                        else
                        {
                            il.Emit(OpCodes.Leave, (Label)compilerGlobals.ContinueLabelStack.Peek(n - i));
                        }
                        il.MarkLabel(lab);
                    }
                    il.Emit(OpCodes.Pop);
                    ScriptObject scope = Globals.ScopeStack.Peek();
                    while (scope != null && !(scope is FunctionScope))
                    {
                        scope = scope.GetParent();
                    }
                    if (scope != null && !savedInsideFinally)
                    {
                        il.BeginCatchBlock(Typeob.ReturnOutOfFinally);
                        il.Emit(OpCodes.Pop);
                        il.Emit(OpCodes.Leave, ((FunctionScope)scope).owner.returnLabel);
                    }
                    il.EndExceptionBlock();
                }
            }
            compilerGlobals.InsideProtectedRegion = savedInsideProtectedRegion;
            compilerGlobals.BreakLabelStack.Pop();
            compilerGlobals.ContinueLabelStack.Pop();
        }
Exemple #21
0
        public static void Generate(DynamicMethodDefinition dmd, MethodBase _mb, ILGenerator il)
        {
            MethodDefinition def = dmd.Definition;
            DynamicMethod    dm  = _mb as DynamicMethod;

#if !NETSTANDARD
            MethodBuilder mb            = _mb as MethodBuilder;
            ModuleBuilder moduleBuilder = mb?.Module as ModuleBuilder;
            // moduleBuilder.Assembly sometimes avoids the .Assembly override under mysterious circumstances.
            AssemblyBuilder    assemblyBuilder     = (mb?.DeclaringType as TypeBuilder)?.Assembly as AssemblyBuilder;
            HashSet <Assembly> accessChecksIgnored = null;
            if (mb != null)
            {
                accessChecksIgnored = new HashSet <Assembly>();
            }
#endif

#if !CECIL0_9
            MethodDebugInformation defInfo = dmd.Debug ? def.DebugInformation : null;
#endif

            if (dm != null)
            {
                foreach (ParameterDefinition param in def.Parameters)
                {
                    dm.DefineParameter(param.Index + 1, (System.Reflection.ParameterAttributes)param.Attributes, param.Name);
                }
            }
#if !NETSTANDARD
            if (mb != null)
            {
                foreach (ParameterDefinition param in def.Parameters)
                {
                    mb.DefineParameter(param.Index + 1, (System.Reflection.ParameterAttributes)param.Attributes, param.Name);
                }
            }
#endif

            LocalBuilder[] locals = def.Body.Variables.Select(
                var => {
                LocalBuilder local = il.DeclareLocal(var.VariableType.ResolveReflection(), var.IsPinned);
#if !NETSTANDARD && !CECIL0_9
                if (mb != null && defInfo != null && defInfo.TryGetName(var, out string name))
                {
                    local.SetLocalSymInfo(name);
                }
#endif
                return(local);
            }
                ).ToArray();

            // Pre-pass - Set up label map.
            Dictionary <Instruction, Label> labelMap = new Dictionary <Instruction, Label>();
            foreach (Instruction instr in def.Body.Instructions)
            {
                if (instr.Operand is Instruction[] targets)
                {
                    foreach (Instruction target in targets)
                    {
                        if (!labelMap.ContainsKey(target))
                        {
                            labelMap[target] = il.DefineLabel();
                        }
                    }
                }
                else if (instr.Operand is Instruction target)
                {
                    if (!labelMap.ContainsKey(target))
                    {
                        labelMap[target] = il.DefineLabel();
                    }
                }
            }

#if !NETSTANDARD && !CECIL0_9
            Dictionary <Document, ISymbolDocumentWriter> infoDocCache = mb == null ? null : new Dictionary <Document, ISymbolDocumentWriter>();
#endif

            int      paramOffs        = def.HasThis ? 1 : 0;
            object[] emitArgs         = new object[2];
            bool     checkTryEndEarly = false;
            foreach (Instruction instr in def.Body.Instructions)
            {
                if (labelMap.TryGetValue(instr, out Label label))
                {
                    il.MarkLabel(label);
                }

#if !NETSTANDARD && !CECIL0_9
                SequencePoint instrInfo = defInfo?.GetSequencePoint(instr);
                if (mb != null && instrInfo != null)
                {
                    if (!infoDocCache.TryGetValue(instrInfo.Document, out ISymbolDocumentWriter infoDoc))
                    {
                        infoDocCache[instrInfo.Document] = infoDoc = moduleBuilder.DefineDocument(
                            instrInfo.Document.Url,
                            instrInfo.Document.LanguageGuid,
                            instrInfo.Document.LanguageVendorGuid,
                            instrInfo.Document.TypeGuid
                            );
                    }
                    il.MarkSequencePoint(infoDoc, instrInfo.StartLine, instrInfo.StartColumn, instrInfo.EndLine, instrInfo.EndColumn);
                }
#endif

                foreach (ExceptionHandler handler in def.Body.ExceptionHandlers)
                {
                    if (checkTryEndEarly && handler.HandlerEnd == instr)
                    {
                        il.EndExceptionBlock();
                    }

                    if (handler.TryStart == instr)
                    {
                        il.BeginExceptionBlock();
                    }
                    else if (handler.FilterStart == instr)
                    {
                        il.BeginExceptFilterBlock();
                    }
                    else if (handler.HandlerStart == instr)
                    {
                        switch (handler.HandlerType)
                        {
                        case ExceptionHandlerType.Filter:
                            il.BeginCatchBlock(null);
                            break;

                        case ExceptionHandlerType.Catch:
                            il.BeginCatchBlock(handler.CatchType.ResolveReflection());
                            break;

                        case ExceptionHandlerType.Finally:
                            il.BeginFinallyBlock();
                            break;

                        case ExceptionHandlerType.Fault:
                            il.BeginFaultBlock();
                            break;
                        }
                    }

                    // Avoid duplicate endfilter / endfinally
                    if (handler.HandlerStart == instr.Next)
                    {
                        switch (handler.HandlerType)
                        {
                        case ExceptionHandlerType.Filter:
                            if (instr.OpCode == Mono.Cecil.Cil.OpCodes.Endfilter)
                            {
                                goto SkipEmit;
                            }
                            break;

                        case ExceptionHandlerType.Finally:
                            if (instr.OpCode == Mono.Cecil.Cil.OpCodes.Endfinally)
                            {
                                goto SkipEmit;
                            }
                            break;
                        }
                    }
                }

                if (instr.OpCode.OperandType == Mono.Cecil.Cil.OperandType.InlineNone)
                {
                    il.Emit(_ReflOpCodes[instr.OpCode.Value]);
                }
                else
                {
                    object operand = instr.Operand;

                    if (operand is Instruction[] targets)
                    {
                        operand = targets.Select(target => labelMap[target]).ToArray();
                        // Let's hope that the JIT treats the long forms identically to the short forms.
                        instr.OpCode = instr.OpCode.ToLongOp();
                    }
                    else if (operand is Instruction target)
                    {
                        operand = labelMap[target];
                        // Let's hope that the JIT treats the long forms identically to the short forms.
                        instr.OpCode = instr.OpCode.ToLongOp();
                    }
                    else if (operand is VariableDefinition var)
                    {
                        operand = locals[var.Index];
                    }
                    else if (operand is ParameterDefinition param)
                    {
                        operand = param.Index + paramOffs;
                    }
                    else if (operand is MemberReference mref)
                    {
                        MemberInfo member = mref.ResolveReflection();
                        operand = member;
#if !NETSTANDARD
                        if (mb != null && member != null)
                        {
                            Assembly asm = member.Module?.Assembly;
                            if (asm != null && !accessChecksIgnored.Contains(asm))
                            {
                                // while (member.DeclaringType != null)
                                //     member = member.DeclaringType;
                                assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(DynamicMethodDefinition.c_IgnoresAccessChecksToAttribute, new object[] {
                                    asm.GetName().Name
                                }));
                                accessChecksIgnored.Add(asm);
                            }
                        }
#endif
                    }
                    else if (operand is CallSite csite)
                    {
                        if (dm != null)
                        {
                            // SignatureHelper in unmanaged contexts cannot be fully made use of for DynamicMethods.
                            _EmitCallSite(dm, il, _ReflOpCodes[instr.OpCode.Value], csite);
                            continue;
                        }
#if !NETSTANDARD
                        operand = csite.ResolveReflection(mb.Module);
#else
                        throw new NotSupportedException();
#endif
                    }

#if !NETSTANDARD
                    if (mb != null && operand is MethodBase called && called.DeclaringType == null)
                    {
                        // "Global" methods (f.e. DynamicMethods) cannot be tokenized.
                        if (instr.OpCode == Mono.Cecil.Cil.OpCodes.Call)
                        {
                            if (operand is DynamicMethod target)
                            {
                                // This should be heavily optimizable.
                                operand = _CreateMethodProxy(mb, target);
                            }
                            else
                            {
                                IntPtr ptr = called.GetLdftnPointer();
                                if (IntPtr.Size == 4)
                                {
                                    il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)ptr);
                                }
                                else
                                {
                                    il.Emit(System.Reflection.Emit.OpCodes.Ldc_I8, (long)ptr);
                                }
                                il.Emit(System.Reflection.Emit.OpCodes.Conv_I);
                                instr.OpCode = Mono.Cecil.Cil.OpCodes.Calli;
                                operand      = ((MethodReference)instr.Operand).ResolveReflectionSignature(mb.Module);
                            }
                        }
                        else
                        {
                            throw new NotSupportedException($"Unsupported global method operand on opcode {instr.OpCode.Name}");
                        }
                    }
#endif

                    if (operand == null)
                    {
                        throw new NullReferenceException($"Unexpected null in {def} @ {instr}");
                    }

                    il.DynEmit(_ReflOpCodes[instr.OpCode.Value], operand);
                }

                if (!checkTryEndEarly)
                {
                    foreach (ExceptionHandler handler in def.Body.ExceptionHandlers)
                    {
                        if (handler.HandlerEnd == instr.Next)
                        {
                            il.EndExceptionBlock();
                        }
                    }
                }

                checkTryEndEarly = false;
                continue;

SkipEmit:
                checkTryEndEarly = true;
                continue;
            }
        }
        internal override void TranslateToIL(ILGenerator il, Type rtype)
        {
            bool insideProtectedRegion = base.compilerGlobals.InsideProtectedRegion;

            base.compilerGlobals.InsideProtectedRegion = true;
            base.compilerGlobals.BreakLabelStack.Push(base.compilerGlobals.BreakLabelStack.Peek(0));
            base.compilerGlobals.ContinueLabelStack.Push(base.compilerGlobals.ContinueLabelStack.Peek(0));
            il.BeginExceptionBlock();
            if (this.finally_block != null)
            {
                if (this.finallyHasControlFlowOutOfIt)
                {
                    il.BeginExceptionBlock();
                }
                if (this.handler != null)
                {
                    il.BeginExceptionBlock();
                }
            }
            this.body.TranslateToIL(il, Typeob.Void);
            if (this.tryEndContext != null)
            {
                this.tryEndContext.EmitLineInfo(il);
            }
            if (this.handler != null)
            {
                if (this.type == null)
                {
                    il.BeginCatchBlock(Typeob.Exception);
                    this.handler.context.EmitLineInfo(il);
                    base.EmitILToLoadEngine(il);
                    il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
                }
                else
                {
                    Type c = this.type.ToType();
                    if (Typeob.Exception.IsAssignableFrom(c))
                    {
                        il.BeginCatchBlock(c);
                        this.handler.context.EmitLineInfo(il);
                    }
                    else
                    {
                        il.BeginExceptFilterBlock();
                        this.handler.context.EmitLineInfo(il);
                        base.EmitILToLoadEngine(il);
                        il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
                        il.Emit(OpCodes.Isinst, c);
                        il.Emit(OpCodes.Ldnull);
                        il.Emit(OpCodes.Cgt_Un);
                        il.BeginCatchBlock(null);
                        base.EmitILToLoadEngine(il);
                        il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
                        Microsoft.JScript.Convert.Emit(this, il, Typeob.Object, c);
                    }
                }
                object obj2 = (this.field is JSVariableField) ? ((JSVariableField)this.field).GetMetaData() : this.field;
                if (obj2 is LocalBuilder)
                {
                    il.Emit(OpCodes.Stloc, (LocalBuilder)obj2);
                }
                else if (obj2 is FieldInfo)
                {
                    il.Emit(OpCodes.Stsfld, (FieldInfo)obj2);
                }
                else
                {
                    Microsoft.JScript.Convert.EmitLdarg(il, (short)obj2);
                }
                if (this.handler_scope != null)
                {
                    if (!this.handler_scope.isKnownAtCompileTime)
                    {
                        base.EmitILToLoadEngine(il);
                        il.Emit(OpCodes.Ldstr, this.fieldName);
                        ConstantWrapper.TranslateToILInt(il, this.handler_scope.scopeId);
                        il.Emit(OpCodes.Call, Typeob.Try.GetMethod("PushHandlerScope"));
                        base.Globals.ScopeStack.Push(this.handler_scope);
                        il.BeginExceptionBlock();
                    }
                    il.BeginScope();
                    if (base.context.document.debugOn)
                    {
                        this.handler_scope.EmitLocalInfoForFields(il);
                    }
                }
                this.handler.TranslateToIL(il, Typeob.Void);
                if (this.handler_scope != null)
                {
                    il.EndScope();
                    if (!this.handler_scope.isKnownAtCompileTime)
                    {
                        il.BeginFinallyBlock();
                        base.EmitILToLoadEngine(il);
                        il.Emit(OpCodes.Call, CompilerGlobals.popScriptObjectMethod);
                        il.Emit(OpCodes.Pop);
                        base.Globals.ScopeStack.Pop();
                        il.EndExceptionBlock();
                    }
                }
                il.EndExceptionBlock();
            }
            if (this.finally_block != null)
            {
                bool insideFinally   = base.compilerGlobals.InsideFinally;
                int  finallyStackTop = base.compilerGlobals.FinallyStackTop;
                base.compilerGlobals.InsideFinally   = true;
                base.compilerGlobals.FinallyStackTop = base.compilerGlobals.BreakLabelStack.Size();
                il.BeginFinallyBlock();
                this.finally_block.TranslateToIL(il, Typeob.Void);
                il.EndExceptionBlock();
                base.compilerGlobals.InsideFinally   = insideFinally;
                base.compilerGlobals.FinallyStackTop = finallyStackTop;
                if (this.finallyHasControlFlowOutOfIt)
                {
                    il.BeginCatchBlock(Typeob.BreakOutOfFinally);
                    il.Emit(OpCodes.Ldfld, Typeob.BreakOutOfFinally.GetField("target"));
                    int i    = base.compilerGlobals.BreakLabelStack.Size() - 1;
                    int num3 = i;
                    while (i > 0)
                    {
                        il.Emit(OpCodes.Dup);
                        ConstantWrapper.TranslateToILInt(il, i);
                        Label label = il.DefineLabel();
                        il.Emit(OpCodes.Blt_S, label);
                        il.Emit(OpCodes.Pop);
                        if (insideFinally && (i < finallyStackTop))
                        {
                            il.Emit(OpCodes.Rethrow);
                        }
                        else
                        {
                            il.Emit(OpCodes.Leave, (Label)base.compilerGlobals.BreakLabelStack.Peek(num3 - i));
                        }
                        il.MarkLabel(label);
                        i--;
                    }
                    il.Emit(OpCodes.Pop);
                    il.BeginCatchBlock(Typeob.ContinueOutOfFinally);
                    il.Emit(OpCodes.Ldfld, Typeob.ContinueOutOfFinally.GetField("target"));
                    int num4 = base.compilerGlobals.ContinueLabelStack.Size() - 1;
                    int num5 = num4;
                    while (num4 > 0)
                    {
                        il.Emit(OpCodes.Dup);
                        ConstantWrapper.TranslateToILInt(il, num4);
                        Label label2 = il.DefineLabel();
                        il.Emit(OpCodes.Blt_S, label2);
                        il.Emit(OpCodes.Pop);
                        if (insideFinally && (num4 < finallyStackTop))
                        {
                            il.Emit(OpCodes.Rethrow);
                        }
                        else
                        {
                            il.Emit(OpCodes.Leave, (Label)base.compilerGlobals.ContinueLabelStack.Peek(num5 - num4));
                        }
                        il.MarkLabel(label2);
                        num4--;
                    }
                    il.Emit(OpCodes.Pop);
                    ScriptObject parent = base.Globals.ScopeStack.Peek();
                    while ((parent != null) && !(parent is FunctionScope))
                    {
                        parent = parent.GetParent();
                    }
                    if ((parent != null) && !insideFinally)
                    {
                        il.BeginCatchBlock(Typeob.ReturnOutOfFinally);
                        il.Emit(OpCodes.Pop);
                        il.Emit(OpCodes.Leave, ((FunctionScope)parent).owner.returnLabel);
                    }
                    il.EndExceptionBlock();
                }
            }
            base.compilerGlobals.InsideProtectedRegion = insideProtectedRegion;
            base.compilerGlobals.BreakLabelStack.Pop();
            base.compilerGlobals.ContinueLabelStack.Pop();
        }
Exemple #23
0
 public void BeginExceptionFilterBlock()
 {
     ig.BeginExceptFilterBlock();
 }
Exemple #24
0
    public static Type AddType()
    {
        // Create an assembly.
        AssemblyName myAssemblyName = new AssemblyName();

        myAssemblyName.Name = "AdderExceptionAsm";

        // Create dynamic assembly.
        AppDomain       myAppDomain       = Thread.GetDomain();
        AssemblyBuilder myAssemblyBuilder = myAppDomain.DefineDynamicAssembly(myAssemblyName,
                                                                              AssemblyBuilderAccess.Run);

        // Create a dynamic module.
        ModuleBuilder myModuleBuilder = myAssemblyBuilder.DefineDynamicModule("AdderExceptionMod");
        TypeBuilder   myTypeBuilder   = myModuleBuilder.DefineType("Adder");

        Type[] adderParams = new Type[] { typeof(int), typeof(int) };

        // Define method to add two numbers.
        MethodBuilder myMethodBuilder = myTypeBuilder.DefineMethod("DoAdd", MethodAttributes.Public |
                                                                   MethodAttributes.Static, typeof(int), adderParams);
        ILGenerator myAdderIL = myMethodBuilder.GetILGenerator();

        // Create constructor.
        ConstructorInfo myConstructorInfo = typeof(OverflowException).GetConstructor(
            new Type[] { typeof(string) });
        MethodInfo myExToStrMI   = typeof(OverflowException).GetMethod("ToString");
        MethodInfo myWriteLineMI = typeof(Console).GetMethod("WriteLine", new Type[]
                                                             { typeof(string), typeof(object) });

        // Declare local variable.
        LocalBuilder myLocalBuilder1 = myAdderIL.DeclareLocal(typeof(int));
        LocalBuilder myLocalBuilder2 = myAdderIL.DeclareLocal(typeof(OverflowException));

        // Define label.
        Label myFailedLabel      = myAdderIL.DefineLabel();
        Label myEndOfMethodLabel = myAdderIL.DefineLabel();

        // Begin exception block.
        Label myLabel = myAdderIL.BeginExceptionBlock();

        myAdderIL.Emit(OpCodes.Ldarg_0);
        myAdderIL.Emit(OpCodes.Ldc_I4_S, 10);
        myAdderIL.Emit(OpCodes.Bgt_S, myFailedLabel);

        myAdderIL.Emit(OpCodes.Ldarg_1);
        myAdderIL.Emit(OpCodes.Ldc_I4_S, 10);
        myAdderIL.Emit(OpCodes.Bgt_S, myFailedLabel);

        myAdderIL.Emit(OpCodes.Ldarg_0);
        myAdderIL.Emit(OpCodes.Ldarg_1);
        myAdderIL.Emit(OpCodes.Add_Ovf_Un);
        myAdderIL.Emit(OpCodes.Stloc_S, myLocalBuilder1);
        myAdderIL.Emit(OpCodes.Br_S, myEndOfMethodLabel);

        myAdderIL.MarkLabel(myFailedLabel);
        myAdderIL.Emit(OpCodes.Ldstr, "Cannot accept values over 10 for add.");
        myAdderIL.Emit(OpCodes.Newobj, myConstructorInfo);

        myAdderIL.Emit(OpCodes.Stloc_S, myLocalBuilder2);
        myAdderIL.Emit(OpCodes.Ldloc_S, myLocalBuilder2);

        // Throw the exception.
        myAdderIL.ThrowException(typeof(OverflowException));

        // Call 'BeginExceptFilterBlock'.
        myAdderIL.BeginExceptFilterBlock();
        myAdderIL.EmitWriteLine("Except filter block called.");

        // Call catch block.
        myAdderIL.BeginCatchBlock(null);

        // Call other catch block.
        myAdderIL.BeginCatchBlock(typeof(OverflowException));

        myAdderIL.Emit(OpCodes.Ldstr, "{0}");
        myAdderIL.Emit(OpCodes.Ldloc_S, myLocalBuilder2);
        myAdderIL.EmitCall(OpCodes.Callvirt, myExToStrMI, null);
        myAdderIL.EmitCall(OpCodes.Call, myWriteLineMI, null);
        myAdderIL.Emit(OpCodes.Ldc_I4_M1);
        myAdderIL.Emit(OpCodes.Stloc_S, myLocalBuilder1);

        // Call finally block.
        myAdderIL.BeginFinallyBlock();
        myAdderIL.EmitWriteLine("Finally block called.");

        // End the exception block.
        myAdderIL.EndExceptionBlock();

        myAdderIL.MarkLabel(myEndOfMethodLabel);
        myAdderIL.Emit(OpCodes.Ldloc_S, myLocalBuilder1);
        myAdderIL.Emit(OpCodes.Ret);

        return(myTypeBuilder.CreateType());
    }