aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-06-17 10:49:53 +0100
committerMichael Williamson <mike@zwobble.org>2023-06-17 10:49:53 +0100
commit43fd7ec22f5f86ab79a5aa70c8dd460d84ad4726 (patch)
tree2aeb384c88372b8b6f37307b7471b85031134e92 /src/main/java
parentc70a0a1ecbd562f8e13c6c96b28bcd15d3cd2b62 (diff)
Hack together compilation of LLVM modules to object files
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/ShedCompiler.java31
-rw-r--r--src/main/java/org/shedlang/compiler/backends/Backend.java8
-rw-r--r--src/main/java/org/shedlang/compiler/backends/GenerateInstructionsBackend.java7
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java62
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java26
5 files changed, 113 insertions, 21 deletions
diff --git a/src/main/java/org/shedlang/compiler/ShedCompiler.java b/src/main/java/org/shedlang/compiler/ShedCompiler.java
index 6f252776..ebf97bdc 100644
--- a/src/main/java/org/shedlang/compiler/ShedCompiler.java
+++ b/src/main/java/org/shedlang/compiler/ShedCompiler.java
@@ -36,6 +36,18 @@ public class ShedCompiler {
var namespaces = new LinkedHashMap<NamespaceName, List<Instruction>>();
+ var typeCheckerContext = TypeCheckerContext.EMPTY
+ .enter(P.map(
+ Map.entry("Io", Types.effectType(Effects.IO)),
+ Map.entry("Unit", Types.metaType(Types.UNIT)),
+
+ Map.entry("print", new FunctionType(
+ List.of(Types.STRING),
+ List.of(),
+ Types.UNIT
+ ))
+ ));
+
for (var sourceFilePath : sourceFilePaths) {
var namespaceNameParts = StreamSupport.stream(sourceRoot.relativize(sourceFilePath).spliterator(), false)
.map(element -> {
@@ -51,25 +63,14 @@ public class ShedCompiler {
var tokens = tokenise(source);
var untypedNode = Parser.parseNamespace(tokens, namespaceName);
+ var typeCheckNamespaceResult = TypeChecker.typeCheckNamespace(untypedNode, typeCheckerContext);
+ typeCheckerContext = typeCheckNamespaceResult.context();
- var context = TypeCheckerContext.EMPTY
- .enter(P.map(
- Map.entry("Io", Types.effectType(Effects.IO)),
- Map.entry("Unit", Types.metaType(Types.UNIT)),
-
- Map.entry("print", new FunctionType(
- List.of(Types.STRING),
- List.of(),
- Types.UNIT
- ))
- ));
- var typedNode = TypeChecker.typeCheckNamespace(untypedNode, context);
-
- var instructions = StackCompiler.compileNamespace(typedNode.value());
+ var instructions = StackCompiler.compileNamespace(typeCheckNamespaceResult.value());
namespaces.put(namespaceName, instructions);
}
- backend.compile(config, namespaces);
+ backend.compile(config, namespaces, typeCheckerContext.toTypeInfo());
}
private List<Path> collectSourceFilePaths(Path sourceRoot) throws IOException {
diff --git a/src/main/java/org/shedlang/compiler/backends/Backend.java b/src/main/java/org/shedlang/compiler/backends/Backend.java
index ef0e31ca..aaf73bf9 100644
--- a/src/main/java/org/shedlang/compiler/backends/Backend.java
+++ b/src/main/java/org/shedlang/compiler/backends/Backend.java
@@ -2,11 +2,17 @@ package org.shedlang.compiler.backends;
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.IOException;
import java.util.List;
import java.util.Map;
public interface Backend {
- void compile(ProjectConfig config, Map<NamespaceName, List<Instruction>> namespaces);
+ void compile(
+ ProjectConfig config,
+ Map<NamespaceName, List<Instruction>> namespaces,
+ TypeInfo typeInfo
+ ) throws IOException;
}
diff --git a/src/main/java/org/shedlang/compiler/backends/GenerateInstructionsBackend.java b/src/main/java/org/shedlang/compiler/backends/GenerateInstructionsBackend.java
index bd7d5451..ed980e77 100644
--- a/src/main/java/org/shedlang/compiler/backends/GenerateInstructionsBackend.java
+++ b/src/main/java/org/shedlang/compiler/backends/GenerateInstructionsBackend.java
@@ -3,13 +3,18 @@ package org.shedlang.compiler.backends;
import org.shedlang.compiler.config.ProjectConfig;
import org.shedlang.compiler.stackir.InstructionSerializer;
import org.shedlang.compiler.stackir.instructions.Instruction;
+import org.shedlang.compiler.typechecker.TypeInfo;
import org.shedlang.compiler.types.NamespaceName;
import java.util.List;
import java.util.Map;
public class GenerateInstructionsBackend implements Backend {
- public void compile(ProjectConfig config, Map<NamespaceName, List<Instruction>> namespaces) {
+ public void compile(
+ ProjectConfig config,
+ Map<NamespaceName, List<Instruction>> namespaces,
+ TypeInfo typeInfo
+ ) {
System.out.println("main: " + config.main());
for (var namespaceEntry : namespaces.entrySet()) {
diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java
index 4abc46e5..2ee2b710 100644
--- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java
+++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java
@@ -1,16 +1,74 @@
package org.shedlang.compiler.backends.llvm;
import org.shedlang.compiler.backends.Backend;
+import org.shedlang.compiler.backends.llvm.ir.LlvmIrSerializer;
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.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.List;
import java.util.Map;
public class LlvmBackend implements Backend {
@Override
- public void compile(ProjectConfig config, Map<NamespaceName, List<Instruction>> namespaces) {
- throw new UnsupportedOperationException("TODO");
+ public void compile(
+ ProjectConfig config,
+ Map<NamespaceName, List<Instruction>> namespaces,
+ TypeInfo typeInfo
+ ) throws IOException {
+ for (var namespace : namespaces.entrySet()) {
+ var llvmModule = LlvmCompiler.compileNamespace(
+ namespace.getKey(),
+ namespace.getValue(),
+ typeInfo
+ );
+
+ // TODO: write directly to file
+ var builder = new StringBuilder();
+ LlvmIrSerializer.serializeModule(llvmModule, builder);
+ var temporaryDirectory = Files.createTempDirectory("shed-");
+ try {
+ // TODO: proper name
+ var llvmModulePath = temporaryDirectory.resolve("module.ll");
+ var objectPath = temporaryDirectory.resolve("module.o");
+ Files.writeString(
+ llvmModulePath,
+ builder.toString(),
+ StandardCharsets.UTF_8
+ );
+ run(List.of(
+ "llc", llvmModulePath.toString(),
+ "-filetype", "obj",
+ "-relocation-model", "pic",
+ "-o", objectPath.toString()
+ ));
+ } finally {
+ // TODO: delete
+ }
+ }
+ }
+
+ 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/llvm/LlvmCompiler.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java
index 694f3ff9..2ae8b649 100644
--- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java
+++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java
@@ -1,6 +1,7 @@
package org.shedlang.compiler.backends.llvm;
import org.shedlang.compiler.backends.llvm.ir.ast.LlvmFunctionDefinition;
+import org.shedlang.compiler.backends.llvm.ir.ast.LlvmModule;
import org.shedlang.compiler.backends.llvm.ir.ast.LlvmParam;
import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmCall;
import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmGetElementPtr;
@@ -9,6 +10,7 @@ import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmStore;
import org.shedlang.compiler.backends.llvm.ir.ast.operands.*;
import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes;
import org.shedlang.compiler.stackir.instructions.*;
+import org.shedlang.compiler.typechecker.TypeInfo;
import org.shedlang.compiler.types.NamespaceName;
import java.util.*;
@@ -16,8 +18,28 @@ import java.util.*;
import static org.shedlang.compiler.util.Lists.reversed;
public class LlvmCompiler {
- public static void compileNamespace(NamespaceName namespaceName, List<Instruction> instructions) {
-
+ public static LlvmModule compileNamespace(
+ NamespaceName namespaceName,
+ List<Instruction> instructions,
+ TypeInfo typeInfo
+ ) {
+ var context = LlvmCompilerContext.fromTypeInfo(typeInfo);
+ for (var instruction : instructions) {
+ context = compileInstruction(instruction, context);
+ }
+
+ var basicBlocks = context.basicBlocks();
+ var namespaceInitFunction = new LlvmFunctionDefinition(
+ "shed__namespaceInit__" + String.join("_", namespaceName.parts()),
+ LlvmTypes.VOID,
+ List.of(),
+ basicBlocks
+ );
+
+ var topLevelEntities = context.addTopLevelEntity(namespaceInitFunction)
+ .topLevelEntities().stream().toList();
+
+ return new LlvmModule(topLevelEntities);
}
public static LlvmCompilerContext compileInstruction(Instruction instruction, LlvmCompilerContext context) {