aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-06-21 21:27:31 +0100
committerMichael Williamson <mike@zwobble.org>2023-06-21 21:27:31 +0100
commit126533bf5210d1bf311628a18af6e46f765c922e (patch)
tree6114298e13d96d391564b5eab2dc004e2dfd87d7 /src/main/java
parentb92d46a9fc641afca93571e1b398b968816b1b57 (diff)
Add binary encoding of WASM type section
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/BinaryWriter.java19
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/WasmBinaryFormat.java80
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/WasmModule.java18
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/types/WasmFuncType.java9
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/types/WasmValueType.java8
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
+}