File: Compiler\DependencyAnalysis\DataflowAnalyzedTypeDefinitionNode.cs
Web Access
Project: src\src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler)
// 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 System.Diagnostics;

using Internal.TypeSystem;

using ILCompiler.Dataflow;
using ILCompiler.DependencyAnalysisFramework;
using ILCompiler.Logging;

using ILLink.Shared;
using ILLink.Shared.TrimAnalysis;

namespace ILCompiler.DependencyAnalysis
{
    public class DataflowAnalyzedTypeDefinitionNode : DependencyNodeCore<NodeFactory>
    {
        private readonly TypeDesc _typeDefinition;

        public DataflowAnalyzedTypeDefinitionNode(TypeDesc typeDefinition)
        {
            Debug.Assert(typeDefinition.IsTypeDefinition);
            _typeDefinition = typeDefinition;
        }

        public static void GetDependencies(ref DependencyList dependencies, NodeFactory factory, FlowAnnotations flowAnnotations, TypeDesc type)
        {
            bool needsDataflowAnalysis = false;

            type = type.GetTypeDefinition();

            try
            {
                if (type.HasBaseType)
                {
                    if (type.BaseType.DoesTypeRequire(DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out _) &&
                        !type.DoesTypeRequire(DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out _))
                        needsDataflowAnalysis = true;

                    needsDataflowAnalysis |= GenericArgumentDataFlow.RequiresGenericArgumentDataFlow(flowAnnotations, type.BaseType);
                }

                if (type is MetadataType metadataType)
                {
                    foreach (var interfaceType in metadataType.ExplicitlyImplementedInterfaces)
                    {
                        needsDataflowAnalysis |= GenericArgumentDataFlow.RequiresGenericArgumentDataFlow(flowAnnotations, interfaceType);
                    }
                }
            }
            catch (TypeSystemException)
            {
                // Wasn't able to do dataflow because of missing references or something like that.
                // This likely won't compile either, so we don't care about missing dependencies.
            }

            if (needsDataflowAnalysis)
            {
                dependencies ??= new DependencyList();
                dependencies.Add(factory.DataflowAnalyzedTypeDefinition(type), "Dataflow for type definition");
            }
        }

        public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
        {
            DependencyList dependencies = null;

            if (_typeDefinition is MetadataType metadataType)
            {
                foreach (var interfaceType in metadataType.ExplicitlyImplementedInterfaces)
                {
                    GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_typeDefinition), interfaceType, _typeDefinition);
                }
            }

            return dependencies;
        }

        protected override string GetName(NodeFactory factory)
        {
            return "Dataflow analysis for type definition " + _typeDefinition.ToString();
        }

        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 context) => null;
        public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
    }
}