Exemple #1
0
 public void TestAllExceptionIdsHaveMessages()
 {
     foreach (var exceptionId in (ExceptionStringID[])Enum.GetValues(typeof(ExceptionStringID)))
     {
         Assert.NotNull(TypeSystemException.GetFormatString(exceptionId));
     }
 }
        public static MethodIL EmitIL(MethodDesc methodThatShouldThrow, TypeSystemException exception)
        {
            TypeSystemContext context = methodThatShouldThrow.Context;

            MethodDesc helper;

            Type exceptionType = exception.GetType();

            if (exceptionType == typeof(TypeSystemException.TypeLoadException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadException");
            }
            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));
        }
Exemple #3
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);
        }
Exemple #4
0
        public void InitializeDependencies(NodeFactory factory, IEnumerable <DependencyListEntry> dependencies, TypeSystemException scanningException = null)
        {
            _dependencies = new DependencyList(dependencies);

            if (factory.TypeSystemContext.IsSpecialUnboxingThunk(_method))
            {
                // Special unboxing thunks reference a MethodAssociatedDataNode that points to the non-unboxing version.
                // This dependency is redundant with the dependency list we constructed above, with a notable
                // exception of special unboxing thunks for byref-like types. Those don't actually unbox anything
                // and their body is a dummy. We capture the dependency here.
                MethodDesc nonUnboxingMethod = factory.TypeSystemContext.GetTargetOfSpecialUnboxingThunk(_method);
                _dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(nonUnboxingMethod, false), "Non-unboxing method"));
            }

            _exception = scanningException;
        }
        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);
                }
            }
        }
Exemple #6
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);
                    }
                }
            }