Refactor missing reference errors to allow not throwing for all cases (#50437)
authorDavid Wrighton <davidwr@microsoft.com>
Wed, 31 Mar 2021 17:50:25 +0000 (10:50 -0700)
committerGitHub <noreply@github.com>
Wed, 31 Mar 2021 17:50:25 +0000 (10:50 -0700)
- Build the concept of a cacheable resolution failure
- Plumb it through the Ecma type loader and the required public api surfaces
- Use it within the Mibc parser to avoid throwing

28 files changed:
src/coreclr/tools/Common/Compiler/TypeExtensions.cs
src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs
src/coreclr/tools/Common/TypeSystem/Common/MetadataTypeSystemContext.cs
src/coreclr/tools/Common/TypeSystem/Common/ModuleDesc.cs
src/coreclr/tools/Common/TypeSystem/Common/NotFoundBehavior.cs [new file with mode: 0644]
src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx
src/coreclr/tools/Common/TypeSystem/Common/ResolutionFailure.cs [new file with mode: 0644]
src/coreclr/tools/Common/TypeSystem/Common/ThrowHelper.Common.cs
src/coreclr/tools/Common/TypeSystem/Common/ThrowHelper.cs
src/coreclr/tools/Common/TypeSystem/Common/TypeSystemException.cs
src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs
src/coreclr/tools/Common/TypeSystem/Ecma/EcmaField.cs
src/coreclr/tools/Common/TypeSystem/Ecma/EcmaMethod.cs
src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs
src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs
src/coreclr/tools/Common/TypeSystem/IL/EcmaMethodIL.cs
src/coreclr/tools/Common/TypeSystem/IL/HelperExtensions.cs
src/coreclr/tools/Common/TypeSystem/IL/InstantiatedMethodIL.cs
src/coreclr/tools/Common/TypeSystem/IL/MethodIL.cs
src/coreclr/tools/Common/TypeSystem/IL/Stubs/ILEmitter.cs
src/coreclr/tools/ILVerification/ILVerification.projitems
src/coreclr/tools/ILVerification/SimpleArrayOfTRuntimeInterfacesAlgorithm.cs
src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCProfileParser.cs
src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs
src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj
src/coreclr/tools/dotnet-pgo/R2RSignatureTypeProvider.cs
src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs
src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemModule.cs

index e75f982..c941896 100644 (file)
@@ -32,7 +32,7 @@ namespace ILCompiler
             {
                 if (!type.IsArrayTypeWithoutGenericInterfaces())
                 {
-                    MetadataType arrayShadowType = type.Context.SystemModule.GetType("System", "Array`1", throwIfNotFound: false);
+                    MetadataType arrayShadowType = type.Context.SystemModule.GetType("System", "Array`1", NotFoundBehavior.ReturnNull);
                     if (arrayShadowType != null)
                     {
                         return arrayShadowType.MakeInstantiatedType(((ArrayType)type).ElementType);
index d9d3de4..dd38a71 100644 (file)
@@ -40,5 +40,6 @@ namespace Internal.TypeSystem
 
         // BadImageFormatException
         BadImageFormatGeneric,
+        BadImageFormatSpecific,
     }
 }
index b578eb6..d8ed92d 100644 (file)
@@ -73,7 +73,7 @@ namespace Internal.TypeSystem
             {
                 // Require System.Object to be present as a minimal sanity check. 
                 // The set of required well-known types is not strictly defined since different .NET profiles implement different subsets.
-                MetadataType type = systemModule.GetType("System", s_wellKnownTypeNames[typeIndex], typeIndex == (int)WellKnownType.Object);
+                MetadataType type = systemModule.GetType("System", s_wellKnownTypeNames[typeIndex], typeIndex == (int)WellKnownType.Object ? NotFoundBehavior.Throw : NotFoundBehavior.ReturnNull);
                 if (type != null)
                 {
                     type.SetWellKnownType((WellKnownType)(typeIndex + 1));
index c1e143d..f2d45c1 100644 (file)
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System;
 using System.Collections.Generic;
 
 namespace Internal.TypeSystem
@@ -28,8 +29,13 @@ namespace Internal.TypeSystem
 
         /// <summary>
         /// Gets a type in this module with the specified name.
+        /// If notFoundBehavior == NotFoundBehavior.ReturnResolutionFailure
+        /// then ModuleDesc.GetTypeResolutionFailure will be set to the failure, and the function will return null
         /// </summary>
-        public abstract MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true);
+        public abstract MetadataType GetType(string nameSpace, string name, NotFoundBehavior notFoundBehavior = NotFoundBehavior.Throw);
+
+        [ThreadStatic]
+        public static ResolutionFailure GetTypeResolutionFailure;
 
         /// <summary>
         /// Gets the global &lt;Module&gt; type.
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/NotFoundBehavior.cs b/src/coreclr/tools/Common/TypeSystem/Common/NotFoundBehavior.cs
new file mode 100644 (file)
index 0000000..1403bb8
--- /dev/null
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Internal.TypeSystem
+{
+    public enum NotFoundBehavior
+    {
+        Throw,
+        ReturnNull,
+        ReturnResolutionFailure
+    }
+}
\ No newline at end of file
index b0efd67..489fa6d 100644 (file)
   <data name="BadImageFormatGeneric" xml:space="preserve">
     <value>The format of a DLL or executable being loaded is invalid</value>
   </data>
+  <data name="BadImageFormatSpecific" xml:space="preserve">
+    <value>The format of a DLL or executable being loaded is invalid with {0}</value>
+  </data>
 </root>
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/ResolutionFailure.cs b/src/coreclr/tools/Common/TypeSystem/Common/ResolutionFailure.cs
new file mode 100644 (file)
index 0000000..04d75a5
--- /dev/null
@@ -0,0 +1,110 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Internal.TypeSystem
+{
+    public sealed class ResolutionFailure
+    {
+        private enum FailureType
+        {
+            TypeLoadException1,
+            TypeLoadException2,
+            TypeLoadException3,
+            MissingMethodException1,
+            MissingFieldException1,
+            MissingAssemblyException1,
+        }
+
+        private ResolutionFailure() { }
+
+        private FailureType _failureType;
+        private string _namespace;
+        private string _name;
+        private string _moduleName;
+        private ModuleDesc _module;
+        private TypeDesc _owningType;
+        private MethodSignature _methodSignature;
+
+
+        public static ResolutionFailure GetTypeLoadResolutionFailure(string nestedTypeName, ModuleDesc module)
+        {
+            ResolutionFailure failure = new ResolutionFailure();
+            failure._failureType = FailureType.TypeLoadException1;
+            failure._name = nestedTypeName;
+            failure._module = module;
+            return failure;
+        }
+
+        public static ResolutionFailure GetTypeLoadResolutionFailure(string @namespace, string name, ModuleDesc module)
+        {
+            ResolutionFailure failure = new ResolutionFailure();
+            failure._failureType = FailureType.TypeLoadException2;
+            failure._namespace = @namespace;
+            failure._name = name;
+            failure._module = module;
+            return failure;
+        }
+
+        public static ResolutionFailure GetTypeLoadResolutionFailure(string @namespace, string name, string moduleName)
+        {
+            ResolutionFailure failure = new ResolutionFailure();
+            failure._failureType = FailureType.TypeLoadException3;
+            failure._namespace = @namespace;
+            failure._name = name;
+            failure._moduleName = moduleName;
+            return failure;
+        }
+
+        public static ResolutionFailure GetMissingMethodFailure(TypeDesc owningType, string methodName, MethodSignature signature)
+        {
+            ResolutionFailure failure = new ResolutionFailure();
+            failure._failureType = FailureType.MissingMethodException1;
+            failure._methodSignature = signature;
+            failure._name = methodName;
+            failure._owningType = owningType;
+            return failure;
+        }
+
+        public static ResolutionFailure GetMissingFieldFailure(TypeDesc owningType, string fieldName)
+        {
+            ResolutionFailure failure = new ResolutionFailure();
+            failure._failureType = FailureType.MissingMethodException1;
+            failure._name = fieldName;
+            failure._owningType = owningType;
+            return failure;
+        }
+
+        public static ResolutionFailure GetAssemblyResolutionFailure(string simpleName)
+        {
+            ResolutionFailure failure = new ResolutionFailure();
+            failure._failureType = FailureType.MissingAssemblyException1;
+            failure._name = simpleName;
+            return failure;
+        }
+
+        public void Throw()
+        {
+            switch(_failureType)
+            {
+                case FailureType.TypeLoadException1:
+                    ThrowHelper.ThrowTypeLoadException(_name, _module);
+                    break;
+                case FailureType.TypeLoadException2:
+                    ThrowHelper.ThrowTypeLoadException(_namespace, _name, _module);
+                    break;
+                case FailureType.TypeLoadException3:
+                    ThrowHelper.ThrowTypeLoadException(_namespace, _name, _moduleName);
+                    break;
+                case FailureType.MissingMethodException1:
+                    ThrowHelper.ThrowMissingMethodException(_owningType, _name, _methodSignature);
+                    break;
+                case FailureType.MissingFieldException1:
+                    ThrowHelper.ThrowMissingFieldException(_owningType, _name);
+                    break;
+                case FailureType.MissingAssemblyException1:
+                    ThrowHelper.ThrowFileNotFoundException(ExceptionStringID.FileLoadErrorGeneric, _name);
+                    break;
+            }
+        }
+    }
+}
index bfe36b4..cf644ad 100644 (file)
@@ -22,6 +22,11 @@ namespace Internal.TypeSystem
             ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, Format.Type(@namespace, name), Format.Module(module));
         }
 
+        public static void ThrowTypeLoadException(string @namespace, string name, string moduleName)
+        {
+            ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, Format.Type(@namespace, name), moduleName);
+        }
+
         [System.Diagnostics.DebuggerHidden]
         public static void ThrowTypeLoadException(TypeDesc type)
         {
index 094ade1..90c02f6 100644 (file)
@@ -59,6 +59,12 @@ namespace Internal.TypeSystem
             throw new TypeSystemException.BadImageFormatException();
         }
 
