aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-06-28 00:26:04 +0100
committerMichael Williamson <mike@zwobble.org>2023-06-28 00:26:04 +0100
commitd64012b950a646bd1d607f73147619ed1f1abbc7 (patch)
tree250eb236b90cc620268d2acc22109725a807a41f /src/main/java
parent94d8f0318b35658a86e2b4aacad7025dbe2e0ff5 (diff)
Hack together support for True example with WASM backend
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/WasmBackend.java68
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java41
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java40
3 files changed, 140 insertions, 9 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmBackend.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmBackend.java
index 89ca9189..48a8d5ee 100644
--- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmBackend.java
+++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmBackend.java
@@ -1,13 +1,18 @@
package org.shedlang.compiler.backends.wasm;
import org.shedlang.compiler.backends.Backend;
+import org.shedlang.compiler.backends.wasm.structure.WasmBinaryFormat;
+import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmModule;
import org.shedlang.compiler.config.ProjectConfig;
import org.shedlang.compiler.stackir.instructions.Instruction;
import org.shedlang.compiler.typechecker.TypeInfo;
import org.shedlang.compiler.types.NamespaceName;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -19,11 +24,74 @@ public class WasmBackend implements Backend {
TypeInfo typeInfo,
Path targetDir
) throws IOException {
+ var objectFilePaths = new ArrayList<Path>();
+ for (var namespace : namespaces.entrySet()) {
+ var namespaceName = namespace.getKey();
+ var wasmModule = WasmCodeGen.generateNamespace(
+ namespaceName,
+ namespace.getValue(),
+ typeInfo
+ );
+ var objectPath = writeObjectFile(
+ wasmModule,
+ targetDir.resolve("namespaces"),
+ String.join("_", namespaceName.parts())
+ );
+ objectFilePaths.add(objectPath);
+ }
+
+ for (var bin : config.bins()) {
+ var ldArgs = new ArrayList<String>();
+ ldArgs.add("wasm-ld");
+
+ ldArgs.add("-o");
+ ldArgs.add(targetDir.resolve(bin.name() + ".wasm").toString());
+
+ for (var objectFilePath : objectFilePaths) {
+ ldArgs.add(objectFilePath.toString());
+ }
+
+ var mainModule = WasmCodeGen.generateMain(config.main(), typeInfo);
+ var mainObjectPath = writeObjectFile(mainModule, targetDir.resolve("bins"), bin.name());
+ ldArgs.add(mainObjectPath.toString());
+
+ run(ldArgs);
+ }
}
@Override
public String name() {
return "wasm";
}
+
+ private static Path writeObjectFile(WasmModule module, Path workingDirectory, String name) throws IOException {
+ var objectPath = workingDirectory.resolve(name + ".o");
+ Files.createDirectories(objectPath.getParent());
+ try (var outputStream = new FileOutputStream(objectPath.toFile())) {
+ WasmBinaryFormat.serializeModule(module, outputStream);
+ }
+ return objectPath;
+ }
+
+ // TODO: extract common run() code
+ private static void run(List<String> args) throws IOException {
+ var process = new ProcessBuilder(args)
+ .inheritIO()
+ .start();
+
+ while (true) {
+ try {
+ var exitCode = process.waitFor();
+ if (exitCode != 0) {
+ // TODO: better error code
+ throw new RuntimeException("exit code: " + exitCode);
+ } else {
+ return;
+ }
+ } catch (InterruptedException exception) {
+
+ }
+ }
+ }
}
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java
index 88d46346..844a2347 100644
--- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java
+++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java
@@ -1,11 +1,16 @@
package org.shedlang.compiler.backends.wasm;
import org.shedlang.compiler.backends.wasm.structure.ast.instructions.*;
+import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFunction;
import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmLocalIndex;
+import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmModule;
import org.shedlang.compiler.stackir.instructions.*;
+import org.shedlang.compiler.typechecker.TypeInfo;
+import org.shedlang.compiler.types.NamespaceName;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import static org.shedlang.compiler.util.Lists.reversed;
@@ -14,6 +19,42 @@ public class WasmCodeGen {
private WasmCodeGen() {
}
+ public static WasmModule generateMain(NamespaceName main, TypeInfo typeInfo) {
+ var context = WasmCodeGenContext.fromTypeInfo(typeInfo);
+
+ context = context.addFunction(new WasmFunction(
+ "_start",
+ List.of(),
+ List.of(),
+ List.of(),
+ new WasmExpression(List.of())
+ ));
+
+ return context.toModule();
+ }
+
+ public static WasmModule generateNamespace(
+ NamespaceName namespaceName,
+ List<Instruction> instructions,
+ TypeInfo typeInfo
+ ) {
+ var context = WasmCodeGenContext.fromTypeInfo(typeInfo);
+
+ context = WasmCodeGenNamespaces.define(
+ namespaceName,
+ initContext -> {
+ for (var instruction : instructions) {
+ initContext = generateInstruction(instruction, initContext);
+ }
+
+ return initContext;
+ },
+ context
+ );
+
+ return context.toModule();
+ }
+
public static WasmCodeGenContext generateInstruction(Instruction instruction, WasmCodeGenContext context) {
return switch (instruction) {
case CallInstruction call -> {
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java
index 38f57f52..a1fdb0fc 100644
--- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java
+++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java
@@ -9,10 +9,35 @@ import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmAlignment;
import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmLocalIndex;
import org.shedlang.compiler.types.NamespaceName;
+import java.util.function.Function;
+
public class WasmCodeGenNamespaces {
private WasmCodeGenNamespaces() {
}
+ public static WasmCodeGenContext define(
+ NamespaceName namespaceName,
+ Function<WasmCodeGenContext, WasmCodeGenContext> generateInitBody,
+ WasmCodeGenContext context
+ ) {
+ var namespaceTypeInfo = context.typeInfo().namespaceTypeInfo(namespaceName);
+
+ var dataName = globalNameNamespaceValue(namespaceName);
+
+ context = context.addData(
+ dataName,
+ // TODO: remove magic number
+ new byte[4 * namespaceTypeInfo.fieldCount()],
+ WasmAlignment.ALIGN_32_BIT
+ ).context();
+
+ context = generateInitBody.apply(context);
+
+ var namespaceInitFunction = context.toFunction(globalNameNamespaceInit(namespaceName));
+
+ return context.addFunction(namespaceInitFunction);
+ }
+
public static WasmCodeGenContext fieldStore(
NamespaceName namespaceName,
String fieldName,
@@ -34,21 +59,18 @@ public class WasmCodeGenNamespaces {
}
private static WasmMemoryAddress namespaceMemoryAddress(NamespaceName namespaceName, WasmCodeGenContext context) {
- var dataName = dataNameNamespaceValue(namespaceName);
+ var dataName = globalNameNamespaceValue(namespaceName);
return context.memoryAddress(dataName);
-
-// context.addData(
-// dataName,
-// // TODO: remove magic number
-// new byte[4 * ],
-// WasmAlignment.ALIGN_32_BIT
-// );
}
- private static String dataNameNamespaceValue(NamespaceName namespaceName) {
+ private static String globalNameNamespaceValue(NamespaceName namespaceName) {
return "shed__namespace__" + namespaceNameToWasmIdentifier(namespaceName);
}
+ private static String globalNameNamespaceInit(NamespaceName namespaceName) {
+ return "shed__namespaceInit__" + namespaceNameToWasmIdentifier(namespaceName);
+ }
+
private static String namespaceNameToWasmIdentifier(NamespaceName namespaceName) {
return String.join("_", namespaceName.parts());
}