File: ILCompiler\Metadata\MetadataTransform.cs
Web Access
Project: src\src\runtime\src\coreclr\tools\aot\ILCompiler.MetadataTransform\ILCompiler.MetadataTransform.csproj (ILCompiler.MetadataTransform)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using Internal.Metadata.NativeFormat.Writer;

using Cts = Internal.TypeSystem;

namespace ILCompiler.Metadata
{
    /// <summary>
    /// Transforms type system object model into metadata writer object model that is suitable
    /// for binary serialization into a metadata blob using the <see cref="MetadataWriter"/> class.
    /// </summary>
    public abstract class MetadataTransform
    {
        /// <summary>
        /// Transforms the specified modules using the specified metadata generation
        /// policy. Policy is required to be a struct for performance reasons.
        /// </summary>
        /// <remarks>
        /// The list of <paramref name="modules"/> is required to be transitively complete with respect to
        /// <paramref name="policy"/>: whenever there's a reference from the object graph to a type or member defined in a
        /// module that was not included in the <paramref name="modules"/> enumeration, the
        /// <see cref="IMetadataPolicy.GeneratesMetadata(Cts.MetadataType)"/>
        /// and <see cref="IMetadataPolicy.GeneratesMetadata(Cts.MethodDesc)"/> are required to return false.
        /// </remarks>
        public static MetadataTransformResult<TPolicy> Run<TPolicy>(TPolicy policy, IEnumerable<Cts.ModuleDesc> modules)
            where TPolicy : struct, IMetadataPolicy
        {
            // TODO: Make this multithreaded. The high level plan is:
            // - make EntityMap thread safe
            // - change the way TypeDefs are hooked up into namespaces and scopes
            // - queue up calls to the various Initialize* methods on a threadpool

            var transform = new Transform<TPolicy>(policy);

            foreach (var module in modules)
            {
                foreach (var type in module.GetAllTypes())
                {
                    if (policy.GeneratesMetadata(type) && !policy.IsBlocked(type))
                    {
                        transform.HandleType(type);
                    }
                }
            }

            return new MetadataTransformResult<TPolicy>(transform);
        }

        /// <summary>
        /// Retrieves an existing <see cref="TypeDefinition"/>, <see cref="TypeReference"/>,
        /// or <see cref="TypeSpecification"/> record representing specified type in the metadata writer object
        /// model, or creates a new one.
        /// </summary>
        public abstract MetadataRecord HandleType(Cts.TypeDesc type);

        /// <summary>
        /// Retrieves an existing <see cref="QualifiedMethod"/>, <see cref="MemberReference"/>, or <see cref="MethodInstantiation"/>
        /// record representing specified method in the metadata writer object model, or creates a new one.
        /// </summary>
        public abstract MetadataRecord HandleQualifiedMethod(Cts.MethodDesc method);

        /// <summary>
        /// Retrieves an existing <see cref="QualifiedField"> or a <see cref="MemberReference"/> record
        /// representing specified field in the metadata writer object model, or creates a new one.
        /// </summary>
        public abstract MetadataRecord HandleQualifiedField(Cts.FieldDesc field);

        /// <summary>
        /// Retrieves an existing <see cref="MethodSignature"/> record representing the specified signature
        /// in the metadata writer object model, or creates a new one.
        /// </summary>
        public abstract MethodSignature HandleMethodSignature(Cts.MethodSignature signature);
    }
}