+        [System.Diagnostics.DebuggerHidden]
+        public static void ThrowBadImageFormatException(string message)
+        {
+            throw new TypeSystemException.BadImageFormatException(message);
+        }
+
         private static partial class Format
         {
             public static string OwningModule(TypeDesc type)
index 17836ca..598f0f6 100644 (file)
@@ -155,6 +155,12 @@ namespace Internal.TypeSystem
                 : base(ExceptionStringID.BadImageFormatGeneric)
             {
             }
+
+            internal BadImageFormatException(string reason)
+                : base(ExceptionStringID.BadImageFormatSpecific, reason)
+            {
+
+            }
         }
     }
 }
index 1b901f5..d63e92d 100644 (file)
@@ -276,7 +276,7 @@ namespace Internal.TypeSystem
                 namespaceName = fullName.Substring(0, split);
                 typeName = fullName.Substring(split + 1);
             }
-            return module.GetType(namespaceName, typeName, throwIfNotFound);
+            return module.GetType(namespaceName, typeName, throwIfNotFound ? NotFoundBehavior.Throw : NotFoundBehavior.ReturnNull);
         }
 
         private static AssemblyName FindAssemblyIfNamePresent(string name)
index 31a4c8d..b6d5e4f 100644 (file)
@@ -98,7 +98,7 @@ namespace Internal.TypeSystem.Ecma
             var metadataReader = MetadataReader;
             BlobReader signatureReader = metadataReader.GetBlobReader(metadataReader.GetFieldDefinition(_handle).Signature);
 
-            EcmaSignatureParser parser = new EcmaSignatureParser(Module, signatureReader);
+            EcmaSignatureParser parser = new EcmaSignatureParser(Module, signatureReader, NotFoundBehavior.Throw);
             var fieldType = parser.ParseFieldSignature();
             return (_fieldType = fieldType);
         }
@@ -264,7 +264,7 @@ namespace Internal.TypeSystem.Ecma
             if ((definition.Attributes & FieldAttributes.HasFieldMarshal) != 0)
             {
                 BlobReader marshalAsReader = reader.GetBlobReader(definition.GetMarshallingDescriptor());
-                EcmaSignatureParser parser = new EcmaSignatureParser(_type.EcmaModule, marshalAsReader);
+                EcmaSignatureParser parser = new EcmaSignatureParser(_type.EcmaModule, marshalAsReader, NotFoundBehavior.Throw);
                 return parser.ParseMarshalAsDescriptor();
             }
 
index da51265..182a87c 100644 (file)
@@ -82,7 +82,7 @@ namespace Internal.TypeSystem.Ecma
             var metadataReader = MetadataReader;
             BlobReader signatureReader = metadataReader.GetBlobReader(metadataReader.GetMethodDefinition(_handle).Signature);
 
-            EcmaSignatureParser parser = new EcmaSignatureParser(Module, signatureReader);
+            EcmaSignatureParser parser = new EcmaSignatureParser(Module, signatureReader, NotFoundBehavior.Throw);
             var signature = parser.ParseMethodSignature();
             return (_signature = signature);
         }
