File: Compiler\DependencyAnalysis\ReadyToRun\VirtualResolutionFixupSignature.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 System;
using System.Diagnostics;

using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
using Internal.TypeSystem.Interop;
using Internal.ReadyToRunConstants;
using Internal.CorConstants;
using Internal.JitInterface;

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
    public class VirtualResolutionFixupSignature : Signature, IEquatable<VirtualResolutionFixupSignature>
    {
        private readonly ReadyToRunFixupKind _fixupKind;

        private readonly MethodWithToken _declMethod;
        private readonly TypeDesc _implType;
        private readonly MethodWithToken _implMethod;

        public VirtualResolutionFixupSignature(ReadyToRunFixupKind fixupKind, MethodWithToken declMethod, TypeDesc implType, MethodWithToken implMethod)
        {
            _fixupKind = fixupKind;
            _declMethod = declMethod;
            _implType = implType;
            _implMethod = implMethod;

            // Ensure types in signature are loadable and resolvable, otherwise we'll fail later while emitting the signature
            CompilerTypeSystemContext compilerContext = (CompilerTypeSystemContext)declMethod.Method.Context;
            compilerContext.EnsureLoadableMethod(declMethod.Method);
            compilerContext.EnsureLoadableType(implType);
            if (implMethod != null)
                compilerContext.EnsureLoadableMethod(implMethod.Method);
        }

        public override int ClassCode => 1092747257;

        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataSignatureBuilder dataBuilder = new ObjectDataSignatureBuilder(factory, relocsOnly);

            if (!relocsOnly)
            {
                dataBuilder.AddSymbol(this);

                SignatureContext innerContext = dataBuilder.EmitFixup(factory, _fixupKind, _declMethod.Token.Module, factory.SignatureContext);
                dataBuilder.EmitUInt((uint)(_implMethod != null ? ReadyToRunVirtualFunctionOverrideFlags.VirtualFunctionOverridden : ReadyToRunVirtualFunctionOverrideFlags.None));
                dataBuilder.EmitMethodSignature(_declMethod, enforceDefEncoding: false, enforceOwningType: false, innerContext, isInstantiatingStub: false);
                dataBuilder.EmitTypeSignature(_implType, innerContext);
                if (_implMethod != null)
                    dataBuilder.EmitMethodSignature(_implMethod, enforceDefEncoding: false, enforceOwningType: false, innerContext, isInstantiatingStub: false);
            }

            return dataBuilder.ToObjectData();
        }

        public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(nameMangler.CompilationUnitPrefix);
            sb.Append($@"VirtualResolutionFixupSignature({_fixupKind.ToString()}): ");
            _declMethod.AppendMangledName(nameMangler, sb);
            sb.Append(":"u8);
            sb.Append(nameMangler.GetMangledTypeName(_implType));
            sb.Append(":"u8);
            if (_implMethod == null)
                sb.Append("(null)"u8);
            else
                _implMethod.AppendMangledName(nameMangler, sb);
        }

        public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
        {
            VirtualResolutionFixupSignature otherNode = (VirtualResolutionFixupSignature)other;
            int result = ((int)_fixupKind).CompareTo((int)otherNode._fixupKind);
            if (result != 0)
                return result;

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

            result = _declMethod.CompareTo(otherNode._declMethod, comparer);
            if (result != 0)
                return result;

            // Handle null _implMethod scenario
            if (_implMethod == otherNode._implMethod)
                return 0;

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

        public override string ToString()
        {
            return $"VirtualResolutionFixupSignature {_fixupKind} {_declMethod} {_implType} {_implMethod}";
        }

        public bool Equals(VirtualResolutionFixupSignature other) => object.ReferenceEquals(other, this);
    }
}