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

Code before:
                    methodSignatures.Add(_wasmAbiContext.GetSignature(methodNode.Method));
                    methodBodies.Add(methodNode);
                    // TODO: record relocations and attached data
                }
            }

            var uniqueSignatures = methodSignatures.ToArray().Distinct();
            var signatureMap = uniqueSignatures.Select((sig, i) => (sig, i)).ToDictionary();

            EmitWasmHeader(outputFileStream);
            EmitSection(() => WriteTypeSection(uniqueSignatures, logger), outputFileStream, logger);
            EmitSection(() => WriteFunctionSection(methodSignatures.ToArray(), signatureMap, logger), outputFileStream, logger);
            EmitSection(() => WriteExportSection(methodBodies.ToArray(), methodSignatures.ToArray(), signatureMap, logger), outputFileStream, logger);
            EmitSection(() => WriteCodeSection(methodBodies.ToArray(), logger), outputFileStream, logger);
        }

        private WasmSection WriteExportSection(IReadOnlyList<IMethodBodyNode> methodNodes, IReadOnlyList<WasmFuncType> methodSignatures,
            Dictionary<WasmFuncType, int> signatureMap, Logger logger)
        {
            WasmSection exportSection = new WasmSection(WasmSectionType.Export, new SectionData(), "export");
            SectionWriter writer = exportSection.Writer;
            // Write the number of exports
            writer.WriteULEB128((ulong)methodNodes.Count);
            for (int i = 0; i < methodNodes.Count; i++)
            {
                var methodNode = methodNodes[i];
                var methodSignature = methodSignatures[i];
                string exportName = methodNode.GetMangledName(_nodeFactory.NameMangler);

                var length = Encoding.UTF8.GetByteCount(exportName);
                writer.WriteULEB128((ulong)length);
                writer.WriteUtf8StringNoNull(exportName);
                writer.WriteByte(0x00); // export kind: function
                writer.WriteULEB128((ulong)i);
                if (logger.IsVerbose)
                {
                    logger.LogMessage($"Emitting export: {exportName} for function index {i}");
                }
            }

            return exportSection;
        }

        private WasmSection WriteCodeSection(IReadOnlyCollection<IMethodBodyNode> methodBodies, Logger logger)
        {
            WasmSection codeSection = new WasmSection(WasmSectionType.Code, new SectionData(), "code");

            SectionWriter writer = codeSection.Writer;
            // Write the number of functions
            writer.WriteULEB128((ulong)methodBodies.Count);
            foreach (IMethodBodyNode methodBody in methodBodies)

Review comment (performance):
Nit: (here and elsewhere) we have some guidelines for `var` that optimize for code reading: https://github.com/dotnet/runtime/blob/b54c5d53ca8208e9bb5c95a2fbbd27f30df09b9d/docs/coding-guidelines/coding-style.md?plain=1#L22-L23. So these `var`s need to be changed.

(I personally just avoid using `var` everywhere in this project, since it is a simpler rule to follow)

Code after:
                ObjectData methodBody = methodBodies[i];
                writer.WriteULEB128((ulong)methodBody.Data.Length);
                writer.EmitData(methodBody.Data);
            }

            return codeSection;
        }

        private WasmSection WriteTypeSection(IEnumerable<WasmFuncType> functionSignatures, Logger logger)
        {
            SectionData sectionData = new();
            WasmSection typeSection = new WasmSection(WasmSectionType.Type, sectionData, "type");
            SectionWriter writer = typeSection.Writer;

            // Write the number of types
            writer.WriteULEB128((ulong)functionSignatures.Count());

            IBufferWriter<byte> buffer = sectionData.BufferWriter;
            foreach (WasmFuncType signature in functionSignatures)
            {
                if (logger.IsVerbose)
                {
                    logger.LogMessage($"Emitting function signature: {signature}");
                }

                int signatureSize = signature.EncodeSize();
                signature.Encode(buffer.GetSpan(signatureSize));
                buffer.Advance(signatureSize);
            }

            return typeSection;
        }

        private WasmSection WriteFunctionSection(ArrayBuilder<WasmFuncType> allFunctionSignatures, Dictionary<WasmFuncType, int> signatureMap, Logger logger)
        {
            WasmSection functionSection = new WasmSection(WasmSectionType.Function, new SectionData(), "function");
            SectionWriter writer = functionSection.Writer;
            // Write the number of functions
            writer.WriteULEB128((ulong)allFunctionSignatures.Count);
            for (int i = 0; i < allFunctionSignatures.Count; i++)
            {
                WasmFuncType signature = allFunctionSignatures[i];
                writer.WriteULEB128((ulong)signatureMap[signature]);
            }
            return functionSection;
        }

        private void EmitSection(Func<WasmSection> writeFunc, Stream outputFileStream, Logger logger)
        {
            WasmSection section = writeFunc();
            Span<byte> headerBuffer = stackalloc byte[section.HeaderSize];