@@ -573,7 +573,7 @@ namespace Internal.TypeSystem.Ecma
             {
                 MetadataReader metadataReader = MetadataReader;
                 BlobReader marshalAsReader = metadataReader.GetBlobReader(parameter.GetMarshallingDescriptor());
-                EcmaSignatureParser parser = new EcmaSignatureParser(Module, marshalAsReader);
+                EcmaSignatureParser parser = new EcmaSignatureParser(Module, marshalAsReader, NotFoundBehavior.Throw);
                 MarshalAsDescriptor marshalAs = parser.ParseMarshalAsDescriptor();
                 Debug.Assert(marshalAs != null);
                 return marshalAs;
index 389f060..737b266 100644 (file)
@@ -96,7 +96,7 @@ namespace Internal.TypeSystem.Ecma
                         {
                             MethodDefinitionHandle methodDefinitionHandle = (MethodDefinitionHandle)handle;
                             TypeDefinitionHandle typeDefinitionHandle = _module._metadataReader.GetMethodDefinition(methodDefinitionHandle).GetDeclaringType();
-                            EcmaType type = (EcmaType)_module.GetObject(typeDefinitionHandle);
+                            EcmaType type = (EcmaType)_module.GetObject(typeDefinitionHandle, NotFoundBehavior.Throw);
                             item = new EcmaMethod(type, methodDefinitionHandle);
                         }
                         break;
@@ -105,7 +105,7 @@ namespace Internal.TypeSystem.Ecma
                         {
                             FieldDefinitionHandle fieldDefinitionHandle = (FieldDefinitionHandle)handle;
                             TypeDefinitionHandle typeDefinitionHandle = _module._metadataReader.GetFieldDefinition(fieldDefinitionHandle).GetDeclaringType();
-                            EcmaType type = (EcmaType)_module.GetObject(typeDefinitionHandle);
+                            EcmaType type = (EcmaType)_module.GetObject(typeDefinitionHandle, NotFoundBehavior.Throw);
                             item = new EcmaField(type, fieldDefinitionHandle);
                         }
                         break;
@@ -149,7 +149,9 @@ namespace Internal.TypeSystem.Ecma
                         break;
 
                     default:
-                        throw new BadImageFormatException("Unknown metadata token type: " + handle.Kind);
+                        ThrowHelper.ThrowBadImageFormatException("unknown metadata token type: " + handle.Kind);
+                        item = null;
+                        break;
                 }
 
                 switch (handle.Kind)
@@ -261,7 +263,8 @@ namespace Internal.TypeSystem.Ecma
                 }
 
                 // Bad metadata
-                throw new BadImageFormatException();
+                ThrowHelper.ThrowBadImageFormatException();
+                return null;
             }
         }
 
@@ -277,7 +280,7 @@ namespace Internal.TypeSystem.Ecma
             }
         }
 
-        public sealed override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
+        public sealed override MetadataType GetType(string nameSpace, string name, NotFoundBehavior notFoundBehavior)
         {
             var stringComparer = _metadataReader.StringComparer;
 
@@ -300,12 +303,20 @@ namespace Internal.TypeSystem.Ecma
                 {
                     if (exportedType.IsForwarder)
                     {
-                        Object implementation = GetObject(exportedType.Implementation);
+                        Object implementation = GetObject(exportedType.Implementation, notFoundBehavior);
+
+                        if (implementation == null)
+                            return null;
 
                         if (implementation is ModuleDesc)
                         {
                             return ((ModuleDesc)(implementation)).GetType(nameSpace, name);
                         }
+                        else if (implementation is ResolutionFailure failure)
+                        {
+                            ModuleDesc.GetTypeResolutionFailure = failure;
+                            return null;
+                        }
 
                         // TODO
                         throw new NotImplementedException();
@@ -315,42 +326,57 @@ namespace Internal.TypeSystem.Ecma
                 }
             }
 
-            if (throwIfNotFound)
-                ThrowHelper.ThrowTypeLoadException(nameSpace, name, this);
+            if (notFoundBehavior != NotFoundBehavior.ReturnNull)
+            {
+                var failure = ResolutionFailure.GetTypeLoadResolutionFailure(nameSpace, name, this);
+                if (notFoundBehavior == NotFoundBehavior.Throw)
+                    failure.Throw();
+
+                ModuleDesc.GetTypeResolutionFailure = failure;
+                return null;
+            }
 
             return null;
         }
 
         public TypeDesc GetType(EntityHandle handle)
         {
-            TypeDesc type = GetObject(handle) as TypeDesc;
+            TypeDesc type = GetObject(handle, NotFoundBehavior.Throw) as TypeDesc;
             if (type == null)
-                throw new BadImageFormatException("Type expected");
+                ThrowHelper.ThrowBadImageFormatException($"type expected for handle {handle.ToString()}");
             return type;
         }
 
         public MethodDesc GetMethod(EntityHandle handle)
         {
-            MethodDesc method = GetObject(handle) as MethodDesc;
+            MethodDesc method = GetObject(handle, NotFoundBehavior.Throw) as MethodDesc;
             if (method == null)
-                throw new BadImageFormatException("Method expected");
+                ThrowHelper.ThrowBadImageFormatException($"method expected for handle {handle.ToString()}");
             return method;
         }
 
         public FieldDesc GetField(EntityHandle handle)
         {
-            FieldDesc field = GetObject(handle) as FieldDesc;
+            FieldDesc field = GetObject(handle, NotFoundBehavior.Throw) as FieldDesc;
             if (field == null)
-                throw new BadImageFormatException("Field expected");
+                ThrowHelper.ThrowBadImageFormatException($"field expected for handle {handle.ToString()}");
             return field;
         }
 
