Repository: dotnet/runtime
File: src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs (C#)

Code before:
using ILCompiler.DependencyAnalysisFramework;
using Internal.TypeSystem;

namespace ILCompiler.ObjectWriter
{
    // This is a placeholder for now. It will need to be filled in with ABI-specific signatures
    // for any method we want to emit into the Wasm module.
    public class WasmAbiContext
    {
        private Dictionary<MethodDesc, WasmFuncType> _methodSignatureMap = new();
        public WasmFuncType GetSignature(MethodDesc method)
        {
            return DummyValues.CreateWasmFunc_i32_i32();
        }
    }

    internal class WasmSection
    {
        public WasmSectionType Type { get; }
        public string Name { get; }
        public SectionData Data => _data;
        private SectionWriter? _writer;

        private SectionData _data;

        public Span<byte> Header
        {
            get
            {
                // Section header consists of:
                // 1 byte: section type
                // ULEB128: size of section
                ulong sectionSize = (ulong)_data.Length;
                var encodeLength = DwarfHelper.SizeOfULEB128(sectionSize);

                Span<byte> header = new byte[1+encodeLength];
                header[0] = (byte)Type;
                DwarfHelper.WriteULEB128(header.Slice(1), sectionSize);

                return header;
            }
        }

        public SectionWriter Writer
        {
            get
            {
                if (_writer == null)
                {
                    _writer = new SectionWriter(null, 0, _data);
                }

Review comment (suggestion):
Should this be ReadOnlySpan? I'm also not opposed to returning byte[] to make it clearer that it's allocating a temp array and returning it. You can implicitly convert the array to a span as needed elsewhere, afaik.

Code after:
using System.Text;
using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using ILCompiler.DependencyAnalysisFramework;
using Internal.Text;
using Internal.TypeSystem;

using ObjectData = ILCompiler.DependencyAnalysis.ObjectNode.ObjectData;

namespace ILCompiler.ObjectWriter
{
    /// <summary>
    /// Wasm object file format writer.
    /// </summary>
    internal sealed class WasmObjectWriter : ObjectWriter
    {
        public WasmObjectWriter(NodeFactory factory, ObjectWritingOptions options, OutputInfoBuilder outputInfoBuilder)
            : base(factory, options, outputInfoBuilder)
        {
        }

        private void EmitWasmHeader(Stream outputFileStream)
        {
            outputFileStream.Write("\0asm"u8);
            outputFileStream.Write([0x1, 0x0, 0x0, 0x0]);
        }

        // TODO: for now, we are fully overriding EmitObject. As we support more features, we should
        // see if we can re-use the base, or refactor the base method to allow for code sharing.
        public override void EmitObject(Stream outputFileStream, IReadOnlyCollection<DependencyNode> nodes, IObjectDumper dumper, Logger logger)
        {
            ArrayBuilder<WasmFuncType> methodSignatures = new();
            ArrayBuilder<string> methodNames = new();
            ArrayBuilder<ObjectData> methodBodies = new();
            foreach (DependencyNode node in nodes)
            {
                if (node is not ObjectNode)
                {
                    continue;
                }

                if (node is IMethodBodyNode methodNode)
                {
                    ObjectNode methodObject = (ObjectNode)node;
                    methodSignatures.Add(WasmAbiContext.GetSignature(methodNode.Method));
                    methodNames.Add(methodNode.GetMangledName(_nodeFactory.NameMangler));
                    methodBodies.Add(methodObject.GetData(_nodeFactory));
                    // TODO: record relocations and attached data
                }
            }