protected override void ComputeMetadata(out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            metadataBlob   = _metadataBlob;
            typeMappings   = loadedMetadata.AllTypeMappings;
            methodMappings = loadedMetadata.MethodMappings;
            fieldMappings  = loadedMetadata.FieldMappings;
        }
示例#2
0
        protected override void ComputeMetadata(out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            metadataBlob = _metadataBlob;

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            // Generate type definition mappings
            foreach (var definition in _typeDefinitionsGenerated)
            {
                int token;
                if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token))
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, token));
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                if (method.IsCanonicalMethod(CanonicalFormKind.Specific))
                {
                    // Canonical methods are not interesting.
                    continue;
                }

                int token;
                if (loadedMetadata.MethodMappings.TryGetValue(method.GetTypicalMethodDefinition(), out token))
                {
                    methodMappings.Add(new MetadataMapping <MethodDesc>(method, token));
                }
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    int token;
                    if (loadedMetadata.FieldMappings.TryGetValue(field.GetTypicalFieldDefinition(), out token))
                    {
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, token));
                    }
                }
            }
        }
        void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            // Add all non-generic reflectable methods as roots.
            // Virtual methods need special handling (e.g. with dependency tracking) since they can be abstract.
            foreach (var method in loadedMetadata.MethodMappings.Keys)
            {
                if (method.HasInstantiation || method.OwningType.HasInstantiation)
                {
                    continue;
                }

                if (method.IsVirtual)
                {
                    rootProvider.RootVirtualMethodForReflection(method, "Reflection root");
                }
                else
                {
                    rootProvider.AddCompilationRoot(method, "Reflection root");
                }
            }

            // Root all the generic type instantiations from the pre-computed metadata
            foreach (var type in loadedMetadata.RequiredGenericTypes)
            {
                rootProvider.AddCompilationRoot(type, "Required instantiation");
            }

            // Root all the generic methods (either non-generic methods on generic types, or generic methods) from
            // the pre-computed metadata.
            // Virtual methods need special handling (e.g. with dependency tracking) since they can be abstract.
            foreach (var method in loadedMetadata.RequiredGenericMethods)
            {
                if (method.IsVirtual)
                {
                    rootProvider.RootVirtualMethodForReflection(method, "Required instantiation");
                }
                else
                {
                    rootProvider.AddCompilationRoot(method, "Required instantiation");
                }
            }

            // TODO: required generic fields. Root containing type, and add field to list in ComputeMetadata()
        }
        protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            metadataBlob = _metadataBlob;

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            Dictionary <MethodDesc, MethodDesc> canonicalToSpecificMethods = new Dictionary <MethodDesc, MethodDesc>();

            // The handling of generic methods which are implemented by canonical code is interesting, the invoke map
            // needs to have a specific instantiation for each canonical bit of code.
            foreach (GenericDictionaryNode dictionaryNode in GetCompiledGenericDictionaries())
            {
                MethodGenericDictionaryNode methodDictionary = dictionaryNode as MethodGenericDictionaryNode;
                if (methodDictionary == null)
                {
                    continue;
                }

                MethodDesc method = methodDictionary.OwningMethod;
                Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any));

                MethodDesc canonicalMethod = method.GetCanonMethodTarget(CanonicalFormKind.Specific);

                if (canonicalToSpecificMethods.ContainsKey(canonicalMethod))
                {
                    // We only need to record 1 specific to canonical method mapping
                    continue;
                }

                canonicalToSpecificMethods.Add(canonicalMethod, method);
            }

            // Generate type definition mappings
            foreach (var definition in _typeDefinitionsGenerated)
            {
                int token;
                if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token))
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, token));
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                int token;
                if (loadedMetadata.MethodMappings.TryGetValue(method.GetTypicalMethodDefinition(), out token))
                {
                    MethodDesc invokeMapMethod = method;
                    if (method.HasInstantiation && method.IsCanonicalMethod(CanonicalFormKind.Specific))
                    {
                        Debug.Assert(canonicalToSpecificMethods.ContainsKey(method));

                        invokeMapMethod = canonicalToSpecificMethods[method];
                    }

                    // Non-generic instance canonical methods on generic structures are only available in the invoke map
                    // if the unboxing stub entrypoint is marked already (which will mean that the unboxing stub
                    // has been compiled, On ProjectN abi, this may will not be triggered by the CodeBasedDependencyAlgorithm.
                    // See the ProjectN abi specific code in there.
                    if (!method.HasInstantiation && method.OwningType.IsValueType && method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any) && !method.Signature.IsStatic)
                    {
                        if (!factory.MethodEntrypoint(method, true).Marked)
                        {
                            continue;
                        }
                    }

                    methodMappings.Add(new MetadataMapping <MethodDesc>(invokeMapMethod, token));
                }
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    int token;
                    if (loadedMetadata.FieldMappings.TryGetValue(field.GetTypicalFieldDefinition(), out token))
                    {
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, token));
                    }
                }
            }
        }
        private MetadataLoadedInfo LoadMetadata()
        {
            HashSet <ModuleDesc> metadataModules          = new HashSet <ModuleDesc>();
            MetadataType         typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);

            MethodDesc fullMetadataMethod = typeWithMetadataMappings.GetMethod("Metadata", null);
            MethodDesc weakMetadataMethod = typeWithMetadataMappings.GetMethod("WeakMetadata", null);

            ILProvider ilProvider = new ILProvider(null);

            MetadataLoadedInfo result = new MetadataLoadedInfo();

            if (fullMetadataMethod != null)
            {
                MethodIL fullMethodIL = ilProvider.GetMethodIL(fullMetadataMethod);
                ReadMetadataMethod(fullMethodIL, ref result.AllTypeMappings, ref result.MethodMappings, ref result.FieldMappings, ref metadataModules);
                foreach (var mapping in result.AllTypeMappings)
                {
                    result.TypesWithStrongMetadataMappings.Add(mapping.Key);
                }
            }

            if (weakMetadataMethod != null)
            {
                MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
                Dictionary <MethodDesc, int> weakMethodMappings = new Dictionary <MethodDesc, int>();
                Dictionary <FieldDesc, int>  weakFieldMappings  = new Dictionary <FieldDesc, int>();
                ReadMetadataMethod(weakMethodIL, ref result.AllTypeMappings, ref weakMethodMappings, ref weakFieldMappings, ref metadataModules);
                if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
                {
                    // the format does not permit weak field/method mappings
                    throw new BadImageFormatException();
                }
            }

            result.MetadataModules = ImmutableArray.CreateRange(metadataModules);

            ImmutableArray <ModuleDesc> .Builder externalMetadataModulesBuilder = ImmutableArray.CreateBuilder <ModuleDesc>();
            ImmutableArray <ModuleDesc> .Builder localMetadataModulesBuilder    = ImmutableArray.CreateBuilder <ModuleDesc>();
            foreach (ModuleDesc module in result.MetadataModules)
            {
                if (!_compilationModules.Contains(module))
                {
                    externalMetadataModulesBuilder.Add(module);
                }
                else
                {
                    localMetadataModulesBuilder.Add(module);
                }
            }
            result.ExternalMetadataModules = externalMetadataModulesBuilder.ToImmutable();
            result.LocalMetadataModules    = localMetadataModulesBuilder.ToImmutable();

            // TODO! Replace with something more complete that capture the generic instantiations that the pre-analysis
            // indicates should have been present
            foreach (var pair in result.MethodMappings)
            {
                MethodDesc reflectableMethod = pair.Key;

                if (reflectableMethod.HasInstantiation)
                {
                    continue;
                }

                if (reflectableMethod.OwningType.HasInstantiation)
                {
                    continue;
                }

                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod, out typicalDynamicInvokeStub))
                {
                    continue;
                }

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub.GetCanonMethodTarget(CanonicalFormKind.Specific));
            }

            return(result);
        }
        protected override void ComputeMetadata(NodeFactory factory,
                                                out byte[] metadataBlob,
                                                out List <MetadataMapping <MetadataType> > typeMappings,
                                                out List <MetadataMapping <MethodDesc> > methodMappings,
                                                out List <MetadataMapping <FieldDesc> > fieldMappings,
                                                out List <MetadataMapping <MethodDesc> > stackTraceMapping)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            metadataBlob = _metadataBlob;

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            Dictionary <MethodDesc, MethodDesc> canonicalToSpecificMethods = new Dictionary <MethodDesc, MethodDesc>();

            HashSet <FieldDesc>  canonicalFieldsAddedToMap  = new HashSet <FieldDesc>();
            HashSet <MethodDesc> canonicalMethodsAddedToMap = new HashSet <MethodDesc>();

            // The handling of generic methods which are implemented by canonical code is interesting, the invoke map
            // needs to have a specific instantiation for each canonical bit of code.
            foreach (GenericDictionaryNode dictionaryNode in GetCompiledGenericDictionaries())
            {
                MethodGenericDictionaryNode methodDictionary = dictionaryNode as MethodGenericDictionaryNode;
                if (methodDictionary == null)
                {
                    continue;
                }

                MethodDesc method = methodDictionary.OwningMethod;
                Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any));

                MethodDesc canonicalMethod = method.GetCanonMethodTarget(CanonicalFormKind.Specific);

                if (canonicalToSpecificMethods.ContainsKey(canonicalMethod))
                {
                    // We only need to record 1 specific to canonical method mapping
                    continue;
                }

                canonicalToSpecificMethods.Add(canonicalMethod, method);
            }

            // Generate type definition mappings
            foreach (var type in GetTypesWithEETypes())
            {
                MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
                if (definition == null)
                {
                    continue;
                }

                int token;
                if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token))
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, token));
                }
            }

            // Mappings for all compiled methods
            foreach (var method in GetCompiledMethods())
            {
                AddMethodMapping(factory, method, canonicalMethodsAddedToMap, canonicalToSpecificMethods, methodMappings);
            }

            // Mappings for reflectable abstract non-generic methods (methods with compiled bodies are handled above)
            foreach (var method in loadedMetadata.MethodMappings.Keys)
            {
                if (!method.IsAbstract)
                {
                    continue;
                }

                if (method.HasInstantiation || method.OwningType.HasInstantiation)
                {
                    continue;
                }

                AddMethodMapping(factory, method, canonicalMethodsAddedToMap, canonicalToSpecificMethods, methodMappings);
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    AddFieldMapping(field, canonicalFieldsAddedToMap, fieldMappings);
                }
            }

            stackTraceMapping = GenerateStackTraceMetadata(factory);
        }
        void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            // Add all non-generic reflectable types as roots.
            foreach (var type in loadedMetadata.TypesWithStrongMetadataMappings)
            {
                rootProvider.AddCompilationRoot(type, "Required non-generic type");
            }

            // Add all non-generic reflectable methods as roots.
            // Virtual methods need special handling (e.g. with dependency tracking) since they can be abstract.
            foreach (var method in loadedMetadata.MethodMappings.Keys)
            {
                if (method.HasInstantiation || method.OwningType.HasInstantiation)
                {
                    continue;
                }

                if (!IsMethodSupportedInPrecomputedReflection(method))
                {
                    continue;
                }

                if (method.IsVirtual)
                {
                    rootProvider.RootVirtualMethodForReflection(method, "Reflection root");
                }
                else
                {
                    if (method.IsConstructor)
                    {
                        rootProvider.AddCompilationRoot(method.OwningType, "Type for method reflection root");
                    }

                    rootProvider.AddCompilationRoot(method, "Reflection root");
                }
            }

            // Root all the generic type instantiations from the pre-computed metadata
            foreach (var type in loadedMetadata.RequiredGenericTypes)
            {
                rootProvider.AddCompilationRoot(type, "Required generic type");
            }

            // Root all the generic methods (either non-generic methods on generic types, or generic methods) from
            // the pre-computed metadata.
            // Virtual methods need special handling (e.g. with dependency tracking) since they can be abstract.
            foreach (var method in loadedMetadata.RequiredGenericMethods)
            {
                if (!IsMethodSupportedInPrecomputedReflection(method))
                {
                    continue;
                }

                if (method.IsVirtual)
                {
                    rootProvider.RootVirtualMethodForReflection(method, "Required generic method");
                }

                if (!method.IsAbstract)
                {
                    if (method.IsConstructor)
                    {
                        rootProvider.AddCompilationRoot(method.OwningType, "Type for method required generic method");
                    }

                    rootProvider.AddCompilationRoot(method, "Required generic method");
                }
            }

            foreach (var field in loadedMetadata.RequiredGenericFields)
            {
                rootProvider.AddCompilationRoot(field.OwningType, "Required generic field's owning type");
                if (field.IsThreadStatic)
                {
                    rootProvider.RootThreadStaticBaseForType(field.OwningType, "Required generic field");
                }
                else if (field.IsStatic)
                {
                    if (field.HasGCStaticBase)
                    {
                        rootProvider.RootGCStaticBaseForType(field.OwningType, "Required generic field");
                    }
                    else
                    {
                        rootProvider.RootNonGCStaticBaseForType(field.OwningType, "Required generic field");
                    }
                }
            }

            foreach (var type in loadedMetadata.RequiredTemplateTypes)
            {
                Debug.Assert(type.IsCanonicalSubtype(CanonicalFormKind.Any));
                rootProvider.AddCompilationRoot(type, "Compiler determined template");
            }

            foreach (var method in loadedMetadata.RequiredTemplateMethods)
            {
                Debug.Assert(method.IsCanonicalMethod(CanonicalFormKind.Any));
                if (method.IsVirtual)
                {
                    rootProvider.RootVirtualMethodForReflection(method, "Compiler determined template");
                }

                if (!method.IsAbstract)
                {
                    if (method.IsConstructor)
                    {
                        rootProvider.AddCompilationRoot(method.OwningType, "Type for method compiler determined template method");
                    }

                    rootProvider.AddCompilationRoot(method, "Compiler determined template");
                }
            }
        }
        private MetadataLoadedInfo LoadMetadata()
        {
            HashSet <ModuleDesc> metadataModules          = new HashSet <ModuleDesc>();
            MetadataType         typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);

            MethodDesc fullMetadataMethod           = typeWithMetadataMappings.GetMethod("Metadata", null);
            MethodDesc weakMetadataMethod           = typeWithMetadataMappings.GetMethod("WeakMetadata", null);
            MethodDesc requiredGenericTypesMethod   = typeWithMetadataMappings.GetMethod("RequiredGenericTypes", null);
            MethodDesc requiredGenericMethodsMethod = typeWithMetadataMappings.GetMethod("RequiredGenericMethods", null);
            MethodDesc requiredGenericFieldsMethod  = typeWithMetadataMappings.GetMethod("RequiredGenericFields", null);
            MethodDesc requiredTemplatesMethod      = typeWithMetadataMappings.GetMethod("CompilerDeterminedInstantiations", null);

            ILProvider ilProvider = new ILProvider(null);

            MetadataLoadedInfo result = new MetadataLoadedInfo();

            if (fullMetadataMethod != null)
            {
                MethodIL fullMethodIL = ilProvider.GetMethodIL(fullMetadataMethod);
                ReadMetadataMethod(fullMethodIL, result.AllTypeMappings, result.MethodMappings, result.FieldMappings, metadataModules);
                foreach (var mapping in result.AllTypeMappings)
                {
                    result.TypesWithStrongMetadataMappings.Add(mapping.Key);
                }
            }

            if (weakMetadataMethod != null)
            {
                MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
                Dictionary <MethodDesc, int> weakMethodMappings = new Dictionary <MethodDesc, int>();
                Dictionary <FieldDesc, int>  weakFieldMappings  = new Dictionary <FieldDesc, int>();
                ReadMetadataMethod(weakMethodIL, result.AllTypeMappings, weakMethodMappings, weakFieldMappings, metadataModules);
                if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
                {
                    // the format does not permit weak field/method mappings
                    throw new BadImageFormatException();
                }
            }

            if (requiredGenericTypesMethod != null)
            {
                foreach (var type in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericTypesMethod)))
                {
                    Debug.Assert(type is DefType);
                    result.RequiredGenericTypes.Add((TypeDesc)type);
                }
            }

            if (requiredGenericMethodsMethod != null)
            {
                foreach (var method in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericMethodsMethod)))
                {
                    result.RequiredGenericMethods.Add((MethodDesc)method);
                }
            }

            if (requiredGenericFieldsMethod != null)
            {
                foreach (var field in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericFieldsMethod)))
                {
                    result.RequiredGenericFields.Add((FieldDesc)field);
                }
            }

            if (requiredTemplatesMethod != null)
            {
                ReadRequiredTemplates(ilProvider.GetMethodIL(requiredTemplatesMethod),
                                      result.RequiredTemplateTypes,
                                      result.RequiredTemplateMethods,
                                      result.RequiredTemplateFields);
            }

            result.MetadataModules = ImmutableArray.CreateRange(metadataModules);

            ImmutableArray <ModuleDesc> .Builder externalMetadataModulesBuilder = ImmutableArray.CreateBuilder <ModuleDesc>();
            ImmutableArray <ModuleDesc> .Builder localMetadataModulesBuilder    = ImmutableArray.CreateBuilder <ModuleDesc>();
            foreach (ModuleDesc module in result.MetadataModules)
            {
                if (!_compilationModules.Contains(module))
                {
                    externalMetadataModulesBuilder.Add(module);
                }
                else
                {
                    localMetadataModulesBuilder.Add(module);
                }
            }
            result.ExternalMetadataModules = externalMetadataModulesBuilder.ToImmutable();
            result.LocalMetadataModules    = localMetadataModulesBuilder.ToImmutable();

            foreach (var pair in result.MethodMappings)
            {
                MethodDesc reflectableMethod = pair.Key;

                if (reflectableMethod.HasInstantiation)
                {
                    continue;
                }

                if (reflectableMethod.OwningType.HasInstantiation)
                {
                    continue;
                }

                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod, out typicalDynamicInvokeStub))
                {
                    continue;
                }

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateCanonicalDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub);
            }

            foreach (var reflectableMethod in result.RequiredGenericMethods)
            {
                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod.GetTypicalMethodDefinition(), out typicalDynamicInvokeStub))
                {
                    continue;
                }

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateCanonicalDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub);
            }

            return(result);
        }
