diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-06-26 21:46:39 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-06-26 21:46:39 +0100 |
| commit | 17bcdbfef0e40bedd8e8c16e3b6eb6d134635d49 (patch) | |
| tree | 81cee6ab44660381e76d3fcc47cdada7beffe5a8 /src/main/java | |
| parent | a5b889d21b9fcfac32f6f691fa08146139065fd3 (diff) | |
Add WASM code gen for call instructions with args
Diffstat (limited to 'src/main/java')
6 files changed, 79 insertions, 16 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java index 7c4427b4..5eb418a9 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java @@ -36,7 +36,7 @@ public class LlvmCodeGen { var field = fieldResult.value(); mainContext = fieldResult.context(); - mainContext = LlvmCodeGenClosures.call(field, List.of(), Map.of(), mainContext); + mainContext = LlvmCodeGenClosures.call(field, List.of(), List.of(), mainContext); mainContext = mainContext.addTerminatorInstruction( new LlvmReturn(LlvmTypes.INT_32, new LlvmOperandInt(0)) @@ -97,12 +97,12 @@ public class LlvmCodeGen { public static LlvmCodeGenContext generateInstruction(Instruction instruction, LlvmCodeGenContext context) { return switch (instruction) { case CallInstruction call -> { - var namedArgsByName = new HashMap<String, LlvmOperand>(); + var namedArgsByName = new ArrayList<Map.Entry<String, LlvmOperand>>(); for (var argName : reversed(call.namedArgNames())) { var argResult = context.pop(); var arg = argResult.value(); context = argResult.context(); - namedArgsByName.put(argName, arg); + namedArgsByName.add(Map.entry(argName, arg)); } var positionalArgs = new ArrayList<LlvmOperand>(); diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenClosures.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenClosures.java index 098acbdd..62212a34 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenClosures.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenClosures.java @@ -11,12 +11,11 @@ import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableGlobal; import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableLocal; import org.shedlang.compiler.backends.llvm.ir.ast.types.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.function.Function; +import static org.shedlang.compiler.util.Iterables.sortedBy; + public class LlvmCodeGenClosures { private LlvmCodeGenClosures() { } @@ -157,7 +156,7 @@ public class LlvmCodeGenClosures { public static LlvmCodeGenContext call( LlvmOperand closure, List<LlvmOperand> positionalArgs, - Map<String, LlvmOperand> namedArgsByName, + List<Map.Entry<String, LlvmOperand>> namedArgsByName, LlvmCodeGenContext context ) { var closurePointerResult = castValueToClosurePointer(closure, context); @@ -176,14 +175,14 @@ public class LlvmCodeGenClosures { var fullArgs = new ArrayList<LlvmTypedOperand>(); fullArgs.add(new LlvmTypedOperand(CALLABLE_TYPES.closurePointer(), closurePointer)); + for (var arg : positionalArgs) { fullArgs.add(new LlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, arg)); } - namedArgsByName.entrySet() - .stream().sorted(Map.Entry.comparingByKey()) - .map(x -> x.getValue()) - .forEachOrdered(x -> fullArgs.add(new LlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, x))); + for (var arg : sortedBy(namedArgsByName, x -> x.getKey())) { + fullArgs.add(new LlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, arg.getValue())); + } return context.addInstruction(new LlvmCall( callTarget, 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 3d466648..5926af9c 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,15 @@ package org.shedlang.compiler.backends.wasm; import org.shedlang.compiler.backends.wasm.structure.ast.instructions.*; +import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmLocalIndex; import org.shedlang.compiler.stackir.instructions.*; -import java.util.List; +import java.util.ArrayList; +import java.util.Collections; import java.util.Map; +import static org.shedlang.compiler.util.Lists.reversed; + public class WasmCodeGen { private WasmCodeGen() { } @@ -13,13 +17,47 @@ public class WasmCodeGen { public static WasmCodeGenContext generateInstruction(Instruction instruction, WasmCodeGenContext context) { return switch (instruction) { case CallInstruction call -> { + var namedArgsByName = new ArrayList<Map.Entry<String, WasmLocalIndex>>(); + for (var argName : reversed(call.namedArgNames())) { + var argResult = context.generateLocal( + WasmCodeGenLocalSpace.CALL_ARG_NAMED, + argName + ); + var arg = argResult.value(); + context = argResult.context(); + + context = context.addInstruction(new WasmLocalSet(arg)); + + namedArgsByName.add(Map.entry(argName, arg)); + } + + var positionalArgs = new ArrayList<WasmLocalIndex>(); + for (var i = 0; i < call.positionalArgCount(); i++) { + var argResult = context.generateLocal( + WasmCodeGenLocalSpace.CALL_ARG_POSITIONAL, + Integer.toString(call.positionalArgCount() - i - 1) + ); + var arg = argResult.value(); + context = argResult.context(); + + context = context.addInstruction(new WasmLocalSet(arg)); + + positionalArgs.add(arg); + } + Collections.reverse(positionalArgs); + var receiverResult = context.generateLocal(WasmCodeGenLocalSpace.RECEIVER); var receiver = receiverResult.value(); context = receiverResult.context(); context = context.addInstruction(new WasmLocalSet(receiver)); - yield WasmCodeGenClosures.call(receiver, List.of(), Map.of(), context); + yield WasmCodeGenClosures.call( + receiver, + positionalArgs, + namedArgsByName, + context + ); } case DefineFunctionInstruction defineFunctionInstruction -> { throw new UnsupportedOperationException("TODO"); diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenClosures.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenClosures.java index 86ae472d..a2d34df7 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenClosures.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenClosures.java @@ -12,6 +12,8 @@ import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmValueType; import java.util.List; import java.util.Map; +import static org.shedlang.compiler.util.Iterables.sortedBy; + public class WasmCodeGenClosures { private WasmCodeGenClosures() { } @@ -21,14 +23,24 @@ public class WasmCodeGenClosures { public static WasmCodeGenContext call( WasmLocalIndex closure, List<WasmLocalIndex> positionalArgs, - Map<String, WasmLocalIndex> namedArgsByName, + List<Map.Entry<String, WasmLocalIndex>> namedArgsByName, WasmCodeGenContext context ) { + context = context.addInstruction(new WasmLocalGet(closure)); + + for (var positionalArg : positionalArgs) { + context = context.addInstruction(new WasmLocalGet(positionalArg)); + } + + for (var namedArg : sortedBy(namedArgsByName, x -> x.getKey())) { + context = context.addInstruction(new WasmLocalGet(namedArg.getValue())); + } + context = loadClosureFunctionTableIndex(closure, context); var funcType = new WasmFuncType(List.of(CLOSURE_TYPE), List.of(WasmCodeGenTypes.VALUE_TYPE)); + return context - .addInstruction(new WasmLocalGet(closure)) .addType(funcType) .addInstruction(new WasmCallIndirect(context.indirectFunctionTableIndex(), funcType)); } diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenLocalSpace.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenLocalSpace.java index 80e89155..eeda312a 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenLocalSpace.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenLocalSpace.java @@ -1,6 +1,8 @@ package org.shedlang.compiler.backends.wasm; public enum WasmCodeGenLocalSpace { + CALL_ARG_POSITIONAL("callArgPositional"), + CALL_ARG_NAMED("callArgNamed"), LOCAL("local"), RECEIVER("receiver"); diff --git a/src/main/java/org/shedlang/compiler/util/Iterables.java b/src/main/java/org/shedlang/compiler/util/Iterables.java index ff043c13..38730594 100644 --- a/src/main/java/org/shedlang/compiler/util/Iterables.java +++ b/src/main/java/org/shedlang/compiler/util/Iterables.java @@ -1,5 +1,10 @@ package org.shedlang.compiler.util; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.function.Function; + public class Iterables { private Iterables() { } @@ -26,4 +31,11 @@ public class Iterables { first = false; } } + + public static <T, K extends Comparable<? super K>> List<T> sortedBy( + Collection<T> collection, + Function<? super T, ? extends K> key + ) { + return collection.stream().sorted(Comparator.comparing(key)).toList(); + } } |
