Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
20a74b3
Begin Stubbing out Wasm Object Writer
adamperlin Nov 18, 2025
6657114
Merge branch 'main' of github.com:dotnet/runtime into adamperlin/wasm…
adamperlin Nov 21, 2025
8e9f6cc
crossgen2: Fill in wasm header producing code in WasmObjectWriter, fi…
adamperlin Nov 24, 2025
2992121
crossgen2: Add basic wasm object writer implementation.
adamperlin Dec 1, 2025
369d221
crossgen2: wasm object writer: remove unnecessary slice
adamperlin Dec 2, 2025
984551e
crossgen2: wasm object writer: remove class diagram
adamperlin Dec 2, 2025
152c5c9
Add license header to src/coreclr/tools/Common/Compiler/ObjectWriter/…
adamperlin Dec 2, 2025
6338698
Add license header to src/coreclr/tools/Common/Compiler/ObjectWriter/…
adamperlin Dec 2, 2025
da98f24
Update src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWrite…
adamperlin Dec 2, 2025
319d0a6
Update src/coreclr/tools/Common/Compiler/ObjectWriter/WasmNative.cs
adamperlin Dec 2, 2025
3f8bef1
Update src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWrite…
adamperlin Dec 2, 2025
b3f7b74
Update src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
adamperlin Dec 2, 2025
8ce8bd6
Update src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWrite…
adamperlin Dec 2, 2025
8b3fbee
Update src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyTo…
adamperlin Dec 2, 2025
72c063b
Update src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWrite…
adamperlin Dec 2, 2025
30e0367
Update src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
adamperlin Dec 2, 2025
ec632e4
Use collection expression for crossgen valid OS+Arch lists
adamperlin Dec 2, 2025
9c35865
Fix some copilot suggested changes
adamperlin Dec 2, 2025
4279422
Merge branch 'adamperlin/wasm-r2r-object-writer' of github.com:adampe…
adamperlin Dec 2, 2025
e7feb17
crossgen2: wasm object writer: address review feedback
adamperlin Dec 3, 2025
bf32f24
crossgen2: wasm object writer: nullable annotations for WasmResultType
adamperlin Dec 3, 2025
7852868
Merge branch 'main' of github.com:dotnet/runtime into adamperlin/wasm…
adamperlin Dec 4, 2025
30e2feb
Address additional review feedback
adamperlin Dec 4, 2025
ce53862
Address additional review feedback
adamperlin Dec 5, 2025
73ab2fa
remove unnecessary access change to GetOrCreateSection
adamperlin Dec 8, 2025
d31a01f
Merge branch 'main' of github.com:dotnet/runtime into adamperlin/wasm…
adamperlin Dec 8, 2025
0b96549
Update signatures of inherited methods in WasmObjectWriter
adamperlin Dec 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ private SortedSet<Utf8String> GetUndefinedSymbols()
return undefinedSymbolSet;
}

public void EmitObject(Stream outputFileStream, IReadOnlyCollection<DependencyNode> nodes, IObjectDumper dumper, Logger logger)
public virtual void EmitObject(Stream outputFileStream, IReadOnlyCollection<DependencyNode> nodes, IObjectDumper dumper, Logger logger)
{
// Pre-create some of the sections
GetOrCreateSection(ObjectNodeSection.TextSection);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ public readonly void WriteUtf8String(string value)
bufferWriter.Advance(size);
}

public readonly void WriteUtf8StringNoNull(string value)
{
IBufferWriter<byte> bufferWriter = _sectionData.BufferWriter;
int size = Encoding.UTF8.GetByteCount(value);
Span<byte> buffer = bufferWriter.GetSpan(size);
Encoding.UTF8.GetBytes(value, buffer);
bufferWriter.Advance(size);
}

public readonly void WritePadding(int size) => _sectionData.AppendPadding(size);

public readonly long Position => _sectionData.Length;
Expand Down
185 changes: 185 additions & 0 deletions src/coreclr/tools/Common/Compiler/ObjectWriter/WasmNative.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// 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.Diagnostics;
using System.Linq;
using System.Collections.Generic;