示例#9
0
        protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings)
        {
            MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;

            metadataBlob = _metadataBlob;

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            Dictionary <MethodDesc, MethodDesc> canonicalToSpecificMethods = new Dictionary <MethodDesc, MethodDesc>();

            // The handling of generic methods which are implemented by canonical code is interesting, the invoke map
            // needs to have a specific instantiation for each canonical bit of code.
            foreach (GenericDictionaryNode dictionaryNode in GetCompiledGenericDictionaries())
            {
                MethodGenericDictionaryNode methodDictionary = dictionaryNode as MethodGenericDictionaryNode;
                if (methodDictionary == null)
                {
                    continue;
                }

                MethodDesc method = methodDictionary.OwningMethod;
                Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any));

                MethodDesc canonicalMethod = method.GetCanonMethodTarget(CanonicalFormKind.Specific);

                if (canonicalToSpecificMethods.ContainsKey(canonicalMethod))
                {
                    // We only need to record 1 specific to canonical method mapping
                    continue;
                }

                canonicalToSpecificMethods.Add(canonicalMethod, method);
            }

            // Generate type definition mappings
            foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
            {
                MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
                if (definition == null)
                {
                    continue;
                }

                int token;
                if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token))
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, token));
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                if (!MethodCanBeInvokedViaReflection(factory, method))
                {
                    continue;
                }

                // If there is a possible canonical method, use that instead of a specific method (folds canonically equivalent methods away)
                if (method.GetCanonMethodTarget(CanonicalFormKind.Specific) != method)
                {
                    continue;
                }

                int token;
                if (loadedMetadata.MethodMappings.TryGetValue(method.GetTypicalMethodDefinition(), out token))
                {
                    MethodDesc invokeMapMethod = GetInvokeMapMethodForMethod(canonicalToSpecificMethods, method);

                    if (invokeMapMethod != null)
                    {
                        methodMappings.Add(new MetadataMapping <MethodDesc>(invokeMapMethod, token));
                    }
                }
                else if (!WillUseMetadataTokenToReferenceMethod(method) &&
                         _compilationModuleGroup.ContainsMethod(method.GetCanonMethodTarget(CanonicalFormKind.Specific)))
                {
                    MethodDesc invokeMapMethod = GetInvokeMapMethodForMethod(canonicalToSpecificMethods, method);

                    // For methods on types that are not in the current module, assume they must be reflectable
                    // and generate a non-metadata backed invoke table entry
                    // TODO, the above computation is overly generous with the set of methods that are placed into the method invoke map
                    // It includes methods which are not reflectable at all.
                    if (invokeMapMethod != null)
                    {
                        methodMappings.Add(new MetadataMapping <MethodDesc>(invokeMapMethod, 0));
                    }
                }
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                if (eetypeGenerated.HasInstantiation)
                {
                    // Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries

                    TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific);
                    if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType))
                    {
                        continue;
                    }
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    int token;
                    if (loadedMetadata.FieldMappings.TryGetValue(field.GetTypicalFieldDefinition(), out token))
                    {
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, token));
                    }
                    else if (!WillUseMetadataTokenToReferenceField(field))
                    {
                        // TODO, the above computation is overly generous with the set of fields that are placed into the field invoke map
                        // It includes fields which are not reflectable at all, and collapses static fields across generics

                        // TODO! enable this. Disabled due to cross module import of statics is not yet implemented
                        // fieldMappings.Add(new MetadataMapping<FieldDesc>(field, 0));
                    }
                }
            }
        }
        private MetadataLoadedInfo LoadMetadata()
        {
            HashSet <ModuleDesc> metadataModules          = new HashSet <ModuleDesc>();
            MetadataType         typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);

            MethodDesc fullMetadataMethod = typeWithMetadataMappings.GetMethod("Metadata", null);
            MethodDesc weakMetadataMethod = typeWithMetadataMappings.GetMethod("WeakMetadata", null);

            ILProvider ilProvider = new ILProvider(null);

            MetadataLoadedInfo result = new MetadataLoadedInfo();

            if (fullMetadataMethod != null)
            {
                MethodIL fullMethodIL = ilProvider.GetMethodIL(fullMetadataMethod);
                ReadMetadataMethod(fullMethodIL, out result.StrongTypeMappings, out result.MethodMappings, out result.FieldMappings, ref metadataModules);
            }

            if (weakMetadataMethod != null)
            {
                MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
                List <MetadataMapping <MethodDesc> > weakMethodMappings = new List <MetadataMapping <MethodDesc> >();
                List <MetadataMapping <FieldDesc> >  weakFieldMappings  = new List <MetadataMapping <FieldDesc> >();
                ReadMetadataMethod(weakMethodIL, out result.AllTypeMappings, out weakMethodMappings, out weakFieldMappings, ref metadataModules);
                if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
                {
                    // the format does not permit weak field/method mappings
                    throw new BadImageFormatException();
                }
            }

