aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-07-19 22:10:39 +0100
committerMichael Williamson <mike@zwobble.org>2023-07-19 22:10:39 +0100
commit51c202c469f884d1c67987282ed952cc303f43d7 (patch)
tree448b564d29bfd779fec61393c404ac67cc972ad8 /src/main/java
parent7e1063d13f4d810ec8520367e7a5a1e9438d05aa (diff)
Add Patio code gen for call
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java79
-rw-r--r--src/main/java/org/shedlang/compiler/patio/PatioCodeGenClosures.java47
-rw-r--r--src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java68
-rw-r--r--src/main/java/org/shedlang/compiler/patio/PatioCodeGenLocalSpace.java18
-rw-r--r--src/main/java/org/shedlang/compiler/patio/PatioCodeGenResult.java4
-rw-r--r--src/main/java/org/shedlang/compiler/patio/PatioLocal.java4
6 files changed, 209 insertions, 11 deletions
diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java
index c0d52b54..6d07971f 100644
--- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java
+++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java
@@ -1,35 +1,94 @@
package org.shedlang.compiler.patio;
-import org.pcollections.PVector;
import org.shedlang.compiler.patio.instructions.*;
import org.shedlang.compiler.stackir.instructions.*;
-import org.shedlang.compiler.util.P;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Map;
+
+import static org.shedlang.compiler.util.Lists.reversed;
public class PatioCodeGen {
private PatioCodeGen() {}
- public static PVector<PatioInstruction> generateInstruction(Instruction stackIrInstruction) {
+ public static PatioCodeGenContext generateInstruction(
+ Instruction stackIrInstruction,
+ PatioCodeGenContext context
+ ) {
return switch (stackIrInstruction) {
+ case CallInstruction call -> {
+ var namedArgsByName = new ArrayList<Map.Entry<String, PatioLocal>>();
+ for (var argName : reversed(call.namedArgNames())) {
+ var argResult = context.allocateLocal(
+ PatioCodeGenLocalSpace.CALL_ARG_NAMED,
+ argName
+ );
+ var arg = argResult.value();
+ context = argResult.context();
+
+ context = context.addInstruction(
+ new PatioLocalStore(arg.name(), stackIrInstruction.source())
+ );
+
+ namedArgsByName.add(Map.entry(argName, arg));
+ }
+
+ var positionalArgs = new ArrayList<PatioLocal>();
+ for (var i = 0; i < call.positionalArgCount(); i++) {
+ var argResult = context.allocateLocal(
+ PatioCodeGenLocalSpace.CALL_ARG_POSITIONAL,
+ Integer.toString(call.positionalArgCount() - i - 1)
+ );
+ var arg = argResult.value();
+ context = argResult.context();
+
+ context = context.addInstruction(
+ new PatioLocalStore(arg.name(), stackIrInstruction.source())
+ );
+
+ positionalArgs.add(arg);
+ }
+ Collections.reverse(positionalArgs);
+
+ var receiverResult = context.allocateLocal(PatioCodeGenLocalSpace.RECEIVER);
+ var receiver = receiverResult.value();
+ context = receiverResult.context();
+
+ context = context.addInstruction(new PatioLocalStore(
+ receiver.name(),
+ stackIrInstruction.source()
+ ));
+
+ yield PatioCodeGenClosures.call(
+ receiver,
+ positionalArgs,
+ namedArgsByName,
+ stackIrInstruction.source(),
+ context
+ );
+ }
+
case DiscardInstruction discard ->
- P.vector(new PatioDiscard(discard.source()));
+ context.addInstruction(new PatioDiscard(discard.source()));
case LocalLoadInstruction localLoad ->
- P.vector(new PatioLocalLoad(localLoad.name(), localLoad.source()));
+ context.addInstruction(new PatioLocalLoad(localLoad.name(), localLoad.source()));
case LocalStoreInstruction localStore ->
- P.vector(new PatioLocalStore(localStore.name(), localStore.source()));
+ context.addInstruction(new PatioLocalStore(localStore.name(), localStore.source()));
case PushBoolInstruction pushBool ->
- P.vector(new PatioPushInt(pushBool.value() ? 1 : 0, pushBool.source()));
+ context.addInstruction(new PatioPushInt(pushBool.value() ? 1 : 0, pushBool.source()));
case PushIntInstruction pushInt ->
- P.vector(new PatioPushInt(pushInt.value().intValueExact(), pushInt.source()));
+ context.addInstruction(new PatioPushInt(pushInt.value().intValueExact(), pushInt.source()));
case PushUnitInstruction pushUnit ->
- P.vector(new PatioPushInt(0, pushUnit.source()));
+ context.addInstruction(new PatioPushInt(0, pushUnit.source()));
case ReturnInstruction return_ ->
- P.vector(new PatioReturn(return_.source()));
+ context.addInstruction(new PatioReturn(return_.source()));
default ->
throw new IllegalStateException("Unexpected value: " + stackIrInstruction);
diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenClosures.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenClosures.java
new file mode 100644
index 00000000..0cd31616
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenClosures.java
@@ -0,0 +1,47 @@
+package org.shedlang.compiler.patio;
+
+import org.shedlang.compiler.patio.instructions.PatioCallPointer;
+import org.shedlang.compiler.patio.instructions.PatioLocalLoad;
+import org.shedlang.compiler.patio.instructions.PatioMemoryLoad;
+import org.shedlang.compiler.sources.Source;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.shedlang.compiler.util.Iterables.sortedBy;
+
+class PatioCodeGenClosures {
+ private PatioCodeGenClosures() {}
+
+ private static final int FUNCTION_POINTER_OFFSET = 0;
+
+ static PatioCodeGenContext call(
+ PatioLocal closure,
+ List<PatioLocal> positionalArgs,
+ List<Map.Entry<String, PatioLocal>> namedArgsByName,
+ Source source,
+ PatioCodeGenContext context
+ ) {
+ // TODO: WASM expects the receiver to be pushed last, but we push it first.
+ // Do we change our instruction set to match WASM? Or have a call
+ // mechanism less reliant on stack order?
+ context = context
+ .addInstruction(new PatioLocalLoad(closure.name(), source))
+ .addInstruction(new PatioMemoryLoad(FUNCTION_POINTER_OFFSET, source));
+
+ context = context.addInstruction(new PatioLocalLoad(closure.name(), source));
+
+ for (var positionalArg : positionalArgs) {
+ context = context.addInstruction(new PatioLocalLoad(positionalArg.name(), source));
+ }
+
+ for (var namedArg : sortedBy(namedArgsByName, x -> x.getKey())) {
+ context = context.addInstruction(new PatioLocalLoad(namedArg.getValue().name(), source));
+ }
+
+ var argCount = positionalArgs.size() + namedArgsByName.size();
+
+ return context
+ .addInstruction(new PatioCallPointer(argCount, source));
+ }
+}
diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java
index 675925e3..7ac7b263 100644
--- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java
+++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java
@@ -1,4 +1,70 @@
package org.shedlang.compiler.patio;
-public class PatioCodeGenContext {
+import org.pcollections.PVector;
+import org.shedlang.compiler.backends.llvm.NameAllocator;
+import org.shedlang.compiler.patio.instructions.PatioInstruction;
+import org.shedlang.compiler.util.P;
+
+import java.util.Optional;
+
+public record PatioCodeGenContext(
+ FunctionContext functionContext
+) {
+ public record FunctionContext(
+ PVector<PatioInstruction> instructions,
+ NameAllocator<PatioCodeGenLocalSpace> localNames
+ ) {
+ public static final FunctionContext EMPTY = new FunctionContext(
+ P.vector(),
+ NameAllocator.empty()
+ );
+
+ public FunctionContext addInstruction(PatioInstruction instruction) {
+ return new FunctionContext(
+ this.instructions.plus(instruction),
+ this.localNames
+ );
+ }
+
+ public Result<PatioLocal> allocateLocal(PatioCodeGenLocalSpace space, Optional<String> name) {
+ var result = this.localNames.generateName(space, name);
+
+ return new FunctionContext(
+ this.instructions,
+ result.allocator()
+ ).toResult(new PatioLocal(result.name()));
+ }
+
+ private <T> Result<T> toResult(T value) {
+ return new Result<>(value, this);
+ }
+
+ public record Result<T>(T value, FunctionContext context) {}
+ }
+
+ public static final PatioCodeGenContext EMPTY = new PatioCodeGenContext(
+ FunctionContext.EMPTY
+ );
+
+ public PatioCodeGenContext addInstruction(PatioInstruction instruction) {
+ return new PatioCodeGenContext(
+ this.functionContext.addInstruction(instruction)
+ );
+ }
+
+ public PatioCodeGenResult<PatioLocal> allocateLocal(PatioCodeGenLocalSpace space, String name) {
+ var result = this.functionContext.allocateLocal(space, Optional.of(name));
+
+ return new PatioCodeGenContext(result.context).toResult(result.value);
+ }
+
+ public PatioCodeGenResult<PatioLocal> allocateLocal(PatioCodeGenLocalSpace space) {
+ var result = this.functionContext.allocateLocal(space, Optional.empty());
+
+ return new PatioCodeGenContext(result.context).toResult(result.value);
+ }
+
+ private <T> PatioCodeGenResult<T> toResult(T value) {
+ return new PatioCodeGenResult<>(value, this);
+ }
}
diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenLocalSpace.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenLocalSpace.java
new file mode 100644
index 00000000..dfbcf4ee
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenLocalSpace.java
@@ -0,0 +1,18 @@
+package org.shedlang.compiler.patio;
+
+public enum PatioCodeGenLocalSpace {
+ CALL_ARG_POSITIONAL("callArgPositional"),
+ CALL_ARG_NAMED("callArgNamed"),
+ RECEIVER("receiver");;
+
+ private final String name;
+
+ PatioCodeGenLocalSpace(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenResult.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenResult.java
new file mode 100644
index 00000000..5644a3b1
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenResult.java
@@ -0,0 +1,4 @@
+package org.shedlang.compiler.patio;
+
+public record PatioCodeGenResult<T>(T value, PatioCodeGenContext context) {
+}
diff --git a/src/main/java/org/shedlang/compiler/patio/PatioLocal.java b/src/main/java/org/shedlang/compiler/patio/PatioLocal.java
new file mode 100644
index 00000000..bdd1a7ab
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/patio/PatioLocal.java
@@ -0,0 +1,4 @@
+package org.shedlang.compiler.patio;
+
+public record PatioLocal(String name) {
+}