예제 #1
0
        private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeNodeNeedingCode)
        {
            MethodDesc method = methodCodeNodeNeedingCode.Method;

            try
            {
                corInfo.CompileMethod(methodCodeNodeNeedingCode);
            }
            catch (TypeSystemException ex)
            {
                // TODO: fail compilation if a switch was passed

                // Try to compile the method again, but with a throwing method body this time.
                MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, ex);
                corInfo.CompileMethod(methodCodeNodeNeedingCode, throwingIL);

                // TODO: Log as a warning. For now, just log to the logger; but this needs to
                // have an error code, be supressible, the method name/sig needs to be properly formatted, etc.
                // https://github.com/dotnet/corert/issues/72
                Logger.Writer.WriteLine($"Warning: Method `{method}` will always throw because: {ex.Message}");
            }
            finally
            {
                if (_compilationCountdown != null)
                {
                    _compilationCountdown.Signal();
                }
            }
        }
예제 #2
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);
        }
예제 #3
0
        private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeNodeNeedingCode)
        {
            MethodDesc method = methodCodeNodeNeedingCode.Method;

            TypeSystemException exception = _methodImportationErrorProvider.GetCompilationError(method);

            // If we previously failed to import the method, do not try to import it again and go
            // directly to the error path.
            if (exception == null)
            {
                try
                {
                    corInfo.CompileMethod(methodCodeNodeNeedingCode);
                }
                catch (TypeSystemException ex)
                {
                    exception = ex;
                }
            }

            if (exception != null)
            {
                // Try to compile the method again, but with a throwing method body this time.
                MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, exception);
                corInfo.CompileMethod(methodCodeNodeNeedingCode, throwingIL);

                if (exception is TypeSystemException.InvalidProgramException &&
                    method.OwningType is MetadataType mdOwningType &&
                    mdOwningType.HasCustomAttribute("System.Runtime.InteropServices", "ClassInterfaceAttribute"))
                {
                    Logger.LogWarning(method, DiagnosticId.COMInteropNotSupportedInFullAOT);
                }
                if ((_compilationOptions & RyuJitCompilationOptions.UseResilience) != 0)
                {
                    Logger.LogMessage($"Method '{method}' will always throw because: {exception.Message}");
                }
                else
                {
                    Logger.LogError($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis);
                }
            }
        }
예제 #4
0
        private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeNodeNeedingCode)
        {
            try
            {
                MethodDesc method = methodCodeNodeNeedingCode.Method;

                TypeSystemException exception = _methodImportationErrorProvider.GetCompilationError(method);

                // If we previously failed to import the method, do not try to import it again and go
                // directly to the error path.
                if (exception == null)
                {
                    try
                    {
                        corInfo.CompileMethod(methodCodeNodeNeedingCode);
                    }
                    catch (TypeSystemException ex)
                    {
                        exception = ex;
                    }
                }

                if (exception != null)
                {
                    // TODO: fail compilation if a switch was passed

                    // Try to compile the method again, but with a throwing method body this time.
                    MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, exception);
                    corInfo.CompileMethod(methodCodeNodeNeedingCode, throwingIL);

                    if (exception is TypeSystemException.InvalidProgramException &&
                        method.OwningType is MetadataType mdOwningType &&
                        mdOwningType.HasCustomAttribute("System.Runtime.InteropServices", "ClassInterfaceAttribute"))
                    {
                        Logger.LogWarning("COM interop is not supported with full ahead of time compilation", 3052, method, MessageSubCategory.AotAnalysis);
                    }
                    else
                    {
                        Logger.LogWarning($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis);
                    }
                }
            }
예제 #5
0
        private void CompileSingleMethod(MethodCodeNode methodCodeNodeNeedingCode)
        {
            CorInfoImpl corInfo = _corinfos.GetValue(Thread.CurrentThread, thread => new CorInfoImpl(this));

            CompileSingleMethod(corInfo, methodCodeNodeNeedingCode);
        }