diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-11-26 16:45:51 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-11-26 16:45:51 +0000 |
| commit | aa13c97dac536bd1c4bf2f4e5c6ee505a487c634 (patch) | |
| tree | 61fe8650b0579aa5dc5b55fb50b41eff6c3470d6 /src | |
| parent | ee02a8cd9af3b2ae723cbba9a910fc159fe75a7c (diff) | |
Support Patio exceptions in Patio Wasm backend
Diffstat (limited to 'src')
4 files changed, 125 insertions, 9 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java index 1447ee14..585de4e6 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java @@ -337,18 +337,36 @@ public class WasmPatioCodeGen { yield context; } - case PatioThrow throw_ -> - throw new UnsupportedOperationException("TODO"); + case PatioThrow throw_ -> { + context = generateOperand(throw_.value(), context); + + context = context.addInstruction(new WasmThrow(new WasmTagName(throw_.exceptionTypeName()))); + + yield context; + } case PatioTry try_ -> { + context = context.enterTryInstruction( + new WasmBlockType(List.of(WasmValueType.I32)) + ); + context = generateBlockBody(try_.body(), context); + for (var catchClause : try_.catchClauses()) { + context = context.enterCatch(new WasmTagName(catchClause.exceptionTypeName())); + + // TODO: pop into local for catch + context = context.addInstruction(new WasmDrop()); + context = generateBlockBody(catchClause.body(), context); + } + + context = context.exitTryInstruction(); + context = popIntoPatioLocals(try_.targets(), context); yield context; } - case PatioUnreachable patioUnreachable -> context.addInstruction(new WasmUnreachable()); @@ -732,6 +750,33 @@ public class WasmPatioCodeGen { return exitStructuredInstruction(); } + public Context enterTryInstruction(WasmBlockType blockType) { + return new Context( + this.module, + P.vector(), + this.instructionsStack.plus(this.instructions), + this.patioLocalNameToWasmLocalIndex, + new WasmTryInstructionBuilder(blockType), + this.structuredInstructionBuilderStack.plus(this.structuredInstructionBuilder) + ); + } + + public Context enterCatch(WasmTagName tagName) { + return new Context( + this.module, + P.vector(), + this.instructionsStack, + this.patioLocalNameToWasmLocalIndex, + this.structuredInstructionBuilder.enterCatch(tagName, this.instructions), + this.structuredInstructionBuilderStack + ); + } + + public Context exitTryInstruction() { + // TODO: verify matching enter/exit? + return exitStructuredInstruction(); + } + public Context exitStructuredInstruction() { var context = new Context( this.module, @@ -775,6 +820,13 @@ public class WasmPatioCodeGen { default WasmStructuredInstructionBuilder enterElse(PVector<WasmInstruction> instructions) { throw new UnsupportedOperationException(); } + + default WasmStructuredInstructionBuilder enterCatch( + WasmTagName tagName, + PVector<WasmInstruction> instructions + ) { + throw new UnsupportedOperationException(); + } } private static class NullStructuredInstructionBuilder implements WasmStructuredInstructionBuilder { @@ -821,4 +873,55 @@ public class WasmPatioCodeGen { return new WasmIf(blockType, ifTrue, instructions); } } + + private record WasmTryInstructionBuilder( + WasmBlockType blockType + ) implements WasmStructuredInstructionBuilder { + @Override + public WasmInstruction exit(PVector<WasmInstruction> instructions) { + return new WasmTry(blockType, List.of(), instructions); + } + + @Override + public WasmStructuredInstructionBuilder enterCatch( + WasmTagName tagName, + PVector<WasmInstruction> instructions + ) { + return new WasmTryCatchInstructionBuilder( + blockType, + instructions, + tagName, + P.vector() + ); + } + } + + private record WasmTryCatchInstructionBuilder( + WasmBlockType blockType, + List<WasmInstruction> tryBodyInstructions, + WasmTagName tagName, + PVector<WasmCatchBlock> catchBlocks + ) implements WasmStructuredInstructionBuilder { + @Override + public WasmInstruction exit(PVector<WasmInstruction> instructions) { + return new WasmTry( + this.blockType, + this.catchBlocks.plus(new WasmCatchBlock(this.tagName, instructions)), + this.tryBodyInstructions + ); + } + + @Override + public WasmStructuredInstructionBuilder enterCatch( + WasmTagName tagName, + PVector<WasmInstruction> instructions + ) { + return new WasmTryCatchInstructionBuilder( + this.blockType, + this.tryBodyInstructions, + tagName, + this.catchBlocks.plus(new WasmCatchBlock(this.tagName, instructions)) + ); + } + } } diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGenTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGenTests.java index a4c823df..56262676 100644 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGenTests.java +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGenTests.java @@ -1,5 +1,7 @@ package org.shedlang.compiler.backends.llvm; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.shedlang.compiler.backends.llvm.ir.ast.LlvmBasicBlock; import org.shedlang.compiler.backends.llvm.ir.ast.LlvmFunctionDefinition; import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmCall; @@ -64,4 +66,10 @@ public class LlvmPatioCodeGenTests extends PatioExampleTests { return TestProcessRunner.runCaptureOutput(List.of(executablePath.toString())); } + + @Disabled("WIP") + @Test + public void whenExceptionIsThrownThenFirstMatchingExceptionHandlerIsUsed() { + + } } diff --git a/src/test/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGenTests.java b/src/test/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGenTests.java index b3c0960f..fe87bfc8 100644 --- a/src/test/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGenTests.java +++ b/src/test/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGenTests.java @@ -9,6 +9,7 @@ import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmImport; import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmImportDescriptor; import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmFuncType; import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmValueType; +import org.shedlang.compiler.filesystem.ShedCompilerFiles; import org.shedlang.compiler.patio.PatioExampleTests; import org.shedlang.compiler.patio.ast.PatioCompilationUnit; import org.shedlang.compiler.testing.ExecutionResult; @@ -61,6 +62,13 @@ public class WasmPatioCodeGenTests extends PatioExampleTests { executablePath ); - return TestProcessRunner.runCaptureOutput(List.of("wasmtime", executablePath.toString())); + return TestProcessRunner.runCaptureOutput(List.of( + "node", + "--experimental-wasi-unstable-preview1", + "--no-warnings=ExperimentalWarning", + "--experimental-wasm-eh", + ShedCompilerFiles.getRoot().resolve("run-wasm.js").toString(), + executablePath.toString() + )); } } diff --git a/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java b/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java index b0917393..d1314e5c 100644 --- a/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java +++ b/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java @@ -1,6 +1,5 @@ package org.shedlang.compiler.patio; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.shedlang.compiler.patio.ast.PatioCompilationUnit; import org.shedlang.compiler.patio.ast.PatioFunctionDefinition; @@ -223,7 +222,6 @@ public abstract class PatioExampleTests { } @Test - @Disabled("WIP") public void whenExceptionIsThrownThenFirstMatchingExceptionHandlerIsUsed() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) @@ -266,7 +264,7 @@ public abstract class PatioExampleTests { ) ) ), - List.of(Patio.int_(0)) + List.of(Patio.localRef("r2")) ) )) .addBodyInstruction(Patio.return_( @@ -275,13 +273,12 @@ public abstract class PatioExampleTests { .build(); var patio = Patio.compilationUnit(List.of( Patio.exceptionTypeDefinition("Error", PatioTypes.INT), - Patio.exceptionTypeDefinition("OtherError", PatioTypes.INT), patioFunction )); var result = run(patio); - assertThat(result, isSilentExit(47)); + assertThat(result, isSilentExit(2)); } @Test |
