diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2017-05-23 04:31:42 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-23 04:31:42 +0300 |
commit | dfcefa77c07a33938370f216d96e9b20066766de (patch) | |
tree | 621188f3e729c0a9f631ec789a94c46dded699ad /src | |
parent | 0df43f3f22e5f52bf0f92bd54ab19d2455bcbc84 (diff) | |
parent | 7867539d3123f3312a8100f2f1063c69ac2aae55 (diff) |
Merge pull request #3664 from MichalStrehovsky/mdManagerCreation
Make metadata generation dependency driven
Diffstat (limited to 'src')
16 files changed, 823 insertions, 146 deletions
diff --git a/src/Common/src/TypeSystem/Common/FieldDesc.cs b/src/Common/src/TypeSystem/Common/FieldDesc.cs index cfdc3d12d..be2d81bd5 100644 --- a/src/Common/src/TypeSystem/Common/FieldDesc.cs +++ b/src/Common/src/TypeSystem/Common/FieldDesc.cs @@ -76,6 +76,14 @@ namespace Internal.TypeSystem return this; } + public bool IsTypicalFieldDefinition + { + get + { + return GetTypicalFieldDefinition() == this; + } + } + public virtual FieldDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation) { FieldDesc field = this; diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs index 698d7a46f..838606a9d 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs @@ -23,13 +23,14 @@ namespace ILCompiler protected IEnumerable<ICompilationRootProvider> _compilationRoots = Array.Empty<ICompilationRootProvider>(); protected OptimizationMode _optimizationMode = OptimizationMode.None; protected bool _generateDebugInfo = false; - private string _metadataLogFile = null; + protected MetadataManager _metadataManager; public CompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler nameMangler) { _context = context; _compilationGroup = compilationGroup; _nameMangler = nameMangler; + _metadataManager = new EmptyMetadataManager(compilationGroup, context); } public CompilationBuilder UseLogger(Logger logger) @@ -44,21 +45,21 @@ namespace ILCompiler return this; } - public CompilationBuilder UseCompilationRoots(IEnumerable<ICompilationRootProvider> compilationRoots) + public CompilationBuilder UseMetadataManager(MetadataManager metadataManager) { - _compilationRoots = compilationRoots; + _metadataManager = metadataManager; return this; } - public CompilationBuilder UseOptimizationMode(OptimizationMode mode) + public CompilationBuilder UseCompilationRoots(IEnumerable<ICompilationRootProvider> compilationRoots) { - _optimizationMode = mode; + _compilationRoots = compilationRoots; return this; } - public CompilationBuilder UseMetadataLogFile(string fileName) + public CompilationBuilder UseOptimizationMode(OptimizationMode mode) { - _metadataLogFile = fileName; + _optimizationMode = mode; return this; } @@ -76,11 +77,6 @@ namespace ILCompiler return _dependencyTrackingLevel.CreateDependencyGraph(factory); } - protected MetadataManager CreateMetadataManager() - { - return new CompilerGeneratedMetadataManager(_compilationGroup, _context, _metadataLogFile); - } - public ILScannerBuilder GetILScannerBuilder(CompilationModuleGroup compilationGroup = null) { return new ILScannerBuilder(_context, compilationGroup ?? _compilationGroup, _nameMangler); diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedMetadataManager.cs index 3e1a5c368..9026446e2 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedMetadataManager.cs @@ -15,6 +15,7 @@ using ILCompiler.Metadata; using ILCompiler.DependencyAnalysis; using Debug = System.Diagnostics.Debug; +using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList; namespace ILCompiler { @@ -22,56 +23,70 @@ namespace ILCompiler /// This class is responsible for managing native metadata to be emitted into the compiled /// module. It applies a policy that every type/method emitted shall be reflectable. /// </summary> - public class CompilerGeneratedMetadataManager : MetadataManager + public sealed class CompilerGeneratedMetadataManager : MetadataManager { - private GeneratedTypesAndCodeMetadataPolicy _metadataPolicy; - private string _metadataLogFile; + private readonly string _metadataLogFile; + private Dictionary<DynamicInvokeMethodSignature, MethodDesc> _dynamicInvokeThunks = new Dictionary<DynamicInvokeMethodSignature, MethodDesc>(); public CompilerGeneratedMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext, string logFile) - : base(group, typeSystemContext) + : base(group, typeSystemContext, new BlockedInternalsBlockingPolicy()) { - _metadataPolicy = new GeneratedTypesAndCodeMetadataPolicy(this); _metadataLogFile = logFile; } - private HashSet<MetadataType> _typeDefinitionsToGenerate = new HashSet<MetadataType>(); - private HashSet<MethodDesc> _methodDefinitionsToGenerate = new HashSet<MethodDesc>(); - private HashSet<ModuleDesc> _modulesSeen = new HashSet<ModuleDesc>(); - private Dictionary<DynamicInvokeMethodSignature, MethodDesc> _dynamicInvokeThunks = new Dictionary<DynamicInvokeMethodSignature, MethodDesc>(); - - public override IEnumerable<ModuleDesc> GetCompilationModulesWithMetadata() - { - return _modulesSeen; - } - - public override bool IsReflectionBlocked(MetadataType type) - { - return _metadataPolicy.IsBlocked(type); - } - public override bool WillUseMetadataTokenToReferenceMethod(MethodDesc method) { - return _compilationModuleGroup.ContainsType(method.GetTypicalMethodDefinition().OwningType); + return (GetMetadataCategory(method) & MetadataCategory.Description) != 0; } public override bool WillUseMetadataTokenToReferenceField(FieldDesc field) { - return _compilationModuleGroup.ContainsType(field.GetTypicalFieldDefinition().OwningType); + return (GetMetadataCategory(field) & MetadataCategory.Description) != 0; } protected override MetadataCategory GetMetadataCategory(FieldDesc field) { - return MetadataCategory.RuntimeMapping; + MetadataCategory category = 0; + + if (!IsReflectionBlocked(field)) + { + category = MetadataCategory.RuntimeMapping; + + if (_compilationModuleGroup.ContainsType(field.GetTypicalFieldDefinition().OwningType)) + category |= MetadataCategory.Description; + } + + return category; } protected override MetadataCategory GetMetadataCategory(MethodDesc method) { - return MetadataCategory.RuntimeMapping; + MetadataCategory category = 0; + + if (!IsReflectionBlocked(method)) + { + category = MetadataCategory.RuntimeMapping; + + if (_compilationModuleGroup.ContainsType(method.GetTypicalMethodDefinition().OwningType)) + category |= MetadataCategory.Description; + } + + return category; } protected override MetadataCategory GetMetadataCategory(TypeDesc type) { - return MetadataCategory.RuntimeMapping; + MetadataCategory category = 0; + + if (!IsReflectionBlocked(type)) + { + category = MetadataCategory.RuntimeMapping; + + if (_compilationModuleGroup.ContainsType(type.GetTypeDefinition())) + category |= MetadataCategory.Description; + } + + return category; } protected override void ComputeMetadata(NodeFactory factory, @@ -80,34 +95,7 @@ namespace ILCompiler out List<MetadataMapping<MethodDesc>> methodMappings, out List<MetadataMapping<FieldDesc>> fieldMappings) { - foreach (var type in factory.MetadataManager.GetTypesWithEETypes()) - { - var definition = type.GetTypeDefinition() as Internal.TypeSystem.Ecma.EcmaType; - if (definition == null) - continue; - if (factory.CompilationModuleGroup.ContainsType(definition)) - { - _typeDefinitionsToGenerate.Add(definition); - _modulesSeen.Add(definition.Module); - } - } - - foreach (var method in GetCompiledMethods()) - { - var typicalMethod = method.GetTypicalMethodDefinition() as Internal.TypeSystem.Ecma.EcmaMethod; - if (typicalMethod != null) - { - var owningType = (MetadataType)typicalMethod.OwningType; - if (factory.CompilationModuleGroup.ContainsType(owningType)) - { - _typeDefinitionsToGenerate.Add(owningType); - _modulesSeen.Add(owningType.Module); - _methodDefinitionsToGenerate.Add(typicalMethod); - } - } - } - - var transformed = MetadataTransform.Run(new GeneratedTypesAndCodeMetadataPolicy(this), _modulesSeen); + var transformed = MetadataTransform.Run(new GeneratedTypesAndCodeMetadataPolicy(this, factory), GetCompilationModulesWithMetadata()); // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate // TypeReference records for _typeDefinitionsGenerated that don't have metadata. @@ -194,7 +182,14 @@ namespace ILCompiler public override bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method) { Debug.Assert(IsReflectionInvokable(method)); - return true; + + // Place an upper limit on how many parameters a method can have to still get a static stub. + // From the past experience, methods taking 8000+ parameters get a stub that can hit various limitations + // in the codegen. On Project N, we were limited to 256 parameters because of MDIL limitations. + // We don't have such limitations here, but it's a nice round number. + // Reflection invoke will still work, but will go through the calling convention converter. + + return method.Signature.Length <= 256; } /// <summary> @@ -217,79 +212,48 @@ namespace ILCompiler return InstantiateCanonicalDynamicInvokeMethodForMethod(thunk, method); } + protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + { + dependencies = dependencies ?? new DependencyList(); + dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "Reflectable method"); + } + + protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + { + TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type"); + } + private struct GeneratedTypesAndCodeMetadataPolicy : IMetadataPolicy { - private CompilerGeneratedMetadataManager _parent; - private ExplicitScopeAssemblyPolicyMixin _explicitScopeMixin; - private Dictionary<MetadataType, bool> _isAttributeCache; + private readonly CompilerGeneratedMetadataManager _parent; + private readonly NodeFactory _factory; + private readonly ExplicitScopeAssemblyPolicyMixin _explicitScopeMixin; - public GeneratedTypesAndCodeMetadataPolicy(CompilerGeneratedMetadataManager parent) + public GeneratedTypesAndCodeMetadataPolicy(CompilerGeneratedMetadataManager parent, NodeFactory factory) { _parent = parent; + _factory = factory; _explicitScopeMixin = new ExplicitScopeAssemblyPolicyMixin(); - - MetadataType systemAttributeType = parent._typeSystemContext.SystemModule.GetType("System", "Attribute", false); - _isAttributeCache = new Dictionary<MetadataType, bool>(); - _isAttributeCache.Add(systemAttributeType, true); } public bool GeneratesMetadata(FieldDesc fieldDef) { - return _parent._typeDefinitionsToGenerate.Contains((MetadataType)fieldDef.OwningType); + return _factory.TypeMetadata((MetadataType)fieldDef.OwningType).Marked; } public bool GeneratesMetadata(MethodDesc methodDef) { - return _parent._methodDefinitionsToGenerate.Contains(methodDef); + return _factory.MethodMetadata(methodDef).Marked; } public bool GeneratesMetadata(MetadataType typeDef) { - // Global module type always generates metadata. This is e.g. used in various places - // where we need a metadata enabled type from an assembly but we don't have a convenient way - // to find one. - // We don't need to worry about metadata consistency (accidentally generating metadata - // that can't be used with any reflection API at runtime because it's incomplete) because - // global module types don't derive from anything and have an empty interface list. - if (typeDef.IsModuleType) - return true; - - // Metadata consistency: if a nested type generates metadata, the containing type is - // required to generate metadata, or metadata generation will fail. - foreach (var nested in typeDef.GetNestedTypes()) - { - if (GeneratesMetadata(nested)) - return true; - } - - return _parent._typeDefinitionsToGenerate.Contains(typeDef); + return _factory.TypeMetadata(typeDef).Marked; } public bool IsBlocked(MetadataType typeDef) { - // If an attribute type would generate metadata in this blob (had we compiled it), consider it blocked. - // Otherwise we end up with an attribute that is an unresolvable TypeRef and we would get a TypeLoadException - // when enumerating attributes on anything that has it. - if (!GeneratesMetadata(typeDef) - && _parent._compilationModuleGroup.ContainsType(typeDef) - && IsAttributeType(typeDef)) - { - return true; - } - - return false; - } - - private bool IsAttributeType(MetadataType type) - { - bool result; - if (!_isAttributeCache.TryGetValue(type, out result)) - { - MetadataType baseType = type.MetadataBaseType; - result = baseType != null && IsAttributeType(baseType); - _isAttributeCache.Add(type, result); - } - return result; + return _parent._blockingPolicy.IsBlocked(typeDef); } public ModuleDesc GetModuleOfType(MetadataType typeDef) diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs new file mode 100644 index 000000000..28cee9b04 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs @@ -0,0 +1,204 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Diagnostics; +using System.Reflection.Metadata; + +using Internal.TypeSystem; +using Internal.TypeSystem.Ecma; + +using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList; + +namespace ILCompiler.DependencyAnalysis +{ + /// <summary> + /// Computes the list of dependencies that are necessary to generate metadata for a custom attribute, but also the dependencies to + /// make the custom attributes usable by the reflection stack at runtime. + /// </summary> + internal class CustomAttributeBasedDependencyAlgorithm + { + public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaMethod method) + { + MetadataReader reader = method.MetadataReader; + MethodDefinition methodDef = reader.GetMethodDefinition(method.Handle); + AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, methodDef.GetCustomAttributes()); + } + + public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaType type) + { + TypeDefinition typeDef = type.MetadataReader.GetTypeDefinition(type.Handle); + AddDependenciesDueToCustomAttributes(ref dependencies, factory, type.EcmaModule, typeDef.GetCustomAttributes()); + } + + public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaField field) + { + FieldDefinition fieldDef = field.MetadataReader.GetFieldDefinition(field.Handle); + AddDependenciesDueToCustomAttributes(ref dependencies, factory, field.Module, fieldDef.GetCustomAttributes()); + } + + public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaAssembly assembly) + { + AssemblyDefinition asmDef = assembly.MetadataReader.GetAssemblyDefinition(); + AddDependenciesDueToCustomAttributes(ref dependencies, factory, assembly, asmDef.GetCustomAttributes()); + } + + private static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaModule module, CustomAttributeHandleCollection attributeHandles) + { + MetadataReader reader = module.MetadataReader; + MetadataManager mdManager = factory.MetadataManager; + var attributeTypeProvider = new CustomAttributeTypeProvider(module); + + + foreach (CustomAttributeHandle caHandle in attributeHandles) + { + CustomAttribute attribute = reader.GetCustomAttribute(caHandle); + + try + { + MethodDesc constructor = module.GetMethod(attribute.Constructor); + if (mdManager.IsReflectionBlocked(constructor)) + continue; + + // Make a new list in case we need to abort. + var caDependencies = new DependencyList(); + + caDependencies.Add(factory.CanonicalEntrypoint(constructor), "Attribute constructor"); + caDependencies.Add(factory.ConstructedTypeSymbol(constructor.OwningType), "Attribute type"); + + CustomAttributeValue<TypeDesc> decodedValue = attribute.DecodeValue(attributeTypeProvider); + + if (AddDependenciesFromCustomAttributeBlob(caDependencies, factory, constructor.OwningType, decodedValue)) + { + dependencies = dependencies ?? new DependencyList(); + dependencies.AddRange(caDependencies); + } + } + catch (TypeSystemException) + { + // We could end up seeing an exception here for a multitude of reasons: + // * Attribute ctor doesn't resolve + // * There's a typeof() that refers to something that can't be loaded + // * Attribute refers to a non-existing field + // * Etc. + // + // If we really wanted to, we could probably come up with a way to still make this + // work with the same failure modes at runtime as the CLR, but it might not be + // worth the hassle: the input was invalid. The most important thing is that we + // don't crash the compilation. + } + } + } + + private static bool AddDependenciesFromCustomAttributeBlob(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, CustomAttributeValue<TypeDesc> value) + { + MetadataManager mdManager = factory.MetadataManager; + + foreach (CustomAttributeTypedArgument<TypeDesc> decodedArgument in value.FixedArguments) + { + if (!AddDependenciesFromCustomAttributeArgument(dependencies, factory, decodedArgument.Type, decodedArgument.Value)) + return false; + } + + foreach (CustomAttributeNamedArgument<TypeDesc> decodedArgument in value.NamedArguments) + { + if (decodedArgument.Kind == CustomAttributeNamedArgumentKind.Field) + { + // This is an instance field. We don't track them right now. + } + else + { + Debug.Assert(decodedArgument.Kind == CustomAttributeNamedArgumentKind.Property); + + // Reflection will need to reflection-invoke the setter at runtime. + if (!AddDependenciesFromPropertySetter(dependencies, factory, attributeType, decodedArgument.Name)) + return false; + } + + if (!AddDependenciesFromCustomAttributeArgument(dependencies, factory, decodedArgument.Type, decodedArgument.Value)) + return false; + } + + return true; + } + + private static bool AddDependenciesFromPropertySetter(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, string propertyName) + { + EcmaType attributeTypeDefinition = (EcmaType)attributeType.GetTypeDefinition(); + + MetadataReader reader = attributeTypeDefinition.MetadataReader; + var typeDefinition = reader.GetTypeDefinition(attributeTypeDefinition.Handle); + + foreach (PropertyDefinitionHandle propDefHandle in typeDefinition.GetProperties()) + { + PropertyDefinition propDef = reader.GetPropertyDefinition(propDefHandle); + if (reader.StringComparer.Equals(propDef.Name, propertyName)) + { + PropertyAccessors accessors = propDef.GetAccessors(); + + if (!accessors.Setter.IsNil) + { + MethodDesc setterMethod = (MethodDesc)attributeTypeDefinition.EcmaModule.GetObject(accessors.Setter); + if (factory.MetadataManager.IsReflectionBlocked(setterMethod)) + return false; + + // Method on a generic attribute + if (attributeType != attributeTypeDefinition) + { + setterMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(setterMethod, (InstantiatedType)attributeType); + } + + // TODO: what if the setter is virtual/abstract? + dependencies.Add(factory.CanonicalEntrypoint(setterMethod), "Custom attribute blob"); + } + + return true; + } + } + + // Haven't found it in current type. Check the base type. + TypeDesc baseType = attributeType.BaseType; + + if (baseType != null) + return AddDependenciesFromPropertySetter(dependencies, factory, baseType, propertyName); + + // Not found. This is bad metadata that will result in a runtime failure, but we shouldn't fail the compilation. + return true; + } + + private static bool AddDependenciesFromCustomAttributeArgument(DependencyList dependencies, NodeFactory factory, TypeDesc type, object value) + { + if (type.UnderlyingType.IsPrimitive || type.IsString || value == null) + return true; + + if (type.IsSzArray) + { + TypeDesc elementType = ((ArrayType)type).ElementType; + if (elementType.UnderlyingType.IsPrimitive || elementType.IsString) + return true; + + foreach (CustomAttributeTypedArgument<TypeDesc> arrayElement in (ImmutableArray<CustomAttributeTypedArgument<TypeDesc>>)value) + { + if (!AddDependenciesFromCustomAttributeArgument(dependencies, factory, arrayElement.Type, arrayElement.Value)) + return false; + } + + return true; + } + + // typeof() should be the only remaining option. + + Debug.Assert(value is TypeDesc); + + TypeDesc typeofType = (TypeDesc)value; + + if (factory.MetadataManager.IsReflectionBlocked(typeofType)) + return false; + + TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, typeofType, "Custom attribute blob"); + + return true; + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodMetadataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodMetadataNode.cs new file mode 100644 index 000000000..04dd37671 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodMetadataNode.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; + +using ILCompiler.DependencyAnalysisFramework; + +using Internal.TypeSystem; + +using Debug = System.Diagnostics.Debug; +using EcmaMethod = Internal.TypeSystem.Ecma.EcmaMethod; + +namespace ILCompiler.DependencyAnalysis +{ + /// <summary> + /// Represents a method that has metadata generated in the current compilation. + /// </summary> + /// <remarks> + /// Only expected to be used during ILScanning when scanning for reflection. + /// </remarks> + internal class MethodMetadataNode : DependencyNodeCore<NodeFactory> + { + private readonly MethodDesc _method; + + public MethodMetadataNode(MethodDesc method) + { + Debug.Assert(method.IsTypicalMethodDefinition); + _method = method; + } + + public MethodDesc Method => _method; + + public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) + { + DependencyList dependencies = new DependencyList(); + dependencies.Add(factory.TypeMetadata((MetadataType)_method.OwningType), "Owning type metadata"); + + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaMethod)_method)); + + return dependencies; + } + protected override string GetName(NodeFactory factory) + { + return "Reflectable method: " + _method.ToString(); + } + + protected override void OnMarked(NodeFactory factory) + { + Debug.Assert(!factory.MetadataManager.IsReflectionBlocked(_method)); + Debug.Assert(factory.MetadataManager.CanGenerateMetadata(_method)); + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + public override bool HasDynamicDependencies => false; + public override bool HasConditionalStaticDependencies => false; + public override bool StaticDependenciesAreComputed => true; + public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; + public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModuleMetadataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModuleMetadataNode.cs new file mode 100644 index 000000000..f152dc988 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModuleMetadataNode.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; + +using ILCompiler.DependencyAnalysisFramework; + +using Internal.TypeSystem; + +using Debug = System.Diagnostics.Debug; +using EcmaAssembly = Internal.TypeSystem.Ecma.EcmaAssembly; + +namespace ILCompiler.DependencyAnalysis +{ + /// <summary> + /// Represents a reflectable module. + /// </summary> + /// <remarks> + /// Only expected to be used during ILScanning when scanning for reflection. + /// </remarks> + internal class ModuleMetadataNode : DependencyNodeCore<NodeFactory> + { + private readonly ModuleDesc _module; + + public ModuleMetadataNode(ModuleDesc module) + { + Debug.Assert(module is IAssemblyDesc, "Multi-module assemblies?"); + _module = module; + } + + public ModuleDesc Module => _module; + + public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) + { + DependencyList dependencies = new DependencyList(); + + // Global module type always generates metadata because it's really convenient to + // have something in an assembly that always generates metadata. + dependencies.Add(factory.TypeMetadata(_module.GetGlobalModuleType()), "Global module type"); + + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, (EcmaAssembly)_module); + + return dependencies; + } + + protected override string GetName(NodeFactory factory) + { + return "Reflectable module: " + ((IAssemblyDesc)_module).GetName().FullName; + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + public override bool HasDynamicDependencies => false; + public override bool HasConditionalStaticDependencies => false; + public override bool StaticDependenciesAreComputed => true; + public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; + public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs index 139204519..8e721c7a3 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs @@ -435,6 +435,21 @@ namespace ILCompiler.DependencyAnalysis } }); + _typesWithMetadata = new NodeCache<MetadataType, TypeMetadataNode>(type => + { + return new TypeMetadataNode(type); + }); + + _methodsWithMetadata = new NodeCache<MethodDesc, MethodMetadataNode>(method => + { + return new MethodMetadataNode(method); + }); + + _modulesWithMetadata = new NodeCache<ModuleDesc, ModuleMetadataNode>(module => + { + return new ModuleMetadataNode(module); + }); + _genericDictionaryLayouts = new NodeCache<TypeSystemEntity, DictionaryLayoutNode>(methodOrType => { return new DictionaryLayoutNode(methodOrType); @@ -854,6 +869,27 @@ namespace ILCompiler.DependencyAnalysis } } + private NodeCache<MetadataType, TypeMetadataNode> _typesWithMetadata; + + internal TypeMetadataNode TypeMetadata(MetadataType type) + { + return _typesWithMetadata.GetOrAdd(type); + } + + private NodeCache<MethodDesc, MethodMetadataNode> _methodsWithMetadata; + + internal MethodMetadataNode MethodMetadata(MethodDesc method) + { + return _methodsWithMetadata.GetOrAdd(method); + } + + private NodeCache<ModuleDesc, ModuleMetadataNode> _modulesWithMetadata; + + internal ModuleMetadataNode ModuleMetadata(ModuleDesc module) + { + return _modulesWithMetadata.GetOrAdd(module); + } + private NodeCache<string, FrozenStringNode> _frozenStringNodes; public FrozenStringNode SerializedStringObject(string data) diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs new file mode 100644 index 000000000..a213511c0 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +using ILCompiler.DependencyAnalysisFramework; + +using Internal.TypeSystem; + +using Debug = System.Diagnostics.Debug; +using EcmaType = Internal.TypeSystem.Ecma.EcmaType; + +namespace ILCompiler.DependencyAnalysis +{ + /// <summary> + /// Represents a type that has metadata generated in the current compilation. + /// </summary> + /// <remarks> + /// Only expected to be used during ILScanning when scanning for reflection. + /// </remarks> + internal class TypeMetadataNode : DependencyNodeCore<NodeFactory> + { + private readonly MetadataType _type; + + public TypeMetadataNode(MetadataType type) + { + Debug.Assert(type.IsTypeDefinition); + _type = type; + } + + public MetadataType Type => _type; + + public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) + { + DependencyList dependencies = new DependencyList(); + + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type)); + + DefType containingType = _type.ContainingType; + if (containingType != null) + dependencies.Add(factory.TypeMetadata((MetadataType)containingType), "Containing type of a reflectable type"); + else + dependencies.Add(factory.ModuleMetadata(_type.Module), "Containing module of a reflectable type"); + + return dependencies; + } + + /// <summary> + /// Decomposes a constructed type into individual <see cref="TypeMetadataNode"/> units that will be needed to + /// express the constructed type in metadata. + /// </summary> + public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason) + { + MetadataManager mdManager = nodeFactory.MetadataManager; + + switch (type.Category) + { + case TypeFlags.Array: + case TypeFlags.SzArray: + case TypeFlags.ByRef: + case TypeFlags.Pointer: + GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason); + break; + case TypeFlags.FunctionPointer: + throw new NotImplementedException(); + + default: + Debug.Assert(type.IsDefType); + + TypeDesc typeDefinition = type.GetTypeDefinition(); + if (typeDefinition != type) + { + if (mdManager.CanGenerateMetadata((MetadataType)typeDefinition)) + { + dependencies.Add(nodeFactory.TypeMetadata((MetadataType)typeDefinition), reason); + } + + foreach (TypeDesc typeArg in type.Instantiation) + { + GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason); + } + } + else + { + if (mdManager.CanGenerateMetadata((MetadataType)type)) + { + dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason); + } + } + break; + } + } + + protected override string GetName(NodeFactory factory) + { + return "Reflectable type: " + _type.ToString(); + } + + protected override void OnMarked(NodeFactory factory) + { + Debug.Assert(!factory.MetadataManager.IsReflectionBlocked(_type)); + Debug.Assert(factory.MetadataManager.CanGenerateMetadata(_type)); + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + public override bool HasDynamicDependencies => false; + public override bool HasConditionalStaticDependencies => false; + public override bool StaticDependenciesAreComputed => true; + public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; + public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs index d80103870..082268a5f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs @@ -14,7 +14,8 @@ namespace ILCompiler { class EmptyMetadataManager : MetadataManager { - public EmptyMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext) : base(group, typeSystemContext) + public EmptyMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext) + : base(group, typeSystemContext, new FullyBlockedMetadataPolicy()) { } @@ -23,11 +24,6 @@ namespace ILCompiler return Array.Empty<ModuleDesc>(); } - public override bool IsReflectionBlocked(MetadataType type) - { - return true; - } - protected override MetadataCategory GetMetadataCategory(FieldDesc field) { return MetadataCategory.None; @@ -78,5 +74,26 @@ namespace ILCompiler { return false; } + + private sealed class FullyBlockedMetadataPolicy : MetadataBlockingPolicy + { + public override bool IsBlocked(MetadataType type) + { + Debug.Assert(type.IsTypeDefinition); + return true; + } + + public override bool IsBlocked(MethodDesc method) + { + Debug.Assert(method.IsTypicalMethodDefinition); + return true; + } + + public override bool IsBlocked(FieldDesc field) + { + Debug.Assert(field.IsTypicalFieldDefinition); + return true; + } + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/MetadataBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/MetadataBlockingPolicy.cs new file mode 100644 index 000000000..3a2591a28 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/MetadataBlockingPolicy.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.TypeSystem; + +using Debug = System.Diagnostics.Debug; + +namespace ILCompiler +{ + /// <summary> + /// Represents a metadata blocking policy. A metadata blocking policy decides what types or members are never + /// eligible to have their metadata generated into the executable. + /// </summary> + public abstract class MetadataBlockingPolicy + { + /// <summary> + /// Returns true if type definition '<paramref name="type"/>' is reflection blocked. + /// </summary> + public abstract bool IsBlocked(MetadataType type); + + /// <summary> + /// Returns true if method definition '<paramref name="method"/>' is reflection blocked. + /// </summary> + public abstract bool IsBlocked(MethodDesc method); + + /// <summary> + /// Returns true if field definition '<paramref name="field"/>' is reflection blocked. + /// </summary> + public abstract bool IsBlocked(FieldDesc field); + } + + /// <summary> + /// Represents a metadata policy that blocks implementations details. + /// </summary> + public sealed class BlockedInternalsBlockingPolicy : MetadataBlockingPolicy + { + public override bool IsBlocked(MetadataType type) + { + Debug.Assert(type.IsTypeDefinition); + + // TODO: Make this also respect System.Runtime.CompilerServices.DisablePrivateReflectionAttribute + return !(type is Internal.TypeSystem.Ecma.EcmaType); + } + + public override bool IsBlocked(MethodDesc method) + { + Debug.Assert(method.IsTypicalMethodDefinition); + + // TODO: Make this also respect System.Runtime.CompilerServices.DisablePrivateReflectionAttribute + return !(method is Internal.TypeSystem.Ecma.EcmaMethod); + } + + public override bool IsBlocked(FieldDesc field) + { + Debug.Assert(field.IsTypicalFieldDefinition); + + // TODO: Make this also respect System.Runtime.CompilerServices.DisablePrivateReflectionAttribute + return !(field is Internal.TypeSystem.Ecma.EcmaField); + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs index 3dde1435a..d5021c29c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs @@ -37,21 +37,24 @@ namespace ILCompiler protected readonly CompilationModuleGroup _compilationModuleGroup; protected readonly CompilerTypeSystemContext _typeSystemContext; + protected readonly MetadataBlockingPolicy _blockingPolicy; private List<NonGCStaticsNode> _cctorContextsGenerated = new List<NonGCStaticsNode>(); private HashSet<TypeDesc> _typesWithEETypesGenerated = new HashSet<TypeDesc>(); private HashSet<TypeDesc> _typesWithConstructedEETypesGenerated = new HashSet<TypeDesc>(); private HashSet<MethodDesc> _methodsGenerated = new HashSet<MethodDesc>(); private HashSet<GenericDictionaryNode> _genericDictionariesGenerated = new HashSet<GenericDictionaryNode>(); + private List<ModuleDesc> _modulesWithMetadata = new List<ModuleDesc>(); private List<TypeGVMEntriesNode> _typeGVMEntries = new List<TypeGVMEntriesNode>(); internal NativeLayoutInfoNode NativeLayoutInfo { get; private set; } internal DynamicInvokeTemplateDataNode DynamicInvokeTemplateData { get; private set; } - public MetadataManager(CompilationModuleGroup compilationModuleGroup, CompilerTypeSystemContext typeSystemContext) + public MetadataManager(CompilationModuleGroup compilationModuleGroup, CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy) { _compilationModuleGroup = compilationModuleGroup; _typeSystemContext = typeSystemContext; + _blockingPolicy = blockingPolicy; } public void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph) @@ -193,6 +196,13 @@ namespace ILCompiler { _genericDictionariesGenerated.Add(dictionaryNode); } + + // TODO: temporary until we have an IL scanning Metadata Manager. We shouldn't have to keep track of these. + var moduleMetadataNode = obj as ModuleMetadataNode; + if (moduleMetadataNode != null) + { + _modulesWithMetadata.Add(moduleMetadataNode.Module); + } } /// <summary> @@ -256,18 +266,36 @@ namespace ILCompiler protected bool IsMethodSupportedInReflectionInvoke(MethodDesc method) { - // TODO: also filter out: .cctor, Finalize, string constructors, - // RuntimeHelpers.InitializeArray, methods on Nullable, - // IntPtr/UIntPtr constructors. Maybe more. + TypeDesc owningType = method.OwningType; - // ---------------------------------------------------------------- - // Delegate construction is only allowed through specific IL sequences - // ---------------------------------------------------------------- + // Methods on nullable are special cased in the runtime reflection + if (owningType.IsNullable) + return false; + + // Finalizers are not reflection invokable + if (method.IsFinalizer) + return false; - if (method.OwningType.IsDelegate && method.IsConstructor) + // Static constructors are not reflection invokable + if (method.IsStaticConstructor) return false; - // Everything else should get a stub. + if (method.IsConstructor) + { + // Delegate construction is only allowed through specific IL sequences + if (owningType.IsDelegate) + return false; + + // String constructors are intrinsic and special cased in runtime reflection + if (owningType.IsString) + return false; + + // IntPtr/UIntPtr constructors are intrinsic and special cased in runtime reflection + if (owningType.IsWellKnownType(WellKnownType.IntPtr) || owningType.IsWellKnownType(WellKnownType.UIntPtr)) + return false; + } + + // Everything else can go in the mapping table. return true; } @@ -479,7 +507,11 @@ namespace ILCompiler /// <summary> /// Returns a set of modules that will get some metadata emitted into the output module /// </summary> - public abstract IEnumerable<ModuleDesc> GetCompilationModulesWithMetadata(); + public virtual IEnumerable<ModuleDesc> GetCompilationModulesWithMetadata() + { + // TODO: this is temporary until we have a metadata manager for IL scanner. This method should be abstract. + return _modulesWithMetadata; + } public byte[] GetMetadataBlob(NodeFactory factory) { @@ -540,9 +572,109 @@ namespace ILCompiler return _typesWithConstructedEETypesGenerated; } - public abstract bool IsReflectionBlocked(MetadataType type); + public bool IsReflectionBlocked(TypeDesc type) + { + switch (type.Category) + { + case TypeFlags.SzArray: + case TypeFlags.Array: + case TypeFlags.Pointer: + case TypeFlags.ByRef: + return IsReflectionBlocked(((ParameterizedType)type).ParameterType); + + case TypeFlags.FunctionPointer: + throw new NotImplementedException(); + + default: + Debug.Assert(type.IsDefType); + + TypeDesc typeDefinition = type.GetTypeDefinition(); + if (type != typeDefinition) + { + if (_blockingPolicy.IsBlocked((MetadataType)typeDefinition)) + return true; + + foreach (var arg in type.Instantiation) + if (IsReflectionBlocked(arg)) + return true; + + return false; + } + + if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any)) + return false; + return _blockingPolicy.IsBlocked((MetadataType)type); + } + } + + public bool IsReflectionBlocked(FieldDesc field) + { + FieldDesc typicalFieldDefinition = field.GetTypicalFieldDefinition(); + if (typicalFieldDefinition != field) + { + foreach (TypeDesc type in field.OwningType.Instantiation) + { + if (IsReflectionBlocked(type)) + return true; + } + } + + return _blockingPolicy.IsBlocked(typicalFieldDefinition); + } + + public bool IsReflectionBlocked(MethodDesc method) + { + MethodDesc methodDefinition = method.GetMethodDefinition(); + if (method != methodDefinition) + { + foreach (TypeDesc type in method.Instantiation) + { + if (IsReflectionBlocked(type)) + return true; + } + } + + MethodDesc typicalMethodDefinition = methodDefinition.GetTypicalMethodDefinition(); + if (typicalMethodDefinition != methodDefinition) + { + foreach (TypeDesc type in method.OwningType.Instantiation) + { + if (IsReflectionBlocked(type)) + return true; + } + } + + return _blockingPolicy.IsBlocked(typicalMethodDefinition); + } + + public bool CanGenerateMetadata(MetadataType type) + { + return (GetMetadataCategory(type) & MetadataCategory.Description) != 0; + } + + public bool CanGenerateMetadata(MethodDesc method) + { + Debug.Assert(method.IsTypicalMethodDefinition); + return (GetMetadataCategory(method) & MetadataCategory.Description) != 0; + } + + /// <summary> + /// Gets the metadata category for a compiled method body in the current compilation. + /// The method will only get called with '<paramref name="method"/>' that has a compiled method body + /// in this compilation. + /// Note that if this method doesn't return <see cref="MetadataCategory.Description"/>, it doesn't mean + /// that the method never has metadata. The metadata might just be generated in a different compilation. + /// </summary> protected abstract MetadataCategory GetMetadataCategory(MethodDesc method); + + /// <summary> + /// Gets the metadata category for a generated type in the current compilation. + /// The method can assume it will only get called with '<paramref name="type"/>' that has an EEType generated + /// in the current compilation. + /// Note that if this method doesn't return <see cref="MetadataCategory.Description"/>, it doesn't mean + /// that the method never has metadata. The metadata might just be generated in a different compilation. + /// </summary> protected abstract MetadataCategory GetMetadataCategory(TypeDesc type); protected abstract MetadataCategory GetMetadataCategory(FieldDesc field); } @@ -559,6 +691,7 @@ namespace ILCompiler } } + [Flags] public enum MetadataCategory { None = 0x00, diff --git a/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs index 942e85ba5..9a6765dbe 100644 --- a/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs @@ -42,7 +42,8 @@ namespace ILCompiler private Lazy<Dictionary<MethodDesc, MethodDesc>> _dynamicInvokeStubs; private readonly byte[] _metadataBlob; - public PrecomputedMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext, ModuleDesc metadataDescribingModule, IEnumerable<ModuleDesc> compilationModules, byte[] metadataBlob) : base(group, typeSystemContext) + public PrecomputedMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext, ModuleDesc metadataDescribingModule, IEnumerable<ModuleDesc> compilationModules, byte[] metadataBlob) + : base(group, typeSystemContext, new AttributeSpecifiedBlockingPolicy()) { _metadataDescribingModule = metadataDescribingModule; _compilationModules = new HashSet<ModuleDesc>(compilationModules); @@ -187,11 +188,6 @@ namespace ILCompiler return _loadedMetadata.Value.LocalMetadataModules; } - public override bool IsReflectionBlocked(MetadataType type) - { - return type.HasCustomAttribute("System.Runtime.CompilerServices", "ReflectionBlockedAttribute"); - } - public override bool WillUseMetadataTokenToReferenceMethod(MethodDesc method) { return _compilationModuleGroup.ContainsType(method.GetTypicalMethodDefinition().OwningType); @@ -449,5 +445,28 @@ namespace ILCompiler return dynamicInvokeStubCanonicalized; } + + private sealed class AttributeSpecifiedBlockingPolicy : MetadataBlockingPolicy + { + public override bool IsBlocked(MetadataType type) + { + Debug.Assert(type.IsTypeDefinition); + return type.HasCustomAttribute("System.Runtime.CompilerServices", "ReflectionBlockedAttribute"); + } + + public override bool IsBlocked(MethodDesc method) + { + Debug.Assert(method.IsTypicalMethodDefinition); + // TODO: we might need to do something here if we keep this policy. + return false; + } + + public override bool IsBlocked(FieldDesc field) + { + Debug.Assert(field.IsTypicalFieldDefinition); + // TODO: we might need to do something here if we keep this policy. + return false; + } + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs index 58850e22c..20d9b497f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs +++ b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs @@ -74,9 +74,7 @@ namespace ILCompiler if (_generateDebugInfo) jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_DEBUG_INFO); - MetadataManager metadataManager = CreateMetadataManager(); - - var factory = new RyuJitNodeFactory(_context, _compilationGroup, metadataManager, _nameMangler); + var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, _nameMangler); var jitConfig = new JitConfigProvider(jitFlagBuilder.ToArray(), _ryujitOptions); DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory); diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj index 966f7e972..f780e292c 100644 --- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj +++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj @@ -112,13 +112,18 @@ <Compile Include="Compiler\CompilerTypeSystemContext.BoxedTypes.cs" /> <Compile Include="Compiler\CompilerTypeSystemContext.Mangling.cs" /> <Compile Include="Compiler\CompilerTypeSystemContext.Sorting.cs" /> + <Compile Include="Compiler\DependencyAnalysis\CustomAttributeBasedDependencyAlgorithm.cs" /> <Compile Include="Compiler\DependencyAnalysis\ILScanNodeFactory.cs" /> <Compile Include="Compiler\PreInitFieldInfo.cs" /> <Compile Include="Compiler\DependencyAnalysis\FrozenArrayNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\GCStaticsPreInitDataNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\ImportedGenericDictionaryNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\DynamicInvokeTemplateDataNode.cs" /> + <Compile Include="Compiler\MetadataBlockingPolicy.cs" /> + <Compile Include="Compiler\DependencyAnalysis\MethodMetadataNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\ReflectableMethodNode.cs" /> + <Compile Include="Compiler\DependencyAnalysis\ModuleMetadataNode.cs" /> + <Compile Include="Compiler\DependencyAnalysis\TypeMetadataNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\ScannedMethodNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\ShadowConcreteUnboxingThunkNode.cs" /> <Compile Include="Compiler\DependencyTrackingLevel.cs" /> diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs b/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs index 0ad6851c0..7ea68e212 100644 --- a/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs +++ b/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs @@ -29,8 +29,7 @@ namespace ILCompiler public override ICompilation ToCompilation() { - MetadataManager metadataManager = CreateMetadataManager(); - CppCodegenNodeFactory factory = new CppCodegenNodeFactory(_context, _compilationGroup, metadataManager, _nameMangler); + CppCodegenNodeFactory factory = new CppCodegenNodeFactory(_context, _compilationGroup, _metadataManager, _nameMangler); DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory); return new CppCodegenCompilation(graph, factory, _compilationRoots, _logger, _config); diff --git a/src/ILCompiler/src/Program.cs b/src/ILCompiler/src/Program.cs index ccb52f9c4..28d02f8be 100644 --- a/src/ILCompiler/src/Program.cs +++ b/src/ILCompiler/src/Program.cs @@ -335,14 +335,16 @@ namespace ILCompiler DependencyTrackingLevel trackingLevel = _dgmlLogFileName == null ? DependencyTrackingLevel.None : (_generateFullDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First); + CompilerGeneratedMetadataManager metadataManager = new CompilerGeneratedMetadataManager(compilationGroup, typeSystemContext, _metadataLogFileName); + ICompilation compilation = builder .UseBackendOptions(_codegenOptions) + .UseMetadataManager(metadataManager) .UseLogger(logger) .UseDependencyTracking(trackingLevel) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(_optimizationMode) .UseDebugInfo(_enableDebugInfo) - .UseMetadataLogFile(_metadataLogFileName) .ToCompilation(); ObjectDumper dumper = _mapFileName != null ? new ObjectDumper(_mapFileName) : null; |