diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-06-21 21:27:31 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-06-21 21:27:31 +0100 |
| commit | 126533bf5210d1bf311628a18af6e46f765c922e (patch) | |
| tree | 6114298e13d96d391564b5eab2dc004e2dfd87d7 /src/main/java | |
| parent | b92d46a9fc641afca93571e1b398b968816b1b57 (diff) | |
Add binary encoding of WASM type section
Diffstat (limited to 'src/main/java')
5 files changed, 108 insertions, 26 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/BinaryWriter.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/BinaryWriter.java index d5600a5c..ade47714 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/BinaryWriter.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/BinaryWriter.java @@ -15,12 +15,6 @@ public class BinaryWriter { buffer.put(bytes, 0, bytes.length); } - public ReservedBytes reserve(int length) { - var position = buffer.position(); - advance(length); - return new ReservedBytes(position); - } - private void ensureSpareCapacity(int length) { ensureCapacity(buffer.position() + length); } @@ -38,20 +32,17 @@ public class BinaryWriter { } } - private void advance(int length) { - ensureSpareCapacity(length); - buffer.position(buffer.position() + length); - } - public byte[] toBytes() { var result = new byte[buffer.position()]; buffer.get(0, result); return result; } - public static class ReservedBytes { - public ReservedBytes(int position) { + public int position() { + return buffer.position(); + } - } + public void seek(int newPosition) { + buffer.position(newPosition); } } diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/WasmBinaryFormat.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/WasmBinaryFormat.java index ab43d70d..c87a86e5 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/WasmBinaryFormat.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/WasmBinaryFormat.java @@ -1,10 +1,15 @@ package org.shedlang.compiler.backends.wasm.structure; +import org.pcollections.PVector; import org.shedlang.compiler.backends.wasm.structure.ast.WasmModule; +import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmFuncType; +import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmValueType; +import org.shedlang.compiler.util.Action; -import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.util.HexFormat; +import java.util.List; public class WasmBinaryFormat { private static final byte[] WASM_MAGIC = HexFormat.of().parseHex("0061736D"); @@ -33,8 +38,75 @@ public class WasmBinaryFormat { } } - public static void serializeModule(WasmModule module, FileOutputStream outputStream) throws IOException { - outputStream.write(WASM_MAGIC); - outputStream.write(WASM_VERSION); + public static void serializeModule(WasmModule module, OutputStream outputStream) throws IOException { + var writer = new BinaryWriter(); + writer.writeBytes(WASM_MAGIC); + writer.writeBytes(WASM_VERSION); + writeTypeSection(module.types(), writer); + + outputStream.write(writer.toBytes()); + } + + private static void writeTypeSection( + PVector<WasmFuncType> types, + BinaryWriter writer + ) throws IOException { + if (types.size() > 0) { + writeSection(SectionType.TYPE, writer, () -> { + Leb128Encoding.encodeUnsignedInt32(types.size(), writer); + for (var type : types) { + writeFuncType(type, writer); + } + }); + } + } + + private static void writeFuncType(WasmFuncType type, BinaryWriter writer) { + writer.writeByte((byte) 0x60); + writeValueTypeVector(type.params(), writer); + writeValueTypeVector(type.results(), writer); + } + + private static void writeValueTypeVector(List<WasmValueType> types, BinaryWriter writer) { + Leb128Encoding.encodeUnsignedInt32(types.size(), writer); + for (var type : types) { + writeValueType(type, writer); + } + } + + private static void writeValueType(WasmValueType type, BinaryWriter writer) { + var encoding = switch (type) { + case I32 -> 0x7f; + case I64 -> 0x7e; + case F32 -> 0x7d; + case F64 -> 0x7c; + }; + writer.writeByte((byte) encoding); + } + + private static void writeSection( + SectionType sectionType, + BinaryWriter writer, + Action writeContent + ) throws IOException { + // https://webassembly.github.io/spec/core/binary/modules.html#sections + // + // Each section consists of: + // * a one-byte section ID + // * the u32 size of the contents, in bytes + // * the actual contents + writer.writeByte(sectionType.id); + + var sizePosition = writer.position(); + Leb128Encoding.encodePaddedUnsignedInt32(0, writer); + + var contentStartPosition = writer.position(); + writeContent.call(); + var contentEndPosition = writer.position(); + + var size = contentEndPosition - contentStartPosition; + writer.seek(sizePosition); + Leb128Encoding.encodePaddedUnsignedInt32(size, writer); + writer.seek(contentEndPosition); } } diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/WasmModule.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/WasmModule.java index a5827d58..ed0d88f2 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/WasmModule.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/WasmModule.java @@ -1,13 +1,15 @@ package org.shedlang.compiler.backends.wasm.structure.ast; -public record WasmModule() { - public static Builder builder() { - return new Builder(); - } +import org.pcollections.PVector; +import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmFuncType; +import org.shedlang.compiler.util.P; + +public record WasmModule( + PVector<WasmFuncType> types +) { + public static final WasmModule EMPTY = new WasmModule(P.vector()); - public record Builder() { - public WasmModule build() { - return new WasmModule(); - } + public WasmModule addType(WasmFuncType type) { + return new WasmModule(types.plus(type)); } } diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/types/WasmFuncType.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/types/WasmFuncType.java new file mode 100644 index 00000000..abb58fe3 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/types/WasmFuncType.java @@ -0,0 +1,9 @@ +package org.shedlang.compiler.backends.wasm.structure.ast.types; + +import java.util.List; + +public record WasmFuncType( + List<WasmValueType> params, + List<WasmValueType> results +) { +} diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/types/WasmValueType.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/types/WasmValueType.java new file mode 100644 index 00000000..d46bc8e8 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/types/WasmValueType.java @@ -0,0 +1,8 @@ +package org.shedlang.compiler.backends.wasm.structure.ast.types; + +public enum WasmValueType { + I32, + I64, + F32, + F64 +} |