-        public Object GetObject(EntityHandle handle)
+        public Object GetObject(EntityHandle handle, NotFoundBehavior notFoundBehavior = NotFoundBehavior.Throw)
         {
             IEntityHandleObject obj = _resolvedTokens.GetOrCreateValue(handle);
             if (obj is EcmaObjectLookupWrapper)
             {
-                return ((EcmaObjectLookupWrapper)obj).Object;
+                object result = ((EcmaObjectLookupWrapper)obj).Object;
+                if ((result is ResolutionFailure failure) && (notFoundBehavior != NotFoundBehavior.ReturnResolutionFailure))
+                {
+                    if (notFoundBehavior == NotFoundBehavior.ReturnNull)
+                        return null;
+                    else
+                        failure.Throw();
+                }
+                return result;
             }
             else
             {
@@ -362,12 +388,22 @@ namespace Internal.TypeSystem.Ecma
         {
             MethodSpecification methodSpecification = _metadataReader.GetMethodSpecification(handle);
 
-            MethodDesc methodDef = GetMethod(methodSpecification.Method);
+            object resolvedMethod = GetObject(methodSpecification.Method, NotFoundBehavior.ReturnResolutionFailure);
+            if (resolvedMethod is ResolutionFailure)
+                return resolvedMethod;
+
+            MethodDesc methodDef = resolvedMethod as MethodDesc;
+            if (methodDef == null)
+                ThrowHelper.ThrowBadImageFormatException($"method expected for handle {handle.ToString()}");
 
             BlobReader signatureReader = _metadataReader.GetBlobReader(methodSpecification.Signature);
-            EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader);
+            EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader, NotFoundBehavior.ReturnResolutionFailure);
 
             TypeDesc[] instantiation = parser.ParseMethodSpecSignature();
+
+            if (instantiation == null)
+                return parser.ResolutionFailure;
+
             return Context.GetInstantiatedMethod(methodDef, new Instantiation(instantiation));
         }
 
@@ -375,9 +411,11 @@ namespace Internal.TypeSystem.Ecma
         {
             StandaloneSignature signature = _metadataReader.GetStandaloneSignature(handle);
             BlobReader signatureReader = _metadataReader.GetBlobReader(signature.Signature);
-            EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader);
+            EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader, NotFoundBehavior.ReturnResolutionFailure);
 
             MethodSignature methodSig = parser.ParseMethodSignature();
+            if (methodSig == null)
+                return parser.ResolutionFailure;
             return methodSig;
         }
 
@@ -386,23 +424,30 @@ namespace Internal.TypeSystem.Ecma
             TypeSpecification typeSpecification = _metadataReader.GetTypeSpecification(handle);
 
             BlobReader signatureReader = _metadataReader.GetBlobReader(typeSpecification.Signature);
-            EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader);
+            EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader, NotFoundBehavior.ReturnResolutionFailure);
 
-            return parser.ParseType();
+            TypeDesc parsedType = parser.ParseType();
+            if (parsedType == null)
+                return parser.ResolutionFailure;
+            else
+                return parsedType;
         }
 
         private Object ResolveMemberReference(MemberReferenceHandle handle)
         {
             MemberReference memberReference = _metadataReader.GetMemberReference(handle);
 
-            Object parent = GetObject(memberReference.Parent);
+            Object parent = GetObject(memberReference.Parent, NotFoundBehavior.ReturnResolutionFailure);
+
+            if (parent is ResolutionFailure)
+                return parent;
 
             TypeDesc parentTypeDesc = parent as TypeDesc;
             if (parentTypeDesc != null)
             {
                 BlobReader signatureReader = _metadataReader.GetBlobReader(memberReference.Signature);
 
-                EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader);
+                EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader, NotFoundBehavior.ReturnResolutionFailure);
 
                 string name = _metadataReader.GetString(memberReference.Name);
 
@@ -412,11 +457,13 @@ namespace Internal.TypeSystem.Ecma
                     if (field != null)
                         return field;
 
-                    ThrowHelper.ThrowMissingFieldException(parentTypeDesc, name);
+                    return ResolutionFailure.GetMissingFieldFailure(parentTypeDesc, name);
                 }
                 else
                 {
                     MethodSignature sig = parser.ParseMethodSignature();
+                    if (sig == null)
+                        return parser.ResolutionFailure;
                     TypeDesc typeDescToInspect = parentTypeDesc;
                     Instantiation substitution = default(Instantiation);
 
@@ -460,7 +507,7 @@ namespace Internal.TypeSystem.Ecma
                         typeDescToInspect = baseType;
                     } while (typeDescToInspect != null);
 
-                    ThrowHelper.ThrowMissingMethodException(parentTypeDesc, name, sig);
+                    return ResolutionFailure.GetMissingMethodFailure(parentTypeDesc, name, sig);
                 }
             }
             else if (parent is MethodDesc)
@@ -472,18 +519,26 @@ namespace Internal.TypeSystem.Ecma
                 throw new NotImplementedException("MemberRef to a global function or variable.");
             }
 
-            throw new BadImageFormatException();
+            ThrowHelper.ThrowBadImageFormatException();
+            return null;
         }
 
         private Object ResolveTypeReference(TypeReferenceHandle handle)
         {
             TypeReference typeReference = _metadataReader.GetTypeReference(handle);
 
-            Object resolutionScope = GetObject(typeReference.ResolutionScope);
+            Object resolutionScope = GetObject(typeReference.ResolutionScope, NotFoundBehavior.ReturnResolutionFailure);
+            if (resolutionScope is ResolutionFailure)
+            {
+                return resolutionScope;
+            }
 
             if (resolutionScope is ModuleDesc)
             {
-                return ((ModuleDesc)(resolutionScope)).GetType(_metadataReader.GetString(typeReference.Namespace), _metadataReader.GetString(typeReference.Name));
+                object result = ((ModuleDesc)(resolutionScope)).GetType(_metadataReader.GetString(typeReference.Namespace), _metadataReader.GetString(typeReference.Name), NotFoundBehavior.ReturnResolutionFailure);
+                if (result == null)
+                    result = ModuleDesc.GetTypeResolutionFailure;
+                return result;
             }
             else
             if (resolutionScope is MetadataType)
@@ -495,7 +550,7 @@ namespace Internal.TypeSystem.Ecma
                 if (result != null)
                     return result;
 
-                ThrowHelper.ThrowTypeLoadException(typeName, ((MetadataType)resolutionScope).Module);
+                return ResolutionFailure.GetTypeLoadResolutionFailure(typeName, ((MetadataType)resolutionScope).Module);
             }
 
             // TODO
@@ -523,20 +578,24 @@ namespace Internal.TypeSystem.Ecma
             an.CultureName = _metadataReader.GetString(assemblyReference.Culture);
             an.ContentType = GetContentTypeFromAssemblyFlags(assemblyReference.Flags);
 
