Ejemplo n.º 1
0
        /// <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);
        }