#if DEBUG
            // No duplicates are permitted in metadata mappings
            HashSet <TypeSystemEntity> mappingsDuplicateChecker = new HashSet <TypeSystemEntity>();
            foreach (MetadataMapping <MetadataType> mapping in result.AllTypeMappings)
            {
                if (!mappingsDuplicateChecker.Add(mapping.Entity))
                {
                    throw new BadImageFormatException();
                }
            }

            foreach (MetadataMapping <MetadataType> mapping in result.StrongTypeMappings)
            {
                if (!mappingsDuplicateChecker.Add(mapping.Entity))
                {
                    throw new BadImageFormatException();
                }
            }

            foreach (MetadataMapping <FieldDesc> mapping in result.FieldMappings)
            {
                if (!mappingsDuplicateChecker.Add(mapping.Entity))
                {
                    throw new BadImageFormatException();
                }
            }

            foreach (MetadataMapping <MethodDesc> mapping in result.MethodMappings)
            {
                if (!mappingsDuplicateChecker.Add(mapping.Entity))
                {
                    throw new BadImageFormatException();
                }
            }
#endif

            // All type mappings is the combination of strong and weak type mappings.
            result.AllTypeMappings.AddRange(result.StrongTypeMappings);

            result.MetadataModules = ImmutableArray.CreateRange(metadataModules);

            ImmutableArray <ModuleDesc> .Builder externalMetadataModulesBuilder = ImmutableArray.CreateBuilder <ModuleDesc>();
            ImmutableArray <ModuleDesc> .Builder localMetadataModulesBuilder    = ImmutableArray.CreateBuilder <ModuleDesc>();
            foreach (ModuleDesc module in result.MetadataModules)
            {
                if (!_compilationModules.Contains(module))
                {
                    externalMetadataModulesBuilder.Add(module);
                }
                else
                {
                    localMetadataModulesBuilder.Add(module);
                }
            }
            result.ExternalMetadataModules = externalMetadataModulesBuilder.ToImmutable();
            result.LocalMetadataModules    = localMetadataModulesBuilder.ToImmutable();

            return(result);
        }