-            return _moduleResolver.ResolveAssembly(an);
+            var assembly = _moduleResolver.ResolveAssembly(an, throwIfNotFound: false);
+            if (assembly == null)
+                return ResolutionFailure.GetAssemblyResolutionFailure(an.Name);
+            else
+                return assembly;
         }
 
         private Object ResolveExportedType(ExportedTypeHandle handle)
         {
             ExportedType exportedType = _metadataReader.GetExportedType(handle);
 
-            var implementation = GetObject(exportedType.Implementation);
+            var implementation = GetObject(exportedType.Implementation, NotFoundBehavior.ReturnResolutionFailure);
             if (implementation is ModuleDesc)
             {
                 var module = (ModuleDesc)implementation;
                 string nameSpace = _metadataReader.GetString(exportedType.Namespace);
                 string name = _metadataReader.GetString(exportedType.Name);
-                return module.GetType(nameSpace, name);
+                return module.GetType(nameSpace, name, NotFoundBehavior.ReturnResolutionFailure);
             }
             else
             if (implementation is MetadataType)
@@ -545,12 +604,17 @@ namespace Internal.TypeSystem.Ecma
                 string name = _metadataReader.GetString(exportedType.Name);
                 var nestedType = type.GetNestedType(name);
                 if (nestedType == null)
-                    ThrowHelper.ThrowTypeLoadException(name, this);
+                    return ResolutionFailure.GetTypeLoadResolutionFailure(name, this);
                 return nestedType;
             }
+            else if (implementation is ResolutionFailure)
+            {
+                return implementation;
+            }
             else
             {
-                throw new BadImageFormatException("Unknown metadata token type for exported type");
+                ThrowHelper.ThrowBadImageFormatException();
+                return null;
             }
         }
 
index 9a39fc6..cb3766f 100644 (file)
@@ -14,40 +14,75 @@ namespace Internal.TypeSystem.Ecma
     public struct EcmaSignatureParser
     {
         private TypeSystemContext _tsc;
-        private Func<EntityHandle, TypeDesc> _typeResolver;
+        private Func<EntityHandle, NotFoundBehavior, TypeDesc> _typeResolver;
+        private NotFoundBehavior _notFoundBehavior;
         private EcmaModule _ecmaModule;
         private BlobReader _reader;
+        private ResolutionFailure _resolutionFailure;
 
         private Stack<int> _indexStack;
         private List<EmbeddedSignatureData> _embeddedSignatureDataList;
 
 
-        public EcmaSignatureParser(TypeSystemContext tsc, Func<EntityHandle, TypeDesc> typeResolver, BlobReader reader)
+        public EcmaSignatureParser(TypeSystemContext tsc, Func<EntityHandle, NotFoundBehavior, TypeDesc> typeResolver, BlobReader reader, NotFoundBehavior notFoundBehavior)
         {
+            _notFoundBehavior = notFoundBehavior;
             _ecmaModule = null;
             _tsc = tsc;
             _typeResolver = typeResolver;
             _reader = reader;
             _indexStack = null;
             _embeddedSignatureDataList = null;
+            _resolutionFailure = null;
         }
 
-        public EcmaSignatureParser(EcmaModule ecmaModule, BlobReader reader)
+        public EcmaSignatureParser(EcmaModule ecmaModule, BlobReader reader, NotFoundBehavior notFoundBehavior)
         {
+            _notFoundBehavior = notFoundBehavior;
             _ecmaModule = ecmaModule;
             _tsc = ecmaModule.Context;
             _typeResolver = null;
             _reader = reader;
             _indexStack = null;
             _embeddedSignatureDataList = null;
+            _resolutionFailure = null;
         }
 
+        void SetResolutionFailure(ResolutionFailure failure)
+        {
+            if (_resolutionFailure == null)
+                _resolutionFailure = failure;
+        }
+
+        public ResolutionFailure ResolutionFailure => _resolutionFailure;
+
         private TypeDesc ResolveHandle(EntityHandle handle)
         {
+            object resolvedValue;
             if (_ecmaModule != null)
-                return _ecmaModule.GetType(handle);
+            {
+                resolvedValue = _ecmaModule.GetObject(handle, _notFoundBehavior);
+            }
             else
-                return _typeResolver(handle);
+            {
+                resolvedValue = _typeResolver(handle, _notFoundBehavior);
+            }
+
+            if (resolvedValue == null)
+                return null;
+            if (resolvedValue is ResolutionFailure failure)
+            {
+                SetResolutionFailure(failure);
+                return null;
+            }
+            if (resolvedValue is TypeDesc type)
+            {
+                return type;
+            }
+            else
+            {
+                throw new BadImageFormatException("Type expected");
+            }
         }
 
         private TypeDesc GetWellKnownType(WellKnownType wellKnownType)
@@ -57,7 +92,6 @@ namespace Internal.TypeSystem.Ecma
 
         private TypeDesc ParseType(SignatureTypeCode typeCode)
         {
-
             if (_indexStack != null)
             {
                 int was = _indexStack.Pop();
@@ -114,7 +148,12 @@ namespace Internal.TypeSystem.Ecma
                 case SignatureTypeCode.TypeHandle:
                     return ResolveHandle(_reader.ReadTypeHandle());
                 case SignatureTypeCode.SZArray:
-                    return _tsc.GetArrayType(ParseType());
+                    {
+                        var elementType = ParseType();
+                        if (elementType == null)
+                            return null;
+                        return _tsc.GetArrayType(elementType);
+                    }
                 case SignatureTypeCode.Array:
                     {
                         var elementType = ParseType();
@@ -128,12 +167,27 @@ namespace Internal.TypeSystem.Ecma
                         for (int j = 0; j < lowerBoundsCount; j++)
                             _reader.ReadCompressedInteger();
 
-                        return _tsc.GetArrayType(elementType, rank);
+                        if (elementType != null)
+                            return _tsc.GetArrayType(elementType, rank);
+                        else
+                            return null;
                     }
                 case SignatureTypeCode.ByReference:
-                    return ParseType().MakeByRefType();
+                    {
+                        TypeDesc byRefedType = ParseType();
+                        if (byRefedType != null)
+                            return byRefedType.MakeByRefType();
+                        else
+                            return null;
+                    }
                 case SignatureTypeCode.Pointer:
-                    return _tsc.GetPointerType(ParseType());
+                    {
+                        TypeDesc pointedAtType = ParseType();
+                        if (pointedAtType != null)
+                            return _tsc.GetPointerType(pointedAtType);
+                        else
+                            return null;
+                    }
                 case SignatureTypeCode.GenericTypeParameter:
                     return _tsc.GetSignatureVariable(_reader.ReadCompressedInteger(), false);
                 case SignatureTypeCode.GenericMethodParameter:
@@ -141,19 +195,36 @@ namespace Internal.TypeSystem.Ecma
                 case SignatureTypeCode.GenericTypeInstance:
                     {
                         TypeDesc typeDef = ParseType();
-                        MetadataType metadataTypeDef = typeDef as MetadataType;
-                        if (metadataTypeDef == null)
-                            throw new BadImageFormatException();
+                        MetadataType metadataTypeDef = null;
+
+                        if (typeDef != null)
+                        {
+                            metadataTypeDef = typeDef as MetadataType;
+                            if (metadataTypeDef == null)
+                                throw new BadImageFormatException();
+                        }
 
                         TypeDesc[] instance = new TypeDesc[_reader.ReadCompressedInteger()];
                         for (int i = 0; i < instance.Length; i++)
+                        {
                             instance[i] = ParseType();
-                        return _tsc.GetInstantiatedType(metadataTypeDef, new Instantiation(instance));
+                            if (instance[i] == null)
+                                metadataTypeDef = null;
+                        }
+
+                        if (metadataTypeDef != null)
+                            return _tsc.GetInstantiatedType(metadataTypeDef, new Instantiation(instance));
+                        else
+                            return null;
                     }
                 case SignatureTypeCode.TypedReference:
                     return GetWellKnownType(WellKnownType.TypedReference);
                 case SignatureTypeCode.FunctionPointer:
-                    return _tsc.GetFunctionPointerType(ParseMethodSignatureInternal(skipEmbeddedSignatureData: true));
+                    MethodSignature sig = ParseMethodSignatureInternal(skipEmbeddedSignatureData: true);
+                    if (sig != null)
+                        return _tsc.GetFunctionPointerType(sig);
+                    else
+                        return null;
                 default:
                     throw new BadImageFormatException();
             }
@@ -320,12 +391,19 @@ namespace Internal.TypeSystem.Ecma
 
             EmbeddedSignatureData[] embeddedSignatureDataArray = (_embeddedSignatureDataList == null || _embeddedSignatureDataList.Count == 0 || skipEmbeddedSignatureData) ? null : _embeddedSignatureDataList.ToArray();
 
-            return new MethodSignature(flags, arity, returnType, parameters, embeddedSignatureDataArray);
+            if (_resolutionFailure == null)
+                return new MethodSignature(flags, arity, returnType, parameters, embeddedSignatureDataArray);
+            else
+                return null;
 
         }
 
         public PropertySignature ParsePropertySignature()
         {
+            // As PropertySignature is a struct, we cannot return null
+            if (_notFoundBehavior != NotFoundBehavior.Throw)
+                throw new ArgumentException();
+
             SignatureHeader header = _reader.ReadSignatureHeader();
             if (header.Kind != SignatureKind.Property)
                 throw new BadImageFormatException();
@@ -392,7 +470,10 @@ namespace Internal.TypeSystem.Ecma
             {
                 locals = Array.Empty<LocalVariableDefinition>();
             }
-            return locals;
+            if (_resolutionFailure == null)
+                return locals;
+            else
+                return null;
         }
 
         public TypeDesc[] ParseMethodSpecSignature()
@@ -410,7 +491,10 @@ namespace Internal.TypeSystem.Ecma
             {
                 arguments[i] = ParseType();
             }
-            return arguments;
+            if (_resolutionFailure == null)
+                return arguments;
+            else
+                return null;
         }
 
         public MarshalAsDescriptor ParseMarshalAsDescriptor()
