Пример #1
0
        private void ProcessAssemblyDirective(IRootingServiceProvider rootProvider, XElement assemblyElement)
        {
            var assemblyNameAttribute = assemblyElement.Attribute("Name");
            if (assemblyNameAttribute == null)
                throw new Exception();

            ModuleDesc assembly = _context.ResolveAssembly(new AssemblyName(assemblyNameAttribute.Value));

            rootProvider.RootModuleMetadata(assembly, "RD.XML root");

            var dynamicDegreeAttribute = assemblyElement.Attribute("Dynamic");
            if (dynamicDegreeAttribute != null)
            {
                if (dynamicDegreeAttribute.Value != "Required All")
                    throw new NotSupportedException();

                foreach (TypeDesc type in ((EcmaModule)assembly).GetAllTypes())
                {
                    RootingHelpers.TryRootType(rootProvider, type, "RD.XML root");
                }
            }

            foreach (var element in assemblyElement.Elements())
            {
                switch (element.Name.LocalName)
                {
                    case "Type":
                        ProcessTypeDirective(rootProvider, assembly, element);
                        break;
                    default:
                        throw new NotSupportedException();
                }
            }
        }
Пример #2
0
        private void ProcessTypeDirective(IRootingServiceProvider rootProvider, ModuleDesc containingModule, XElement typeElement)
        {
            var typeNameAttribute = typeElement.Attribute("Name");
            if (typeNameAttribute == null)
                throw new Exception();
            string typeName = typeNameAttribute.Value;
            TypeDesc type = containingModule.GetTypeByCustomAttributeTypeName(typeName);

            var dynamicDegreeAttribute = typeElement.Attribute("Dynamic");
            if (dynamicDegreeAttribute != null)
            {
                if (dynamicDegreeAttribute.Value != "Required All")
                    throw new NotSupportedException();

                RootingHelpers.RootType(rootProvider, type, "RD.XML root");
            }

            foreach (var element in typeElement.Elements())
            {
                switch (element.Name.LocalName)
                {
                    case "Method":
                        ProcessMethodDirective(rootProvider, containingModule, type, element);
                        break;
                    default:
                        throw new NotSupportedException();
                }
            }
        }
Пример #3
0
        private void ProcessMethodDirective(IRootingServiceProvider rootProvider, ModuleDesc containingModule, TypeDesc containingType, XElement methodElement)
        {
            var methodNameAttribute = methodElement.Attribute("Name");
            if (methodNameAttribute == null)
                throw new Exception();
            string methodName = methodNameAttribute.Value;
            MethodDesc method = containingType.GetMethod(methodName, null);

            var instArgs = new List<TypeDesc>();
            foreach (var element in methodElement.Elements())
            {
                switch (element.Name.LocalName)
                {
                    case "GenericArgument":
                        string instArgName = element.Attribute("Name").Value;
                        instArgs.Add(containingModule.GetTypeByCustomAttributeTypeName(instArgName));
                        break;
                    default:
                        throw new NotSupportedException();
                }
            }

            if (instArgs.Count != method.Instantiation.Length)
                throw new Exception();

            if (instArgs.Count > 0)
            {
                var methodInst = new Instantiation(instArgs.ToArray());
                method = method.MakeInstantiatedMethod(methodInst);
            }

            RootingHelpers.TryRootMethod(rootProvider, method, "RD.XML root");
        }
Пример #4
0
        public override void GetDependenciesDueToLdToken(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
        {
            // In order for the RuntimeMethodHandle data structure to be usable at runtime, ensure the method
            // is generating metadata.
            if ((GetMetadataCategory(method) & MetadataCategory.Description) == MetadataCategory.Description)
            {
                dependencies = dependencies ?? new DependencyList();
                dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "LDTOKEN method");
            }

            // Since this is typically used for LINQ expressions, let's also make sure there's runnable code
            // for this available, unless this is ldtoken of something we can't generate code for
            // (ldtoken of an uninstantiated generic method - F# makes this).
            if (!method.IsGenericMethodDefinition)
            {
                var deps = dependencies ?? new DependencyList();
                RootingHelpers.TryRootMethod(
                    new RootingServiceProvider(
                        factory, (o, reason) => deps.Add((DependencyNodeCore <NodeFactory>)o, reason)), method, "LDTOKEN method");
                dependencies = deps;
            }
        }
