File: Compiler\DependencyAnalysis\CallingConventionConverterKey.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.Text;
using Internal.TypeSystem;

namespace ILCompiler.DependencyAnalysis
{
    public static class MethodSignatureExtensions
    {
        public static void AppendName(this MethodSignature signature, StringBuilder nameBuilder, UniqueTypeNameFormatter typeNameFormatter)
        {
            if (signature.GenericParameterCount > 0)
            {
                nameBuilder.Append("GenParams:");
                nameBuilder.Append(signature.GenericParameterCount);
                nameBuilder.Append(' ');
            }

            if (signature.IsStatic)
                nameBuilder.Append("Static ");

            typeNameFormatter.AppendName(nameBuilder, signature.ReturnType);
            nameBuilder.Append('(');
            for (int i = 0; i < signature.Length; i++)
            {
                if (i != 0)
                    nameBuilder.Append(',');
                typeNameFormatter.AppendName(nameBuilder, signature[i]);
            }
            nameBuilder.Append(')');
        }

        public static string GetName(this MethodSignature signature)
        {
            StringBuilder nameBuilder = new StringBuilder();
            signature.AppendName(nameBuilder, UniqueTypeNameFormatter.Instance);
            return nameBuilder.ToString();
        }
    }

    public class UniqueTypeNameFormatter : TypeNameFormatter
    {
        public static UniqueTypeNameFormatter Instance { get; } = new UniqueTypeNameFormatter();

        public override void AppendName(StringBuilder sb, PointerType type)
        {
            AppendName(sb, type.ParameterType);
            sb.Append('*');
        }

        public override void AppendName(StringBuilder sb, GenericParameterDesc type)
        {
            string prefix = type.Kind == GenericParameterKind.Type ? "!" : "!!";
            sb.Append(prefix);
            sb.Append(type.Name);
        }

        public override void AppendName(StringBuilder sb, SignatureTypeVariable type)
        {
            sb.Append('!');
            sb.Append(type.Index.ToStringInvariant());
        }

        public override void AppendName(StringBuilder sb, SignatureMethodVariable type)
        {
            sb.Append("!!");
            sb.Append(type.Index.ToStringInvariant());
        }

        public override void AppendName(StringBuilder sb, FunctionPointerType type)
        {
            MethodSignature signature = type.Signature;

            AppendName(sb, signature.ReturnType);

            sb.Append(" (");
            for (int i = 0; i < signature.Length; i++)
            {
                if (i > 0)
                    sb.Append(", ");
                AppendName(sb, signature[i]);
            }

            // TODO: Append '...' for vararg methods

            sb.Append(')');
        }

        public override void AppendName(StringBuilder sb, ByRefType type)
        {
            AppendName(sb, type.ParameterType);
            sb.Append(" ByRef");
        }

        public override void AppendName(StringBuilder sb, ArrayType type)
        {
            AppendName(sb, type.ElementType);
            sb.Append('[');

            if (type.Rank == 1 && type.IsMdArray)
                sb.Append('*');
            sb.Append(',', type.Rank - 1);

            sb.Append(']');
        }

        protected override void AppendNameForInstantiatedType(StringBuilder sb, DefType type)
        {
            AppendName(sb, type.GetTypeDefinition());
            sb.Append('<');

            for (int i = 0; i < type.Instantiation.Length; i++)
            {
                if (i > 0)
                    sb.Append(", ");
                AppendName(sb, type.Instantiation[i]);
            }

            sb.Append('>');
        }

        protected override void AppendNameForNamespaceType(StringBuilder sb, DefType type)
        {
            string ns = GetTypeNamespace(type);
            if (ns.Length > 0)
            {
                AppendEscapedIdentifier(sb, ns);
                sb.Append('.');
            }
            AppendEscapedIdentifier(sb, GetTypeName(type));

            if (type is MetadataType)
            {
                IAssemblyDesc homeAssembly = ((MetadataType)type).Module as IAssemblyDesc;
                AppendAssemblyName(sb, homeAssembly);
            }
        }

        private static void AppendAssemblyName(StringBuilder sb, IAssemblyDesc assembly)
        {
            if (assembly == null)
                return;

            sb.Append(',');
            AppendEscapedIdentifier(sb, assembly.GetName().Name);
        }

        protected override void AppendNameForNestedType(StringBuilder sb, DefType nestedType, DefType containingType)
        {
            AppendName(sb, containingType);

            sb.Append('+');

            string ns = GetTypeNamespace(nestedType);
            if (ns.Length > 0)
            {
                AppendEscapedIdentifier(sb, ns);
                sb.Append('.');
            }
            AppendEscapedIdentifier(sb, GetTypeName(nestedType));
        }

        private static string GetTypeName(DefType type)
        {
            return type.GetName();
        }

        private static string GetTypeNamespace(DefType type)
        {
            return type.GetNamespace();
        }

        private static char[] s_escapedChars = new char[] { ',', '=', '"', ']', '[', '*', '&', '+', '\\' };
        private static void AppendEscapedIdentifier(StringBuilder sb, string identifier)
        {
            if (identifier.IndexOfAny(s_escapedChars) < 0)
            {
                string escapedIdentifier = identifier;
                foreach (char escapedChar in s_escapedChars)
                {
                    string escapedCharString = new string(escapedChar, 1);
                    escapedIdentifier = escapedIdentifier.Replace(escapedCharString, "\\" + escapedCharString);
                }
                sb.Append(escapedIdentifier);
            }
            else
            {
                sb.Append(identifier);
            }
        }
    }
}