index e014280..02e5207 100644 (file)
@@ -89,7 +89,7 @@ namespace Internal.IL
                 return Array.Empty<LocalVariableDefinition>();
             BlobReader signatureReader = metadataReader.GetBlobReader(metadataReader.GetStandaloneSignature(localSignature).Signature);
 
-            EcmaSignatureParser parser = new EcmaSignatureParser(_module, signatureReader);
+            EcmaSignatureParser parser = new EcmaSignatureParser(_module, signatureReader, NotFoundBehavior.Throw);
             LocalVariableDefinition[] locals = parser.ParseLocalsSignature();
 
             Interlocked.CompareExchange(ref _locals, locals, null);
@@ -131,13 +131,13 @@ namespace Internal.IL
             return _ilExceptionRegions;
         }
 
-        public override object GetObject(int token)
+        public override object GetObject(int token, NotFoundBehavior notFoundBehavior = NotFoundBehavior.Throw)
         {
             // UserStrings cannot be wrapped in EntityHandle
             if ((token & 0xFF000000) == 0x70000000)
                 return _module.GetUserString(MetadataTokens.UserStringHandle(token));
 
-            return _module.GetObject(MetadataTokens.EntityHandle(token));
+            return _module.GetObject(MetadataTokens.EntityHandle(token), notFoundBehavior);
         }
     }
 }
index 0723d40..3c6d4c1 100644 (file)
@@ -22,7 +22,7 @@ namespace Internal.IL
 
         public static MetadataType GetOptionalHelperType(this TypeSystemContext context, string name)
         {
-            MetadataType helperType = context.SystemModule.GetType(HelperTypesNamespace, name, throwIfNotFound: false);
+            MetadataType helperType = context.SystemModule.GetType(HelperTypesNamespace, name, NotFoundBehavior.ReturnNull);
             return helperType;
         }
 
