File: Compiler\DependencyAnalysis\ReadyToRun\InjectStringThunksSignature.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.Collections.Generic;
using System.Text;

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

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
    /// <summary>
    /// Signature node for the READYTORUN_FIXUP_InjectStringThunks fixup.
    /// Encodes a series of (null-terminated UTF8 string, 4-byte RVA/table index) pairs,
    /// terminated by an empty string (single 0x00 byte with no trailing RVA).
    /// </summary>
    internal class InjectStringThunksSignature : Signature
    {
        public InjectStringThunksSignature()
        {
        }

        public override int ClassCode => 1493287651;

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

            if (!relocsOnly)
            {
                List<StringDiscoverableAssemblyStubNode> stubs = factory.GetStringDiscoverableStubs();
                stubs.Sort((a, b) => string.CompareOrdinal(a.LookupString, b.LookupString));

                foreach (StringDiscoverableAssemblyStubNode stub in stubs)
                {
                    // Emit the null-terminated UTF8 string
                    byte[] stringBytes = Encoding.UTF8.GetBytes(stub.LookupString);
                    builder.EmitBytes(stringBytes);
                    builder.EmitByte(0); // null terminator

                    // Emit a 4-byte relocation to the stub code.
                    // On WASM, this is a table index; on other platforms, an RVA.
                    RelocType relocType = factory.Target.Architecture == TargetArchitecture.Wasm32
                        ? RelocType.WASM_TABLE_INDEX_REL_I32
                        : RelocType.IMAGE_REL_BASED_ADDR32NB;
                    builder.EmitReloc(stub, relocType, delta: factory.Target.CodeDelta);
                }
            }

            // Terminal empty string (no trailing RVA)
            builder.EmitByte(0);

            return builder.ToObjectData();
        }

        public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(nameMangler.CompilationUnitPrefix);
            sb.Append("InjectStringThunks"u8);
        }

        public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
        {
            // There should only be one instance of this signature per compilation
            return 0;
        }
    }
}