Пример #5
0
        private void ProcessTypeDirective(IRootingServiceProvider rootProvider, ModuleDesc containingModule, XElement typeElement)
        {
            var typeNameAttribute = typeElement.Attribute("Name");

            if (typeNameAttribute == null)
            {
                throw new Exception("The \"Name\" attribute is required on the \"Type\" Runtime Directive.");
            }

            string   typeName = typeNameAttribute.Value;
            TypeDesc type     = containingModule.GetTypeByCustomAttributeTypeName(typeName);

            var dynamicDegreeAttribute = typeElement.Attribute("Dynamic");

            if (dynamicDegreeAttribute != null)
            {
                if (dynamicDegreeAttribute.Value != "Required All")
                {
                    throw new NotSupportedException($"\"{dynamicDegreeAttribute.Value}\" is not a supported value for the \"Dynamic\" attribute of the \"Type\" Runtime Directive. Supported values are \"Required All\".");
                }

                RootingHelpers.RootType(rootProvider, type, "RD.XML root");
            }

            foreach (var element in typeElement.Elements())
            {
                switch (element.Name.LocalName)
                {
                case "Method":
                    ProcessMethodDirective(rootProvider, containingModule, type, element);
                    break;

                default:
                    throw new NotSupportedException($"\"{element.Name.LocalName}\" is not a supported Runtime Directive.");
                }
            }
        }
