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); }
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; } }
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(); }
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); }
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; } }
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())); }
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; } }
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(); }
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(); }
public void BeginExceptionFilterBlock() { ig.BeginExceptFilterBlock(); }
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()); }