From d720381ec70602fab8639dc9fb5c242a5bed335b Mon Sep 17 00:00:00 2001 From: adamperlin Date: Thu, 7 May 2026 16:37:29 -0700 Subject: [PATCH 1/2] Add length prefix to crossgen generated Wasm in WasmEmitter; Remove now-unused SectionWriter.Params --- .../Target_Wasm/WasmEmitter.cs | 9 +++- .../Compiler/ObjectWriter/ObjectWriter.cs | 23 +--------- .../Compiler/ObjectWriter/SectionWriter.cs | 45 +------------------ .../Compiler/ObjectWriter/WasmInstructions.cs | 4 +- .../Compiler/ObjectWriter/WasmObjectWriter.cs | 9 ---- 5 files changed, 13 insertions(+), 77 deletions(-) diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs index 23d6f76bde1e68..ee36d72cb71cab 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs @@ -25,9 +25,14 @@ public struct WasmEmitter(NodeFactory factory, bool relocsOnly) public ObjectNode.ObjectData Encode(ISymbolDefinitionNode symbolDefinitionNode) { #if READYTORUN - byte[] encodedThunk = new byte[FunctionBody.EncodeSize()]; + int bodySize = FunctionBody.EncodeSize(); + int sizePrefixLength = (int)DwarfHelper.SizeOfULEB128((ulong)bodySize); + byte[] encodedThunk = new byte[bodySize + sizePrefixLength]; + + DwarfHelper.WriteULEB128(encodedThunk, (ulong)bodySize); + FunctionBody.Encode(encodedThunk.AsSpan(sizePrefixLength)); + Relocation[] relocs = new Relocation[FunctionBody.EncodeRelocationCount()]; - FunctionBody.Encode(encodedThunk.AsSpan()); FunctionBody.EncodeRelocations(relocs.AsSpan()); return new ObjectNode.ObjectData(encodedThunk, relocs, 1, new ISymbolDefinitionNode[] { symbolDefinitionNode }); diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs index d1d9c4e50a5209..5eb2018c7cf947 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs @@ -84,20 +84,6 @@ private protected ObjectWriter(NodeFactory factory, ObjectWritingOptions options private protected SectionWriter GetOrCreateSection(ObjectNodeSection section) => GetOrCreateSection(section, default, default); - private readonly SectionWriter.Params _defaultParams = new SectionWriter.Params - { - LengthEncodeFormat = LengthEncodeFormat.None - }; - - /// - /// Some architectures may require section-specific params for the writer. For example, on Wasm, - /// certain sections require length prefixes before each object entry which the section writer does support, - /// but this has to be indicated by a particular implementation. - /// - /// - /// - private protected virtual SectionWriter.Params WriterParams(ObjectNodeSection section) => _defaultParams; - /// /// Get or creates an object file section. /// @@ -139,8 +125,7 @@ private protected SectionWriter GetOrCreateSection(ObjectNodeSection section, Ut return new SectionWriter( this, sectionIndex, - sectionData, - WriterParams(section)); + sectionData); } private protected bool ShouldShareSymbol(ObjectNode node) @@ -482,13 +467,9 @@ public virtual void EmitObject(Stream outputFileStream, IReadOnlyCollection Buffer => _sectionData.BufferWriter; - public struct Params - { - public LengthEncodeFormat LengthEncodeFormat; - } - - public bool HasLengthPrefix => _params.LengthEncodeFormat != LengthEncodeFormat.None; - internal SectionWriter( ObjectWriter objectWriter, int sectionIndex, - SectionData sectionData, - Params ps) + SectionData sectionData) { _objectWriter = objectWriter; SectionIndex = sectionIndex; _sectionData = sectionData; - _params = ps; - } - - public readonly void EmitLengthPrefix(ulong length) - { - switch (_params.LengthEncodeFormat) - { - case LengthEncodeFormat.ULEB128: - WriteULEB128(length); - break; - case LengthEncodeFormat.None: - break; - default: - throw new InvalidOperationException("Length prefix encoding not specified"); - } - } - - public readonly uint LengthPrefixSize(int length) - { - switch (_params.LengthEncodeFormat) - { - case LengthEncodeFormat.ULEB128: - return DwarfHelper.SizeOfULEB128((ulong)length); - default: - return 0; - } } public readonly void EmitData(ReadOnlyMemory data) { - EmitLengthPrefix((ulong)data.Length); _sectionData.AppendData(data); } diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs index 813b439c2ecac3..1bd988f522bc7a 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs @@ -104,8 +104,10 @@ public int EncodeRelocationCount() public int EncodeRelocations(Span buffer) { + uint bodySize = (uint)BodyContentSize(); + int bodySizePrefixLength = (int)DwarfHelper.SizeOfULEB128(bodySize); int relocsEncoded = _body.EncodeRelocations(buffer); - WasmExpr.OffsetRelocationsByOffset(buffer.Slice(0, relocsEncoded), _locals.Length); + WasmExpr.OffsetRelocationsByOffset(buffer.Slice(0, relocsEncoded), bodySizePrefixLength + _locals.Length); return relocsEncoded; } } diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs index b6fabef169fa91..1bdc61409cf33e 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs @@ -360,7 +360,6 @@ private void InsertWasmStub(Utf8String name, WasmFunctionBody body) body.Encode(data); // We must emit the length prefix explicitly - Debug.Assert(!codeWriter.HasLengthPrefix); codeWriter.WriteULEB128((ulong)codeSize); codeWriter.EmitData(data); _uniqueSymbols.Add(name.ToString(), _methodCount); @@ -480,14 +479,6 @@ private protected override ObjectNodeSection GetEmitSection(ObjectNodeSection se return section; } - private protected override SectionWriter.Params WriterParams(ObjectNodeSection section) - { - return new SectionWriter.Params - { - LengthEncodeFormat = LengthEncodeFormat.None - }; - } - private protected override void CreateSection(ObjectNodeSection section, Utf8String comdatName, Utf8String symbolName, int sectionIndex, Stream sectionStream) { WasmSectionType sectionType = GetWasmSectionType(section); From 7378ea82a3149ee05ac9ac8b64a7eb1393b3b988 Mon Sep 17 00:00:00 2001 From: adamperlin Date: Thu, 7 May 2026 18:22:02 -0700 Subject: [PATCH 2/2] crossgen2: Emit length prefix in WasmFunctionBody.Encode() --- .../DependencyAnalysis/Target_Wasm/WasmEmitter.cs | 8 ++------ .../Common/Compiler/ObjectWriter/WasmInstructions.cs | 10 +++++++--- .../Common/Compiler/ObjectWriter/WasmObjectWriter.cs | 2 -- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs index ee36d72cb71cab..900b7a089812e4 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_Wasm/WasmEmitter.cs @@ -25,12 +25,8 @@ public struct WasmEmitter(NodeFactory factory, bool relocsOnly) public ObjectNode.ObjectData Encode(ISymbolDefinitionNode symbolDefinitionNode) { #if READYTORUN - int bodySize = FunctionBody.EncodeSize(); - int sizePrefixLength = (int)DwarfHelper.SizeOfULEB128((ulong)bodySize); - byte[] encodedThunk = new byte[bodySize + sizePrefixLength]; - - DwarfHelper.WriteULEB128(encodedThunk, (ulong)bodySize); - FunctionBody.Encode(encodedThunk.AsSpan(sizePrefixLength)); + byte[] encodedThunk = new byte[FunctionBody.EncodeSize()]; + FunctionBody.Encode(encodedThunk); Relocation[] relocs = new Relocation[FunctionBody.EncodeRelocationCount()]; FunctionBody.EncodeRelocations(relocs.AsSpan()); diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs index 1bd988f522bc7a..57a060714d44d8 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmInstructions.cs @@ -85,13 +85,17 @@ private int BodyContentSize() public int EncodeSize() { - return BodyContentSize(); + int bodySize = BodyContentSize(); + int sizePrefixLength = (int)DwarfHelper.SizeOfULEB128((ulong)bodySize); + return sizePrefixLength + bodySize; } public int Encode(Span buffer) { - _locals.CopyTo(buffer); - int pos = _locals.Length; + int contentSize = BodyContentSize(); + int pos = DwarfHelper.WriteULEB128(buffer, (ulong)contentSize); + _locals.CopyTo(buffer.Slice(pos)); + pos += _locals.Length; pos += _body.Encode(buffer.Slice(pos)); return pos; diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs index 1bdc61409cf33e..c65ef39b255993 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs @@ -359,8 +359,6 @@ private void InsertWasmStub(Utf8String name, WasmFunctionBody body) byte[] data = new byte[codeSize]; body.Encode(data); - // We must emit the length prefix explicitly - codeWriter.WriteULEB128((ulong)codeSize); codeWriter.EmitData(data); _uniqueSymbols.Add(name.ToString(), _methodCount); _methodCount++;