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