namespace ILCompiler.ObjectWriter
{
public enum WasmSectionType
{
Custom = 0,
Type = 1,
Import = 2,
Function = 3,
Table = 4,
Memory = 5,
Global = 6,
Export = 7,
Start = 8,
Element = 9,
Code = 10,
Data = 11,
DataCount = 12,
Tag = 13,
}

public static class PlaceholderValues
{
// Wasm function signature for (func (params i32) (result i32))
public static WasmFuncType CreateWasmFunc_i32_i32()
{
return new WasmFuncType(
paramTypes: new([WasmValueType.I32]),
returnTypes: new([WasmValueType.I32])
);
}
}

// For now, we only encode Wasm numeric value types.
// These are encoded as a single byte. However,
// not all value types can be encoded this way.
// For example, reference types (see https://webassembly.github.io/spec/core/binary/types.html#reference-types)
// require a more complex encoding.
public enum WasmValueType : byte
{
I32 = 0x7F,
I64 = 0x7E,
F32 = 0x7D,
F64 = 0x7C
}

public static class WasmValueTypeExtensions
{
public static string ToTypeString(this WasmValueType valueType)
{
return valueType switch
{
WasmValueType.I32 => "i32",
WasmValueType.I64 => "i64",
WasmValueType.F32 => "f32",
WasmValueType.F64 => "f64",
_ => "unknown",
};
}
}

#nullable enable
public readonly struct WasmResultType : IEquatable<WasmResultType>
{
private readonly WasmValueType[] _types;
public ReadOnlySpan<WasmValueType> Types => _types;

/// <summary>
/// Initializes a new instance of the WasmResultType class with the specified value types.
/// </summary>
/// <param name="types">An array of WasmValueType elements representing the types included in the result. If null, an empty array is
/// used.</param>
public WasmResultType(WasmValueType[]? types)
{
_types = types ?? Array.Empty<WasmValueType>();
}

public bool Equals(WasmResultType other) => Types.SequenceEqual(other.Types);
public override bool Equals(object? obj)
{
return obj is WasmResultType other && Equals(other);
}

public override int GetHashCode()
{
if (_types == null || _types.Length == 0)
return 0;

int code = _types[0].GetHashCode();
for (int i = 1; i < _types.Length; i++)
{
code = HashCode.Combine(code, _types[i].GetHashCode());
}

return code;
}

public int EncodeSize()
{
uint sizeLength = DwarfHelper.SizeOfULEB128((ulong)_types.Length);
return (int)(sizeLength + (uint)_types.Length);
}

public int Encode(Span<byte> buffer)
{
int sizeLength = DwarfHelper.WriteULEB128(buffer, (ulong)_types.Length);
Span<byte> rest = buffer.Slice(sizeLength);
for (int i = 0; i < _types.Length; i++)
{
rest[i] = (byte)_types[i];
}
return (int)(sizeLength + (uint)_types.Length);
}
}

public static class WasmResultTypeExtensions
{
public static string ToTypeListString(this WasmResultType result)
{
return string.Join(" ", result.Types.ToArray().Select(t => t.ToTypeString()));
}
}

public struct WasmFuncType : IEquatable<WasmFuncType>
{
private readonly WasmResultType _params;
private readonly WasmResultType _returns;

public WasmFuncType(WasmResultType paramTypes, WasmResultType returnTypes)
{
_params = paramTypes;
_returns = returnTypes;
}

public readonly int EncodeSize()
{
return 1 + _params.EncodeSize() + _returns.EncodeSize();
}

public readonly int Encode(Span<byte> buffer)
{
int totalSize = EncodeSize();
buffer[0] = 0x60; // function type indicator

int paramSize = _params.Encode(buffer.Slice(1));
int returnSize = _returns.Encode(buffer.Slice(1+paramSize));
Debug.Assert(totalSize == 1 + paramSize + returnSize);

return totalSize;
}

public bool Equals(WasmFuncType other)
{
return _params.Equals(other._params) && _returns.Equals(other._returns);
}

public override bool Equals(object? obj)
{
return obj is WasmFuncType other && Equals(other);
}

public override int GetHashCode()
{
return HashCode.Combine(_params.GetHashCode(), _returns.GetHashCode());
}

public override string ToString()
{
string paramList = _params.ToTypeListString();
string returnList = _returns.ToTypeListString();

if (string.IsNullOrEmpty(returnList))
return $"(func (param {paramList}))";
return $"(func (param {paramList}) (result {returnList}))";
}
}

}
Loading
Loading