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)); }
/// <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 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); } } }
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); } } }