Пример #6
0
        protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
        {
            TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

            // If we don't have precise field usage information, apply policy that all fields that
            // are eligible to have metadata get metadata.
            if (!_hasPreciseFieldUsageInformation)
            {
                TypeDesc typeDefinition = type.GetTypeDefinition();

                foreach (FieldDesc field in typeDefinition.GetFields())
                {
                    if ((GetMetadataCategory(field) & MetadataCategory.Description) != 0)
                    {
                        dependencies = dependencies ?? new DependencyList();
                        dependencies.Add(factory.FieldMetadata(field), "Field of a reflectable type");
                    }
                }
            }

            // If anonymous type heuristic is turned on and this is an anonymous type, make sure we have
            // method bodies for all properties. It's common to have anonymous types used with reflection
            // and it's hard to specify them in RD.XML.
            if ((_generationOptions & UsageBasedMetadataGenerationOptions.AnonymousTypeHeuristic) != 0)
            {
                if (type is MetadataType metadataType &&
                    metadataType.HasInstantiation &&
                    !metadataType.IsGenericDefinition &&
                    metadataType.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute") &&
                    metadataType.Name.Contains("AnonymousType"))
                {
                    foreach (MethodDesc method in type.GetMethods())
                    {
                        if (!method.Signature.IsStatic && method.IsSpecialName)
                        {
                            dependencies = dependencies ?? new DependencyList();
                            dependencies.Add(factory.CanonicalEntrypoint(method), "Anonymous type accessor");
                        }
                    }
                }
            }

            // If the option was specified to root types and methods in all user assemblies, do that.
            if ((_generationOptions & UsageBasedMetadataGenerationOptions.FullUserAssemblyRooting) != 0)
            {
                if (type is MetadataType metadataType &&
                    !_rootAllAssembliesExaminedModules.Contains(metadataType.Module))
                {
                    _rootAllAssembliesExaminedModules.Add(metadataType.Module);

                    if (metadataType.Module is Internal.TypeSystem.Ecma.EcmaModule ecmaModule &&
                        !FrameworkStringResourceBlockingPolicy.IsFrameworkAssembly(ecmaModule))
                    {
                        dependencies = dependencies ?? new DependencyList();
                        var rootProvider = new RootingServiceProvider(factory, dependencies.Add);
                        foreach (TypeDesc t in ecmaModule.GetAllTypes())
                        {
                            RootingHelpers.TryRootType(rootProvider, t, "RD.XML root");
                        }
                    }
                }
            }

            // If a type is marked [Serializable], make sure a couple things are also included.
            if (type.IsSerializable && !type.IsGenericDefinition)
            {
                foreach (MethodDesc method in type.GetAllMethods())
                {
                    MethodSignature signature = method.Signature;

                    if (method.IsConstructor &&
                        signature.Length == 2 &&
                        signature[0] == _serializationInfoType
                        /* && signature[1] is StreamingContext */)
                    {
                        dependencies = dependencies ?? new DependencyList();
                        dependencies.Add(factory.CanonicalEntrypoint(method), "Binary serialization");
                    }

                    // Methods with these attributes can be called during serialization
                    if (signature.Length == 1 && !signature.IsStatic && signature.ReturnType.IsVoid &&
                        (method.HasCustomAttribute("System.Runtime.Serialization", "OnSerializingAttribute") ||
                         method.HasCustomAttribute("System.Runtime.Serialization", "OnSerializedAttribute") ||
                         method.HasCustomAttribute("System.Runtime.Serialization", "OnDeserializingAttribute") ||
                         method.HasCustomAttribute("System.Runtime.Serialization", "OnDeserializedAttribute")))
                    {
                        dependencies = dependencies ?? new DependencyList();
                        dependencies.Add(factory.CanonicalEntrypoint(method), "Binary serialization");
                    }
                }
            }

            // Event sources need their special nested types
            if (type is MetadataType mdType && mdType.HasCustomAttribute("System.Diagnostics.Tracing", "EventSourceAttribute"))
            {
                AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Keywords"));
                AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Tasks"));
                AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Opcodes"));

                void AddEventSourceSpecialTypeDependencies(ref DependencyList dependencies, NodeFactory factory, MetadataType type)
                {
                    if (type != null)
                    {
                        const string reason = "Event source";
                        dependencies = dependencies ?? new DependencyList();
                        dependencies.Add(factory.TypeMetadata(type), reason);
                        foreach (FieldDesc field in type.GetFields())
                        {
                            if (field.IsLiteral)
                            {
                                dependencies.Add(factory.FieldMetadata(field), reason);
                            }
                        }
                    }
                }
            }
        }
        protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
        {
            TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");

            // If we don't have precise field usage information, apply policy that all fields that
            // are eligible to have metadata get metadata.
            if (!_hasPreciseFieldUsageInformation)
            {
                TypeDesc typeDefinition = type.GetTypeDefinition();

                foreach (FieldDesc field in typeDefinition.GetFields())
                {
                    if ((GetMetadataCategory(field) & MetadataCategory.Description) != 0)
                    {
                        dependencies = dependencies ?? new DependencyList();
                        dependencies.Add(factory.FieldMetadata(field), "Field of a reflectable type");
                    }
                }
            }

            MetadataType mdType = type as MetadataType;

            // If anonymous type heuristic is turned on and this is an anonymous type, make sure we have
            // method bodies for all properties. It's common to have anonymous types used with reflection
            // and it's hard to specify them in RD.XML.
            if ((_generationOptions & UsageBasedMetadataGenerationOptions.AnonymousTypeHeuristic) != 0)
            {
                if (mdType != null &&
                    mdType.HasInstantiation &&
                    !mdType.IsGenericDefinition &&
                    mdType.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute") &&
                    mdType.Name.Contains("AnonymousType"))
                {
                    foreach (MethodDesc method in type.GetMethods())
                    {
                        if (!method.Signature.IsStatic && method.IsSpecialName)
                        {
                            dependencies = dependencies ?? new DependencyList();
                            dependencies.Add(factory.CanonicalEntrypoint(method), "Anonymous type accessor");
                        }
                    }
                }
            }

            ModuleDesc module = mdType?.Module;

            if (module != null && !_rootEntireAssembliesExaminedModules.Contains(module))
            {
                // If the owning assembly needs to be fully compiled, do that.
                _rootEntireAssembliesExaminedModules.Add(module);

                string assemblyName = module.Assembly.GetName().Name;

                bool   fullyRoot;
                string reason;

                if (_rootEntireAssembliesModules.Contains(assemblyName))
                {
                    // If the assembly was specified as a root on the command line, root it
                    fullyRoot = true;
                    reason    = "Rooted from command line";
                }
                else if (_trimmedAssemblies.Contains(assemblyName) || IsTrimmableAssembly(module))
                {
                    // If the assembly was specified as trimmed on the command line, do not root
                    // If the assembly is marked trimmable via an attribute, do not root
                    fullyRoot = false;
                    reason    = null;
                }
                else
                {
                    // If rooting default assemblies was requested, root
                    fullyRoot = (_generationOptions & UsageBasedMetadataGenerationOptions.RootDefaultAssemblies) != 0;
                    reason    = "Assemblies rooted from command line";
                }

                if (fullyRoot)
                {
                    dependencies = dependencies ?? new DependencyList();
                    var rootProvider = new RootingServiceProvider(factory, dependencies.Add);
                    foreach (TypeDesc t in mdType.Module.GetAllTypes())
                    {
                        RootingHelpers.TryRootType(rootProvider, t, reason);
                    }
                }
            }

            // Event sources need their special nested types
            if (mdType != null && mdType.HasCustomAttribute("System.Diagnostics.Tracing", "EventSourceAttribute"))
            {
                AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Keywords"));
                AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Tasks"));
                AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Opcodes"));

                void AddEventSourceSpecialTypeDependencies(ref DependencyList dependencies, NodeFactory factory, MetadataType type)
                {
                    if (type != null)
                    {
                        const string reason = "Event source";
                        dependencies = dependencies ?? new DependencyList();
                        dependencies.Add(factory.TypeMetadata(type), reason);
                        foreach (FieldDesc field in type.GetFields())
                        {
                            if (field.IsLiteral)
                            {
                                dependencies.Add(factory.FieldMetadata(field), reason);
                            }
                        }
                    }
                }
            }
        }