From 17bcdbfef0e40bedd8e8c16e3b6eb6d134635d49 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Mon, 26 Jun 2023 21:46:39 +0100 Subject: Add WASM code gen for call instructions with args --- .../compiler/backends/llvm/LlvmCodeGen.java | 6 ++-- .../backends/llvm/LlvmCodeGenClosures.java | 17 +++++---- .../compiler/backends/wasm/WasmCodeGen.java | 42 ++++++++++++++++++++-- .../backends/wasm/WasmCodeGenClosures.java | 16 +++++++-- .../backends/wasm/WasmCodeGenLocalSpace.java | 2 ++ .../java/org/shedlang/compiler/util/Iterables.java | 12 +++++++ 6 files changed, 79 insertions(+), 16 deletions(-) (limited to 'src/main/java') 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(); + var namedArgsByName = new ArrayList>(); 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(); 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 positionalArgs, - Map namedArgsByName, + List> namedArgsByName, LlvmCodeGenContext context ) { var closurePointerResult = castValueToClosurePointer(closure, context); @@ -176,14 +175,14 @@ public class LlvmCodeGenClosures { var fullArgs = new ArrayList(); 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>(); + 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(); + 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 positionalArgs, - Map namedArgsByName, + List> 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 > List sortedBy( + Collection collection, + Function key + ) { + return collection.stream().sorted(Comparator.comparing(key)).toList(); + } } -- cgit v1.2.3