/// <summary> /// Compiles the provided method code node while swapping it's body with a throwing stub. /// </summary> private bool TryCompileWithThrowingBody(MethodCodeNode methodNode, TypeSystemException exception) { MethodDesc helper; Type exceptionType = exception.GetType(); if (exceptionType == typeof(TypeSystemException.TypeLoadException)) { helper = _typeSystemContext.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadException"); } else if (exceptionType == typeof(TypeSystemException.MissingFieldException)) { helper = _typeSystemContext.GetHelperEntryPoint("ThrowHelpers", "ThrowMissingFieldException"); } else if (exceptionType == typeof(TypeSystemException.MissingMethodException)) { helper = _typeSystemContext.GetHelperEntryPoint("ThrowHelpers", "ThrowMissingMethodException"); } else if (exceptionType == typeof(TypeSystemException.FileNotFoundException)) { helper = _typeSystemContext.GetHelperEntryPoint("ThrowHelpers", "ThrowFileNotFoundException"); } else if (exceptionType == typeof(TypeSystemException.InvalidProgramException)) { helper = _typeSystemContext.GetHelperEntryPoint("ThrowHelpers", "ThrowInvalidProgramException"); } else { return false; } Debug.Assert(helper.Signature.Length == exception.Arguments.Count + 1); var emitter = new Internal.IL.Stubs.ILEmitter(); var codeStream = emitter.NewCodeStream(); var infinityLabel = emitter.NewCodeLabel(); codeStream.EmitLabel(infinityLabel); codeStream.EmitLdc((int)exception.StringID); foreach (var arg in exception.Arguments) { codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(arg)); } codeStream.Emit(ILOpcode.call, emitter.NewToken(helper)); // The call will never return, but we still need to emit something. Emit a jump so that // we don't have to bother balancing the stack if the method returns something. codeStream.Emit(ILOpcode.br, infinityLabel); _corInfo.CompileMethod(methodNode, emitter.Link(methodNode.Method)); return true; }
public static MethodIL EmitIL(MethodDesc methodThatShouldThrow, TypeSystemException exception) { TypeSystemContext context = methodThatShouldThrow.Context; MethodDesc helper; Type exceptionType = exception.GetType(); if (exceptionType == typeof(TypeSystemException.TypeLoadException)) { // // There are two ThrowTypeLoadException helpers. Find the one which matches the number of // arguments "exception" was initialized with. // helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadException"); if (helper.Signature.Length != exception.Arguments.Count + 1) { helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadExceptionWithArgument"); } } else if (exceptionType == typeof(TypeSystemException.MissingFieldException)) { helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowMissingFieldException"); } else if (exceptionType == typeof(TypeSystemException.MissingMethodException)) { helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowMissingMethodException"); } else if (exceptionType == typeof(TypeSystemException.FileNotFoundException)) { helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowFileNotFoundException"); } else if (exceptionType == typeof(TypeSystemException.InvalidProgramException)) { helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowInvalidProgramException"); } else { throw new NotImplementedException(); } Debug.Assert(helper.Signature.Length == exception.Arguments.Count + 1); var emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); var infinityLabel = emitter.NewCodeLabel(); codeStream.EmitLabel(infinityLabel); codeStream.EmitLdc((int)exception.StringID); foreach (var arg in exception.Arguments) { codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(arg)); } codeStream.Emit(ILOpcode.call, emitter.NewToken(helper)); // The call will never return, but we still need to emit something. Emit a jump so that // we don't have to bother balancing the stack if the method returns something. codeStream.Emit(ILOpcode.br, infinityLabel); return emitter.Link(methodThatShouldThrow); }