@@ -111,7 +111,7 @@ namespace Internal.IL
         /// </summary>
         public static MetadataType GetKnownType(this ModuleDesc module, string @namespace, string name)
         {
-            MetadataType type = module.GetType(@namespace, name, false);
+            MetadataType type = module.GetType(@namespace, name, NotFoundBehavior.ReturnNull);
             if (type == null)
             {
                 throw new InvalidOperationException(
index 7192e54..9def3ed 100644 (file)
@@ -89,9 +89,9 @@ namespace Internal.IL
             return (clone == null) ? locals : clone;
         }
 
-        public override Object GetObject(int token)
+        public override Object GetObject(int token, NotFoundBehavior notFoundBehavior)
         {
-            Object o = _methodIL.GetObject(token);
+            Object o = _methodIL.GetObject(token, notFoundBehavior);
 
             if (o is MethodDesc)
             {
index 83fecc1..b5eb21f 100644 (file)
@@ -86,7 +86,7 @@ namespace Internal.IL
         /// (typically a <see cref="MethodDesc"/>, <see cref="FieldDesc"/>, <see cref="TypeDesc"/>,
         /// or <see cref="MethodSignature"/>).
         /// </summary>
-        public abstract Object GetObject(int token);
+        public abstract Object GetObject(int token, NotFoundBehavior notFoundBehavior = NotFoundBehavior.ReturnNull);
 
         /// <summary>
         /// Gets a list of exception regions this method body defines.
index 67f79ad..aa20328 100644 (file)
@@ -620,7 +620,7 @@ namespace Internal.IL.Stubs
         {
             return _locals;
         }
-        public override Object GetObject(int token)
+        public override Object GetObject(int token, NotFoundBehavior notFoundBehavior)
         {
             return _tokens[(token & 0xFFFFFF) - 1];
         }
index c68e48b..35b992f 100644 (file)
     <Compile Include="$(ToolsCommonPath)TypeSystem\Common\ModuleDesc.cs">
       <Link>TypeSystem\Common\ModuleDesc.cs</Link>
     </Compile>
+    <Compile Include="$(ToolsCommonPath)TypeSystem\Common\NotFoundBehavior.cs">
+      <Link>TypeSystem\Common\NotFoundBehavior.cs</Link>
+    </Compile>
+    <Compile Include="$(ToolsCommonPath)TypeSystem\Common\ResolutionFailure.cs">
+      <Link>TypeSystem\Common\ResolutionFailure.cs</Link>
+    </Compile>
     <Compile Include="$(ToolsCommonPath)TypeSystem\Common\TypeSystemEntity.cs">
       <Link>TypeSystem\Common\TypeSystemEntity.cs</Link>
     </Compile>
index 3a08440..019f669 100644 (file)
@@ -35,7 +35,7 @@ namespace ILVerify
             int count = 0;
             for (int i = 0; i < s_genericRuntimeInterfacesNames.Length; ++i)
             {
-                MetadataType runtimeInterface =_systemModule.GetType("System.Collections.Generic", s_genericRuntimeInterfacesNames[i], false);
+                MetadataType runtimeInterface =_systemModule.GetType("System.Collections.Generic", s_genericRuntimeInterfacesNames[i], NotFoundBehavior.ReturnNull);
                 if (runtimeInterface != null)
                     _genericRuntimeInterfaces[count++] = runtimeInterface;
             };
index b26d9ab..8b419d4 100644 (file)
@@ -106,7 +106,7 @@ namespace ILCompiler.IBC
                         case CorTokenType.mdtMethodDef:
                         case CorTokenType.mdtMemberRef:
                         case CorTokenType.mdtMethodSpec:
-                            object metadataObject = ecmaModule.GetObject(System.Reflection.Metadata.Ecma335.MetadataTokens.EntityHandle((int)entry.Token));
+                            object metadataObject = ecmaModule.GetObject(System.Reflection.Metadata.Ecma335.MetadataTokens.EntityHandle((int)entry.Token), NotFoundBehavior.ReturnNull);
                             if (metadataObject is MethodDesc)
                             {
                                 associatedMethod = (MethodDesc)metadataObject;
@@ -346,7 +346,7 @@ namespace ILCompiler.IBC
                         if (!(m is EcmaModule))
                             continue;
 
-                        foundType = (EcmaType)m.GetType(typeNamespace, typeName, throwIfNotFound: false);
+                        foundType = (EcmaType)m.GetType(typeNamespace, typeName, NotFoundBehavior.ReturnNull);
                         if (foundType != null)
                         {
                             externalModule = foundType.EcmaModule;
@@ -356,7 +356,7 @@ namespace ILCompiler.IBC
                 }
                 else
                 {
-                    foundType = (EcmaType)externalModule.GetType(typeNamespace, typeName, throwIfNotFound: false);
+                    foundType = (EcmaType)externalModule.GetType(typeNamespace, typeName, NotFoundBehavior.ReturnNull);
                 }
 
                 if (foundType == null)
@@ -451,7 +451,7 @@ namespace ILCompiler.IBC
             {
                 if (EcmaModule.MetadataReader.GetTableRowCount(TableIndex.AssemblyRef) < index)
                     return null;
-                return EcmaModule.GetObject(MetadataTokens.EntityHandle(((int)CorTokenType.mdtAssemblyRef) | index)) as EcmaModule;
+                return EcmaModule.GetObject(MetadataTokens.EntityHandle(((int)CorTokenType.mdtAssemblyRef) | index), NotFoundBehavior.ReturnNull) as EcmaModule;
             }
         }
 
index 987300d..22e54a8 100644 (file)
@@ -41,7 +41,12 @@ namespace ILCompiler.IBC
                         // token type is 0, therefore it can't be a type
                         return new TypeSystemEntityOrUnknown((int)token);
                     }
-                    return new TypeSystemEntityOrUnknown((TypeDesc)_ilBody.GetObject((int)token));
+                    TypeDesc foundType = _ilBody.GetObject((int)token, NotFoundBehavior.ReturnNull) as TypeDesc;
+                    if (foundType == null)
+                    {
+                        return new TypeSystemEntityOrUnknown((int)token & 0x00FFFFFF);
+                    }
+                    return new TypeSystemEntityOrUnknown(foundType);
                 }
                 catch
                 {
@@ -265,7 +270,9 @@ namespace ILCompiler.IBC
                                 metadataObject = null;
                                 try
                                 {
-                                    metadataObject = ilBody.GetObject(token);
+                                    metadataObject = ilBody.GetObject(token, NotFoundBehavior.ReturnNull);
+                                    if (metadataObject == null)
+                                        metadataObject = metadataNotResolvable;
                                 }
                                 catch (TypeSystemException)
                                 {
@@ -509,7 +516,7 @@ namespace ILCompiler.IBC
                     throw new NotImplementedException();
                 }
 
-                public override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
+                public override MetadataType GetType(string nameSpace, string name, NotFoundBehavior notFoundBehavior)
                 {
                     TypeSystemContext context = Context;
 
@@ -519,9 +526,14 @@ namespace ILCompiler.IBC
                         return Context.UniversalCanonType;
                     else
                     {
-                        if (throwIfNotFound)
+                        if (notFoundBehavior != NotFoundBehavior.ReturnNull)
                         {
-                            throw new TypeLoadException($"{nameSpace}.{name}");
+                            var failure = ResolutionFailure.GetTypeLoadResolutionFailure(nameSpace, name, "System.Private.Canon");
+                            ModuleDesc.GetTypeResolutionFailure = failure;
+                            if (notFoundBehavior == NotFoundBehavior.Throw)
+                                failure.Throw();
+
+                            return null;
                         }
                         return null;
                     }
index c8e83d9..580438d 100644 (file)
     <Compile Include="..\..\Common\TypeSystem\Common\ModuleDesc.cs">
       <Link>TypeSystem\Common\ModuleDesc.cs</Link>
     </Compile>
+    <Compile Include="..\..\Common\TypeSystem\Common\NotFoundBehavior.cs">
+      <Link>TypeSystem\Common\NotFoundBehavior.cs</Link>
+    </Compile>
+    <Compile Include="..\..\Common\TypeSystem\Common\ResolutionFailure.cs">
+      <Link>TypeSystem\Common\ResolutionFailure.cs</Link>
+    </Compile>
     <Compile Include="..\..\Common\TypeSystem\Common\TypeSystemEntity.cs">
       <Link>TypeSystem\Common\TypeSystemEntity.cs</Link>
     </Compile>
index 0bc5292..a640425 100644 (file)
@@ -97,7 +97,11 @@ namespace Microsoft.Diagnostics.Tools.Pgo
         MethodDesc IR2RSignatureTypeProvider<TypeDesc, MethodDesc, R2RSigProviderContext>.GetMethodFromMemberRef(MetadataReader reader, MemberReferenceHandle handle, TypeDesc owningTypeOverride)
         {
             var ecmaModule = (EcmaModule)_tsc.GetModuleForSimpleName(reader.GetString(reader.GetAssemblyDefinition().Name));
-            var method = (MethodDesc)ecmaModule.GetObject(handle);
+            var method = (MethodDesc)ecmaModule.GetObject(handle, NotFoundBehavior.ReturnNull);
+            if (method == null)
+            {
+                return null;
+            }
             if (owningTypeOverride != null)
             {
                 return _tsc.GetMethodForInstantiatedType(method.GetTypicalMethodDefinition(), (InstantiatedType)owningTypeOverride);
@@ -108,7 +112,11 @@ namespace Microsoft.Diagnostics.Tools.Pgo
         MethodDesc IR2RSignatureTypeProvider<TypeDesc, MethodDesc, R2RSigProviderContext>.GetMethodFromMethodDef(MetadataReader reader, MethodDefinitionHandle handle, TypeDesc owningTypeOverride)
         {
             var ecmaModule = (EcmaModule)_tsc.GetModuleForSimpleName(reader.GetString(reader.GetAssemblyDefinition().Name));
-            var method = (MethodDesc)ecmaModule.GetObject(handle);
+            var method = (MethodDesc)ecmaModule.GetObject(handle, NotFoundBehavior.ReturnNull);
+            if (method == null)
+            {
+                return null;
+            }
             if (owningTypeOverride != null)
             {
                 return _tsc.GetMethodForInstantiatedType(method.GetTypicalMethodDefinition(), (InstantiatedType)owningTypeOverride);
@@ -214,19 +222,19 @@ namespace Microsoft.Diagnostics.Tools.Pgo
         TypeDesc ISimpleTypeProvider<TypeDesc>.GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
         {
             var ecmaModule = (EcmaModule)_tsc.GetModuleForSimpleName(reader.GetString(reader.GetAssemblyDefinition().Name));
-            return (TypeDesc)ecmaModule.GetObject(handle);
+            return (TypeDesc)ecmaModule.GetObject(handle, NotFoundBehavior.ReturnNull);
         }
 
         TypeDesc ISimpleTypeProvider<TypeDesc>.GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
         {
             var ecmaModule = (EcmaModule)_tsc.GetModuleForSimpleName(reader.GetString(reader.GetAssemblyDefinition().Name));
-            return (TypeDesc)ecmaModule.GetObject(handle);
+            return (TypeDesc)ecmaModule.GetObject(handle, NotFoundBehavior.ReturnNull);
         }
 
         TypeDesc ISignatureTypeProvider<TypeDesc, R2RSigProviderContext>.GetTypeFromSpecification(MetadataReader reader, R2RSigProviderContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
         {
             var ecmaModule = (EcmaModule)_tsc.GetModuleForSimpleName(reader.GetString(reader.GetAssemblyDefinition().Name));
-            return (TypeDesc)ecmaModule.GetObject(handle);
+            return (TypeDesc)ecmaModule.GetObject(handle, NotFoundBehavior.ReturnNull);
         }
     }
 }
index 1cb1138..bb32521 100644 (file)
@@ -3,6 +3,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Linq;
 using System.Reflection.Metadata;
 using System.Text;
@@ -120,7 +121,7 @@ namespace Microsoft.Diagnostics.Tools.Pgo.TypeRefTypeSystem
             {
                 TypeRefSignatureParserProvider parserHelper = new TypeRefSignatureParserProvider(this, peInfo.handleLookup);
 
-                Func<EntityHandle, TypeDesc> resolverFunc = ResolveTypeRefForPeInfo;
+                Func<EntityHandle, NotFoundBehavior, TypeDesc> resolverFunc = ResolveTypeRefForPeInfo;
                 int memberRefRowCount = peInfo.reader.GetTableRowCount(TableIndex.MemberRef);
                 for (int row = 1; row <= memberRefRowCount; row++)
                 {
@@ -142,7 +143,7 @@ namespace Microsoft.Diagnostics.Tools.Pgo.TypeRefTypeSystem
                         continue;
                     }
 
-                    EcmaSignatureParser ecmaSigParse = new EcmaSignatureParser(this, ResolveTypeRefForPeInfo, peInfo.reader.GetBlobReader(memberRef.Signature));
+                    EcmaSignatureParser ecmaSigParse = new EcmaSignatureParser(this, ResolveTypeRefForPeInfo, peInfo.reader.GetBlobReader(memberRef.Signature), NotFoundBehavior.ReturnNull);
                     string name = peInfo.reader.GetString(memberRef.Name);
 
                     if (memberRef.GetKind() == MemberReferenceKind.Method)
@@ -157,8 +158,9 @@ namespace Microsoft.Diagnostics.Tools.Pgo.TypeRefTypeSystem
                     }
                 }
 
-                TypeDesc ResolveTypeRefForPeInfo(EntityHandle handle)
+                TypeDesc ResolveTypeRefForPeInfo(EntityHandle handle, NotFoundBehavior notFoundBehavior)
                 {
+                    Debug.Assert(notFoundBehavior == NotFoundBehavior.ReturnNull);
                     TypeRefTypeSystemType type = null;
                     if (handle.Kind == HandleKind.TypeReference)
                     {
index 4552938..d057112 100644 (file)
@@ -71,11 +71,16 @@ namespace Microsoft.Diagnostics.Tools.Pgo.TypeRefTypeSystem
             return type;
         }
 
-        public override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
+        public override MetadataType GetType(string nameSpace, string name, NotFoundBehavior notFoundBehavior)
         {
             MetadataType type = GetTypeInternal(nameSpace, name);
-            if ((type == null) && throwIfNotFound)
-                ThrowHelper.ThrowTypeLoadException(nameSpace, name, this);
+            if ((type == null) && notFoundBehavior != NotFoundBehavior.ReturnNull)
+            {
+                ResolutionFailure failure = ResolutionFailure.GetTypeLoadResolutionFailure(nameSpace, name, this);
+                ModuleDesc.GetTypeResolutionFailure = failure;
+                if (notFoundBehavior == NotFoundBehavior.Throw)
+                    failure.Throw();
+            }
             return type;
         }
     }