aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-06-25 12:10:39 +0100
committerMichael Williamson <mike@zwobble.org>2023-06-25 12:10:39 +0100
commitbb0029571483cdb4359359c7f978fed62976c891 (patch)
tree5313fdddc04b3fb81f379e3ce5a60e91aa0e03c8 /src/main/java
parent90b74cb3dfa09bc2c5bae3dacd9f16dc841c2e6a (diff)
Write symbol infos for functions
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/modules/WasmModule.java45
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatLinking.java150
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatModules.java2
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatNameSection.java18
4 files changed, 196 insertions, 19 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/modules/WasmModule.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/modules/WasmModule.java
index 6772e6ae..7395d996 100644
--- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/modules/WasmModule.java
+++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/modules/WasmModule.java
@@ -25,18 +25,53 @@ public record WasmModule(
P.vector()
);
- public record IndexedFunction(WasmFuncIndex funcIndex, WasmFunction function) {
+ public sealed interface IndexedFunction {
+ record Import(WasmFuncIndex funcIndex, WasmImportDescriptor.Func descriptor) implements IndexedFunction {
+ @Override
+ public String name() {
+ return descriptor.identifier();
+ }
+ }
+
+ record Definition(WasmFuncIndex funcIndex, WasmFunction function) implements IndexedFunction {
+ @Override
+ public String name() {
+ return function.name();
+ }
+ }
+
+ WasmFuncIndex funcIndex();
+ String name();
}
public List<IndexedFunction> indexedFunctions() {
- var funcIndex = imports.stream()
+ var indexedFunctions = new ArrayList<IndexedFunction>();
+
+ for (var import_ : imports) {
+ if (import_.descriptor() instanceof WasmImportDescriptor.Func func) {
+ var funcIndex = new WasmFuncIndex(indexedFunctions.size());
+ indexedFunctions.add(new IndexedFunction.Import(funcIndex, func));
+ }
+ }
+
+ for (var function : functions) {
+ var funcIndex = new WasmFuncIndex(indexedFunctions.size());
+ indexedFunctions.add(new IndexedFunction.Definition(funcIndex, function));
+ }
+
+ return indexedFunctions;
+ }
+
+ public List<IndexedFunction.Definition> indexedFunctionDefinitions() {
+ var startIndex = imports.stream()
.filter(import_ -> import_.descriptor() instanceof WasmImportDescriptor.Func)
.count();
- var indexedFunctions = new ArrayList<IndexedFunction>();
+ var indexedFunctions = new ArrayList<IndexedFunction.Definition>();
+
for (var function : functions) {
- indexedFunctions.add(new IndexedFunction(new WasmFuncIndex((int) funcIndex), function));
- funcIndex++;
+ var funcIndex = new WasmFuncIndex((int) startIndex + indexedFunctions.size());
+ indexedFunctions.add(new IndexedFunction.Definition(funcIndex, function));
}
return indexedFunctions;
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatLinking.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatLinking.java
new file mode 100644
index 00000000..59bab46e
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatLinking.java
@@ -0,0 +1,150 @@
+package org.shedlang.compiler.backends.wasm.structure.binary;
+
+import org.shedlang.compiler.backends.wasm.structure.BinaryWriter;
+import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFuncIndex;
+import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmModule;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatConventions.writeVec;
+import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatModules.writeCustomSection;
+import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatModules.writeFuncIndex;
+import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatSize.writeSize;
+import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatValues.writeString;
+
+public class WasmBinaryFormatLinking {
+ // Corresponds to https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
+
+ private WasmBinaryFormatLinking() {
+ }
+
+ // == Linking Metadata Section ==
+
+ private static final int VERSION = 2;
+
+ public static void writeLinkingSection(
+ WasmModule module,
+ WasmIndexTable indexTable,
+ BinaryWriter writer
+ ) throws IOException {
+ writeCustomSection("linking", writer, () -> {
+ Leb128Encoding.encodeUnsignedInt32(VERSION, writer);
+ writeSymbolTableSubsection(module, indexTable, writer);
+ });
+ }
+
+ private static void writeSubsection(
+ SubsectionType type,
+ BinaryWriter writer,
+ WasmBinaryFormatModules.Write writeContent
+ ) throws IOException {
+ writer.writeByte(type.id);
+ writeSize(writer, writeContent::write);
+ }
+
+ private enum SubsectionType {
+ WASM_SEGMENT_INFO(5),
+ WASM_INIT_FUNCS(6),
+ WASM_COMDAT_INFO(7),
+ WASM_SYMBOL_TABLE(8);
+
+ private final byte id;
+
+ SubsectionType(int id) {
+ this.id = (byte) id;
+ }
+ }
+
+ private static void writeSymbolTableSubsection(
+ WasmModule module,
+ WasmIndexTable indexTable,
+ BinaryWriter writer
+ ) throws IOException {
+ writeSubsection(SubsectionType.WASM_SYMBOL_TABLE, writer, () -> {
+ writeVec(
+ symbolInfos(module),
+ symbolInfo -> writeSymbolInfo(symbolInfo, writer),
+ writer
+ );
+ });
+ }
+
+ private static void writeSymbolInfo(SymbolInfo symbolInfo, BinaryWriter writer) {
+ switch (symbolInfo) {
+ case SymbolInfo.Function function -> {
+ writer.writeByte(SymbolType.FUNCTION.id);
+ Leb128Encoding.encodeUnsignedInt32(flagsToInt(function.flags), writer);
+ writeFuncIndex(function.funcIndex, writer);
+ writeString(function.name(), writer);
+ }
+ }
+ }
+
+ private enum SymbolType {
+ FUNCTION(0),
+ DATA(1),
+ GLOBAL(2),
+ SECTION(3),
+ EVENT(4),
+ TABLE(5);
+
+ private final byte id;
+
+ SymbolType(int id) {
+ this.id = (byte) id;
+ }
+ }
+
+ private static List<SymbolInfo> symbolInfos(WasmModule module) {
+ return module.indexedFunctions().stream()
+ .<SymbolInfo>map(function -> {
+ var flags = switch (function) {
+ case WasmModule.IndexedFunction.Definition definition ->
+ List.<SymbolFlag>of();
+
+ case WasmModule.IndexedFunction.Import import_ ->
+ List.of(SymbolFlag.UNDEFINED, SymbolFlag.EXPLICIT_NAME);
+ };
+ return new SymbolInfo.Function(
+ flags,
+ function.funcIndex(),
+ function.name()
+ );
+ })
+ .toList();
+ }
+
+ private sealed interface SymbolInfo {
+ record Function(List<SymbolFlag> flags, WasmFuncIndex funcIndex, String name) implements SymbolInfo {
+
+ }
+ }
+
+ private enum SymbolFlag {
+ BINDING_WEAK(0x01),
+ BINDING_LOCAL(0x02),
+ BINDING_VISIBILITY_HIDDEN(0x04),
+ UNDEFINED(0x10),
+ EXPORTED(0x20),
+ EXPLICIT_NAME(0x40),
+ NO_STRIP(0x80);
+
+ private final int value;
+
+ SymbolFlag(int value) {
+ this.value = value;
+ }
+ }
+
+ private static int flagsToInt(Collection<SymbolFlag> flags) {
+ var asInt = 0;
+
+ for (var flag : flags) {
+ asInt |= flag.value;
+ }
+
+ return asInt;
+ }
+}
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatModules.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatModules.java
index 41a84e2a..ef1c6afb 100644
--- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatModules.java
+++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatModules.java
@@ -14,6 +14,7 @@ import java.util.List;
import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatConventions.writeVec;
import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatInstructions.writeExpression;
+import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatLinking.writeLinkingSection;
import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatNameSection.writeNameSection;
import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatSize.writeSize;
import static org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatTypes.*;
@@ -305,6 +306,7 @@ public class WasmBinaryFormatModules {
writeElementSection(module, writer);
writeCodeSection(module, writer);
writeNameSection(module, indexTable, writer);
+ writeLinkingSection(module, indexTable, writer);
outputStream.write(writer.toBytes());
}
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatNameSection.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatNameSection.java
index e5142955..4c4f948a 100644
--- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatNameSection.java
+++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatNameSection.java
@@ -2,12 +2,10 @@ package org.shedlang.compiler.backends.wasm.structure.binary;
import org.shedlang.compiler.backends.wasm.structure.BinaryWriter;
import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFuncIndex;
-import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmImportDescriptor;
import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmLocal;
import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmModule;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
@@ -81,17 +79,9 @@ public class WasmBinaryFormatNameSection {
private static void writeFunctionNameSubsection(WasmModule module, BinaryWriter writer) throws IOException {
writeNameSubsection(NameSubsectionId.FUNCTION_NAMES, writer, () -> {
- var functionNames = new ArrayList<NameAssoc>();
- for (var import_ : module.imports()) {
- if (import_.descriptor() instanceof WasmImportDescriptor.Func func) {
- var funcIndex = new WasmFuncIndex(functionNames.size());
- functionNames.add(new NameAssoc(funcIndex, func.identifier()));
- }
- }
- for (var function : module.functions()) {
- var fundIndex = new WasmFuncIndex(functionNames.size());
- functionNames.add(new NameAssoc(fundIndex, function.name()));
- }
+ var functionNames = module.indexedFunctions().stream()
+ .map(function -> new NameAssoc(function.funcIndex(), function.name()))
+ .toList();
writeNameMap(writer, functionNames);
});
@@ -106,7 +96,7 @@ public class WasmBinaryFormatNameSection {
) throws IOException {
writeNameSubsection(NameSubsectionId.LOCAL_NAMES, writer, () -> {
writeVec(
- module.indexedFunctions(),
+ module.indexedFunctionDefinitions(),
indexedFunction -> {
writeFuncIndex(indexedFunction.funcIndex(), writer);