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

using Internal.TypeSystem;
using Internal.JitInterface;
using Internal.Text;
using Internal.ReadyToRunConstants;

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
    public class DelegateCtorSignature : Signature
    {
        private readonly TypeDesc _delegateType;

        private readonly IMethodNode _targetMethod;

        private readonly MethodWithToken _methodToken;

        public DelegateCtorSignature(
            TypeDesc delegateType,
            IMethodNode targetMethod,
            MethodWithToken methodToken)
        {
            _delegateType = delegateType;
            _targetMethod = targetMethod;
            _methodToken = methodToken;

            // Ensure types in signature are loadable and resolvable, otherwise we'll fail later while emitting the signature
            CompilerTypeSystemContext compilerContext = (CompilerTypeSystemContext)delegateType.Context;
            compilerContext.EnsureLoadableType(delegateType);
            compilerContext.EnsureLoadableMethod(targetMethod.Method);
        }

        public override int ClassCode => 99885741;

        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataSignatureBuilder builder = new ObjectDataSignatureBuilder(factory, relocsOnly);
            builder.AddSymbol(this);

            if (!relocsOnly)
            {
                SignatureContext innerContext = builder.EmitFixup(factory, ReadyToRunFixupKind.DelegateCtor, _methodToken.Token.Module, factory.SignatureContext);

                bool needsInstantiatingStub = _targetMethod.Method.HasInstantiation;
                if (_targetMethod.Method.IsVirtual && _targetMethod.Method.Signature.IsStatic)
                {
                    // For static virtual methods, we always require an instantiating stub as the method may resolve to a canonical representation
                    // at runtime without us being able to detect that at compile time.
                    needsInstantiatingStub |= (_targetMethod.Method.OwningType.HasInstantiation || _methodToken.ConstrainedType != null);
                }

                builder.EmitMethodSignature(
                    _methodToken,
                    enforceDefEncoding: false,
                    enforceOwningType: false,
                    innerContext,
                    isInstantiatingStub: needsInstantiatingStub);

                builder.EmitTypeSignature(_delegateType, innerContext);
            }

            return builder.ToObjectData();
        }

        protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
        {
            return new DependencyList(
                new DependencyListEntry[]
                {
                    new DependencyListEntry(_targetMethod, "Delegate target method")
                }
            );
        }

        public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(nameMangler.CompilationUnitPrefix);
            sb.Append($@"DelegateCtor(");
            sb.Append(nameMangler.GetMangledTypeName(_delegateType));
            sb.Append(" -> "u8);
            _targetMethod.AppendMangledName(nameMangler, sb);
            sb.Append("; "u8);
            sb.Append(_methodToken.ToString());
            sb.Append(")"u8);
        }

        public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
        {
            DelegateCtorSignature otherNode = (DelegateCtorSignature)other;
            int result = comparer.Compare(_delegateType, otherNode._delegateType);
            if (result != 0)
                return result;

            result = comparer.Compare(_targetMethod, otherNode._targetMethod);
            if (result != 0)
                return result;

            return _methodToken.CompareTo(otherNode._methodToken, comparer);
        }
    }
}