diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-08-27 23:37:47 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-08-27 23:37:47 +0100 |
| commit | 425816f43d4f0f9c69558f224a39a48d5cfca096 (patch) | |
| tree | 8dcc81261227aecc3ade5b029c33b7a815aff155 /src/main/java | |
| parent | 4f2cf10ed2459a97cddc567a0d454e3857bd54d8 (diff) | |
Tidy up generation of WASM structured instructions
Diffstat (limited to 'src/main/java')
| -rw-r--r-- | src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java | 192 |
1 files changed, 145 insertions, 47 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 bbf8298d..fc723883 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java @@ -202,23 +202,19 @@ public class WasmPatioCodeGen { case PatioIf patioIf -> { context = generateOperand(patioIf.condition(), context); - var trueBodyResult = generateBlock(patioIf.trueBody(), context); - var trueBody = trueBodyResult.value; - context = trueBodyResult.context; - - var falseBodyResult = generateBlock(patioIf.falseBody(), context); - var falseBody = falseBodyResult.value; - context = falseBodyResult.context; - - context = context.addInstruction(new WasmIf( - new WasmBlockType( - patioIf.targets().stream() - .map(patioTarget -> patioOperandToWasmValueType(patioTarget)) - .toList() - ), - trueBody, - falseBody - )); + var wasmBlockType = new WasmBlockType( + patioIf.targets().stream() + .map(patioTarget -> patioOperandToWasmValueType(patioTarget)) + .toList() + ); + + context = context.enterIfInstruction(wasmBlockType); + context = generateBlockBody(patioIf.trueBody(), context); + + context = context.enterElse(); + context = generateBlockBody(patioIf.falseBody(), context); + + context = context.exitIfInstruction(); for (var patioTarget : Lists.reversed(patioIf.targets())) { context = popIntoPatioLocal(patioTarget, context); @@ -261,20 +257,11 @@ public class WasmPatioCodeGen { ); case PatioLoop patioLoop -> { - context = context.enterBlock(); + context = context.enterBlockInstruction(); + context = context.enterLoopInstruction(); context = generateInstructions(patioLoop.body(), context); - var bodyInstructions = context.instructions; - context = context.exitBlock(); - - context = context.addInstruction(new WasmBlock( - new WasmBlockType(List.of()), - List.of( - new WasmLoop( - new WasmBlockType(List.of()), - bodyInstructions - ) - ) - )); + context = context.exitLoopInstruction(); + context = context.exitBlockInstruction(); yield context; } @@ -342,21 +329,17 @@ public class WasmPatioCodeGen { }; } - private static Context.Result<List<WasmInstruction>> generateBlock( + private static Context generateBlockBody( PatioBlock block, Context context ) { - context = context.enterBlock(); context = generateInstructions(block.body(), context); for (var patioResult : block.results()) { context = generateOperand(patioResult, context); } - var wasmBody = context.instructions; - context = context.exitBlock(); - - return context.toResult(wasmBody); + return context; } private static Context generateBinaryOperation( @@ -562,7 +545,9 @@ public class WasmPatioCodeGen { module, P.vector(), P.stack(), - patioLocalNameToWasmLocalIndex + patioLocalNameToWasmLocalIndex, + new NullStructuredInstructionBuilder(), + P.stack() ); } @@ -570,17 +555,23 @@ public class WasmPatioCodeGen { private final PVector<WasmInstruction> instructions; private final PStack<PVector<WasmInstruction>> instructionsStack; private final PMap<String, WasmLocalIndex> patioLocalNameToWasmLocalIndex; + private final WasmStructuredInstructionBuilder structuredInstructionBuilder; + private final PStack<WasmStructuredInstructionBuilder> structuredInstructionBuilderStack; private Context( WasmModule module, PVector<WasmInstruction> instructions, PStack<PVector<WasmInstruction>> instructionsStack, - PMap<String, WasmLocalIndex> patioLocalNameToWasmLocalIndex + PMap<String, WasmLocalIndex> patioLocalNameToWasmLocalIndex, + WasmStructuredInstructionBuilder structuredInstructionBuilder, + PStack<WasmStructuredInstructionBuilder> structuredInstructionBuilderStack ) { this.module = module; this.instructions = instructions; this.instructionsStack = instructionsStack; this.patioLocalNameToWasmLocalIndex = patioLocalNameToWasmLocalIndex; + this.structuredInstructionBuilder = structuredInstructionBuilder; + this.structuredInstructionBuilderStack = structuredInstructionBuilderStack; } private Context addType(WasmFuncType type) { @@ -588,7 +579,9 @@ public class WasmPatioCodeGen { this.module.addType(type), this.instructions, this.instructionsStack, - this.patioLocalNameToWasmLocalIndex + this.patioLocalNameToWasmLocalIndex, + this.structuredInstructionBuilder, + this.structuredInstructionBuilderStack ); } @@ -597,7 +590,9 @@ public class WasmPatioCodeGen { this.module, this.instructions.plus(instruction), this.instructionsStack, - this.patioLocalNameToWasmLocalIndex + this.patioLocalNameToWasmLocalIndex, + this.structuredInstructionBuilder, + this.structuredInstructionBuilderStack ); } @@ -605,29 +600,132 @@ public class WasmPatioCodeGen { return this.patioLocalNameToWasmLocalIndex.get(patioLocalRef.name()); } - public Context enterBlock() { + public Context enterBlockInstruction() { return new Context( this.module, P.vector(), this.instructionsStack.plus(this.instructions), - this.patioLocalNameToWasmLocalIndex + this.patioLocalNameToWasmLocalIndex, + new WasmBlockInstructionBuilder(), + this.structuredInstructionBuilderStack.plus(this.structuredInstructionBuilder) ); } - public Context exitBlock() { + public Context exitBlockInstruction() { + // TODO: verify matching enter/exit? + return exitStructuredInstruction(); + } + + public Context enterLoopInstruction() { return new Context( this.module, + P.vector(), + this.instructionsStack.plus(this.instructions), + this.patioLocalNameToWasmLocalIndex, + new WasmLoopInstructionBuilder(), + this.structuredInstructionBuilderStack.plus(this.structuredInstructionBuilder) + ); + } + + public Context exitLoopInstruction() { + // TODO: verify matching enter/exit? + return exitStructuredInstruction(); + } + + public Context enterIfInstruction(WasmBlockType blockType) { + return new Context( + this.module, + P.vector(), + this.instructionsStack.plus(this.instructions), + this.patioLocalNameToWasmLocalIndex, + new WasmIfInstructionBuilder(blockType), + this.structuredInstructionBuilderStack.plus(this.structuredInstructionBuilder) + ); + } + + public Context enterElse() { + return new Context( + this.module, + P.vector(), + this.instructionsStack, + this.patioLocalNameToWasmLocalIndex, + this.structuredInstructionBuilder.enterElse(this.instructions), + this.structuredInstructionBuilderStack + ); + } + + public Context exitIfInstruction() { + // TODO: verify matching enter/exit? + return exitStructuredInstruction(); + } + + public Context exitStructuredInstruction() { + var context = new Context( + this.module, this.instructionsStack.get(0), this.instructionsStack.minus(0), - this.patioLocalNameToWasmLocalIndex + this.patioLocalNameToWasmLocalIndex, + this.structuredInstructionBuilderStack.get(0), + this.structuredInstructionBuilderStack.minus(0) ); + + var instruction = this.structuredInstructionBuilder + .exit(this.instructions); + + return context.addInstruction(instruction); + } + } + + private interface WasmStructuredInstructionBuilder { + WasmInstruction exit(PVector<WasmInstruction> instructions); + + default WasmStructuredInstructionBuilder enterElse(PVector<WasmInstruction> instructions) { + throw new UnsupportedOperationException(); } + } + + private static class NullStructuredInstructionBuilder implements WasmStructuredInstructionBuilder { + @Override + public WasmInstruction exit(PVector<WasmInstruction> instructions) { + throw new UnsupportedOperationException(); + } + } + + private static class WasmBlockInstructionBuilder implements WasmStructuredInstructionBuilder { + @Override + public WasmInstruction exit(PVector<WasmInstruction> instructions) { + return new WasmBlock(new WasmBlockType(List.of()), instructions); + } + } - private <T> Result<T> toResult(T value) { - return new Result<>(value, this); + private static class WasmLoopInstructionBuilder implements WasmStructuredInstructionBuilder { + @Override + public WasmInstruction exit(PVector<WasmInstruction> instructions) { + return new WasmLoop(new WasmBlockType(List.of()), instructions); } + } + + private record WasmIfInstructionBuilder( + WasmBlockType blockType + ) implements WasmStructuredInstructionBuilder { + @Override + public WasmInstruction exit(PVector<WasmInstruction> instructions) { + throw new IllegalStateException("if instruction without else not supported"); + } + + @Override + public WasmStructuredInstructionBuilder enterElse(PVector<WasmInstruction> instructions) { + return new WasmIfElseInstructionBuilder(blockType, instructions); + } + } - private record Result<T>(T value, Context context) { + private record WasmIfElseInstructionBuilder( + WasmBlockType blockType, + PVector<WasmInstruction> ifTrue + ) implements WasmStructuredInstructionBuilder { + @Override + public WasmInstruction exit(PVector<WasmInstruction> instructions) { + return new WasmIf(blockType, ifTrue, instructions); } } } |
