File: Compiler\DependencyAnalysis\DataflowAnalyzedMethodNode.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;
using System.Collections.Generic;
using System.Diagnostics;

using Internal.TypeSystem;
using Internal.IL;

using ILCompiler.Dataflow;
using ILCompiler.DependencyAnalysisFramework;

namespace ILCompiler.DependencyAnalysis
{
    /// <summary>
    /// Node that performs dataflow analysis to find dynamic dependencies (e.g. reflection use) of the given method.
    /// </summary>
    public class DataflowAnalyzedMethodNode : DependencyNodeCore<NodeFactory>
    {
        private readonly MethodIL _methodIL;
        private List<(MethodDesc OwningMethod, INodeWithRuntimeDeterminedDependencies Dependency)> _runtimeDependencies;

        public DataflowAnalyzedMethodNode(MethodIL methodIL)
        {
            Debug.Assert(methodIL.OwningMethod.IsTypicalMethodDefinition);
            Debug.Assert(!CompilerGeneratedState.IsNestedFunctionOrStateMachineMember(methodIL.OwningMethod));
            _methodIL = methodIL;
        }

        public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
        {
            var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;
            try
            {
                return Dataflow.ReflectionMethodBodyScanner.ScanAndProcessReturnValue(factory, mdManager.FlowAnnotations, mdManager.Logger, _methodIL, out _runtimeDependencies);
            }
            catch (TypeSystemException)
            {
                // Something wrong with the input - missing references, etc.
                // The method body likely won't compile either, so we don't care.
                _runtimeDependencies = new List<(MethodDesc, INodeWithRuntimeDeterminedDependencies)>();
                return Array.Empty<DependencyListEntry>();
            }
        }

        public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory)
        {
            // Look for any generic specialization of this method or its compiler-generated callees (local methods, lambdas).
            // If any are found, specialize the dataflow dependencies that originated from that method.
            for (int i = firstNode; i < markedNodes.Count; i++)
            {
                if (markedNodes[i] is not IMethodBodyNode methodBody)
                    continue;

                MethodDesc method = methodBody.Method;
                MethodDesc typicalMethod = method.GetTypicalMethodDefinition();

                // Instantiate runtime dependencies whose owning method matches this method body's typical definition
                foreach (var n in _runtimeDependencies)
                {
                    if (n.OwningMethod != typicalMethod)
                        continue;

                    foreach (var d in n.Dependency.InstantiateDependencies(factory, method.OwningType.Instantiation, method.Instantiation, isConcreteInstantiation: !method.IsSharedByGenericInstantiations))
                    {
                        yield return new CombinedDependencyListEntry(d.Node, null, d.Reason);
                    }
                }
            }
        }

        protected override string GetName(NodeFactory factory)
        {
            return "Dataflow analysis for " + _methodIL.OwningMethod.ToString();
        }

        public override bool InterestingForDynamicDependencyAnalysis => false;
        public override bool HasDynamicDependencies => _runtimeDependencies.Count > 0;
        public override bool HasConditionalStaticDependencies => false;
        public override bool StaticDependenciesAreComputed => true;
        public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null;
    }
}