From 71c588ca231d275c5263b3e9ca5f7f57c4e048a1 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 30 Jun 2023 19:35:21 +0100 Subject: Add field-load instruction --- .../backends/llvm/LlvmCodeGenFieldLoadTests.java | 41 ++++++++++++++++++++++ .../compiler/backends/llvm/LlvmCodeGenTesting.java | 34 ++++++++++++++++++ .../backends/wasm/WasmCodeGenFieldLoadTests.java | 38 ++++++++++++++++++++ .../stackir/InstructionSerializerTests.java | 12 +++++++ .../stackir/instructions/Instructions.java | 4 +++ 5 files changed, 129 insertions(+) create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenFieldLoadTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenTesting.java create mode 100644 src/test/java/org/shedlang/compiler/backends/wasm/WasmCodeGenFieldLoadTests.java (limited to 'src/test/java') diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenFieldLoadTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenFieldLoadTests.java new file mode 100644 index 00000000..6bb8c5c7 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenFieldLoadTests.java @@ -0,0 +1,41 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableLocal; +import org.shedlang.compiler.stackir.instructions.Instructions; +import org.shedlang.compiler.testing.snapshots.SnapshotResolver; +import org.shedlang.compiler.testing.snapshots.Snapshotter; +import org.shedlang.compiler.typechecker.TypeCheckerContext; +import org.shedlang.compiler.types.NamespaceName; +import org.shedlang.compiler.types.Types; +import org.shedlang.compiler.util.P; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.shedlang.compiler.backends.llvm.LlvmCodeGenTesting.serializeContext; + +@ExtendWith({SnapshotResolver.class}) +public class LlvmCodeGenFieldLoadTests { + @Test + public void fieldLoadPopsReceiverAndPushesFieldValue(Snapshotter snapshotter) throws IOException { + var namespaceName = new NamespaceName(List.of("Example", "Project")); + var instruction = Instructions.fieldLoad(namespaceName, "y"); + var typeInfo = TypeCheckerContext.EMPTY + .addNamespaceFields(namespaceName, P.orderedMap( + Map.entry("x", Types.INT), + Map.entry("y", Types.INT), + Map.entry("z", Types.INT) + )) + .toTypeInfo(); + var context = LlvmCodeGenContext.fromTypeInfo(typeInfo) + .push(new LlvmVariableLocal("a")) + .push(new LlvmVariableLocal("b")); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + snapshotter.assertSnapshot(serializeContext(result)); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenTesting.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenTesting.java new file mode 100644 index 00000000..e480f3da --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenTesting.java @@ -0,0 +1,34 @@ +package org.shedlang.compiler.backends.llvm; + +import org.shedlang.compiler.backends.llvm.ir.LlvmIrSerializer; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmReturnVoid; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; + +import java.io.IOException; +import java.util.List; + +public class LlvmCodeGenTesting { + private LlvmCodeGenTesting() { + } + + public static String serializeContext(LlvmCodeGenContext context) throws IOException { + context = context.addTerminatorInstruction(new LlvmReturnVoid()); + var function = context.toFunction("f", LlvmTypes.VOID, List.of()); + var module = context.addTopLevelEntity(function).toModule(); + + var builder = new StringBuilder(); + + builder.append("Stack:\n"); + for (var operand : context.stack()) { + builder.append(" * "); + LlvmIrSerializer.serializeOperand(operand, builder); + builder.append("\n"); + } + builder.append("\n"); + + builder.append("Module:\n"); + LlvmIrSerializer.serializeModule(module, builder); + + return builder.toString(); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/wasm/WasmCodeGenFieldLoadTests.java b/src/test/java/org/shedlang/compiler/backends/wasm/WasmCodeGenFieldLoadTests.java new file mode 100644 index 00000000..03f1c457 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/wasm/WasmCodeGenFieldLoadTests.java @@ -0,0 +1,38 @@ +package org.shedlang.compiler.backends.wasm; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.shedlang.compiler.stackir.instructions.Instructions; +import org.shedlang.compiler.testing.snapshots.SnapshotResolver; +import org.shedlang.compiler.testing.snapshots.Snapshotter; +import org.shedlang.compiler.typechecker.TypeCheckerContext; +import org.shedlang.compiler.types.NamespaceName; +import org.shedlang.compiler.types.Types; +import org.shedlang.compiler.util.P; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.shedlang.compiler.backends.wasm.WasmCodeGenTesting.objdumpContext; + +@ExtendWith({SnapshotResolver.class}) +public class WasmCodeGenFieldLoadTests { + @Test + public void fieldLoadPopsReceiverAndPushesFieldValue(Snapshotter snapshotter) throws IOException, InterruptedException { + var namespaceName = new NamespaceName(List.of("Example", "Project")); + var instruction = Instructions.fieldLoad(namespaceName, "y"); + var typeInfo = TypeCheckerContext.EMPTY + .addNamespaceFields(namespaceName, P.orderedMap( + Map.entry("x", Types.INT), + Map.entry("y", Types.INT), + Map.entry("z", Types.INT) + )) + .toTypeInfo(); + var context = WasmCodeGenContext.fromTypeInfo(typeInfo); + + var result = WasmCodeGen.generateInstruction(instruction, context); + + snapshotter.assertSnapshot(objdumpContext(result)); + } +} diff --git a/src/test/java/org/shedlang/compiler/stackir/InstructionSerializerTests.java b/src/test/java/org/shedlang/compiler/stackir/InstructionSerializerTests.java index 5877613d..74e018f3 100644 --- a/src/test/java/org/shedlang/compiler/stackir/InstructionSerializerTests.java +++ b/src/test/java/org/shedlang/compiler/stackir/InstructionSerializerTests.java @@ -63,6 +63,18 @@ public class InstructionSerializerTests { assertThat(string, equalTo("(discard)")); } + @Test + public void canSerializeFieldLoad() { + var instruction = Instructions.fieldLoad( + new NamespaceName(List.of("Example", "Lib")), + "x" + ); + + var string = serialize(instruction); + + assertThat(string, equalTo("(field-load \"Example/Lib\" \"x\")")); + } + @Test public void canSerializeLocalLoad() { var instruction = Instructions.localLoad("x"); diff --git a/src/test/java/org/shedlang/compiler/stackir/instructions/Instructions.java b/src/test/java/org/shedlang/compiler/stackir/instructions/Instructions.java index 6108947b..adc0731b 100644 --- a/src/test/java/org/shedlang/compiler/stackir/instructions/Instructions.java +++ b/src/test/java/org/shedlang/compiler/stackir/instructions/Instructions.java @@ -18,6 +18,10 @@ public class Instructions { return new DiscardInstruction(Sources.NULL); } + public static Instruction fieldLoad(NamespaceName namespaceName, String fieldName) { + return new FieldLoadInstruction(namespaceName, fieldName, Sources.NULL); + } + public static Instruction localLoad(String name) { return new LocalLoadInstruction(name, Sources.NULL); } -- cgit v1.2.3