From 630842133c5de6edd61b28d0a5d704377c1bd962 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 20 Jun 2023 18:52:09 +0100 Subject: Rename LlvmCompiler to LlvmCodeGen --- .../backends/llvm/LlvmCodeGenCallTests.java | 128 +++++++++++++++++++ .../llvm/LlvmCodeGenDefineFunctionTests.java | 136 +++++++++++++++++++++ .../backends/llvm/LlvmCodeGenDiscardTests.java | 24 ++++ .../backends/llvm/LlvmCodeGenLocalLoadTests.java | 35 ++++++ .../backends/llvm/LlvmCodeGenLocalStoreTests.java | 36 ++++++ .../llvm/LlvmCodeGenNamespaceFieldStoreTests.java | 71 +++++++++++ .../backends/llvm/LlvmCodeGenPushBoolTests.java | 32 +++++ .../backends/llvm/LlvmCodeGenPushIntTests.java | 23 ++++ .../backends/llvm/LlvmCodeGenPushStringTests.java | 57 +++++++++ .../backends/llvm/LlvmCodeGenPushUnitTests.java | 21 ++++ .../backends/llvm/LlvmCodeGenReturnTests.java | 43 +++++++ .../backends/llvm/LlvmCompilerCallTests.java | 128 ------------------- .../llvm/LlvmCompilerDefineFunctionTests.java | 136 --------------------- .../backends/llvm/LlvmCompilerDiscardTests.java | 24 ---- .../backends/llvm/LlvmCompilerLocalLoadTests.java | 35 ------ .../backends/llvm/LlvmCompilerLocalStoreTests.java | 36 ------ .../llvm/LlvmCompilerNamespaceFieldStoreTests.java | 71 ----------- .../backends/llvm/LlvmCompilerPushBoolTests.java | 32 ----- .../backends/llvm/LlvmCompilerPushIntTests.java | 23 ---- .../backends/llvm/LlvmCompilerPushStringTests.java | 57 --------- .../backends/llvm/LlvmCompilerPushUnitTests.java | 21 ---- .../backends/llvm/LlvmCompilerReturnTests.java | 43 ------- 22 files changed, 606 insertions(+), 606 deletions(-) create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenCallTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenDefineFunctionTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenDiscardTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenLocalLoadTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenLocalStoreTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenNamespaceFieldStoreTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushBoolTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushIntTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushStringTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushUnitTests.java create mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenReturnTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerCallTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerDefineFunctionTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerDiscardTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalLoadTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalStoreTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerNamespaceFieldStoreTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushBoolTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushIntTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushStringTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushUnitTests.java delete mode 100644 src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerReturnTests.java (limited to 'src/test/java') diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenCallTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenCallTests.java new file mode 100644 index 00000000..a5c56a7b --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenCallTests.java @@ -0,0 +1,128 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmCall; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmGetElementPtr; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmIntToPtr; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmLoad; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; +import org.shedlang.compiler.stackir.instructions.Instructions; + +import java.util.List; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.*; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class LlvmCodeGenCallTests { + @Test + public void canCallFunctionWithNoArgs() { + var instruction = Instructions.call(0, List.of()); + var context = LlvmCodeGenContext.EMPTY + .push(LlvmIr.variableLocal("x")) + .push(LlvmIr.variableLocal("f")); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence( + instanceOf( + LlvmIntToPtr.class, + has("target", x -> x.target(), isLlvmVariableLocal("closurePointer__0")), + has("sourceType", x -> x.sourceType(), equalTo(LlvmCodeGenTypes.VALUE_TYPE)), + has("value", x -> x.value(), isLlvmVariableLocal("f")) + ), + instanceOf( + LlvmGetElementPtr.class, + has("target", x -> x.target(), isLlvmVariableLocal("closureFunctionPointerPointer__0")), + has("pointerType", x -> x.pointerType(), equalTo(LlvmCodeGenClosures.CALLABLE_TYPES.closurePointer())), + has("pointer", x -> x.pointer(), isLlvmVariableLocal("closurePointer__0")), + has("indexes", x -> x.indexes(), isSequence( + isLlvmTypedOperand(LlvmTypes.INT_64, isLlvmOperandInt(0)), + isLlvmTypedOperand(LlvmTypes.INT_32, isLlvmOperandInt(0)) + )) + ), + instanceOf( + LlvmLoad.class, + has("target", x -> x.target(), isLlvmVariableLocal("closureFunctionPointer__0")), + has("type", x -> x.type(), equalTo(LlvmCodeGenClosures.CALLABLE_TYPES.closureFunctionPointer())), + has("pointer", x -> x.pointer(), isLlvmVariableLocal("closureFunctionPointerPointer__0")) + ), + instanceOf( + LlvmCall.class, + has("target", x -> x.target(), isOptionalOf(isLlvmVariableLocal("tmp__0"))), + has("returnType", x -> x.returnType(), equalTo(LlvmCodeGenTypes.VALUE_TYPE)), + has("functionPointer", x -> x.functionPointer(), isLlvmVariableLocal("closureFunctionPointer__0")), + has("args", x -> x.args(), isSequence( + isLlvmTypedOperand( + LlvmCodeGenClosures.CALLABLE_TYPES.closurePointer(), + isLlvmVariableLocal("closurePointer__0") + ) + )) + ) + )); + assertThat(result.stack(), isSequence( + isLlvmVariableLocal("tmp__0"), + isLlvmVariableLocal("x") + )); + } + + @Test + public void canCallFunctionWithArgs() { + var instruction = Instructions.call(2, List.of("b", "a")); + var context = LlvmCodeGenContext.EMPTY + .push(LlvmIr.variableLocal("x")) + .push(LlvmIr.variableLocal("f")) + .push(LlvmIr.variableLocal("positional1")) + .push(LlvmIr.variableLocal("positional2")) + .push(LlvmIr.variableLocal("namedB")) + .push(LlvmIr.variableLocal("namedA")); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence( + instanceOf( + LlvmIntToPtr.class, + has("target", x -> x.target(), isLlvmVariableLocal("closurePointer__0")), + has("sourceType", x -> x.sourceType(), equalTo(LlvmCodeGenTypes.VALUE_TYPE)), + has("value", x -> x.value(), isLlvmVariableLocal("f")) + ), + instanceOf( + LlvmGetElementPtr.class, + has("target", x -> x.target(), isLlvmVariableLocal("closureFunctionPointerPointer__0")), + has("pointerType", x -> x.pointerType(), equalTo(LlvmCodeGenClosures.CALLABLE_TYPES.closurePointer())), + has("pointer", x -> x.pointer(), isLlvmVariableLocal("closurePointer__0")), + has("indexes", x -> x.indexes(), isSequence( + isLlvmTypedOperand(LlvmTypes.INT_64, isLlvmOperandInt(0)), + isLlvmTypedOperand(LlvmTypes.INT_32, isLlvmOperandInt(0)) + )) + ), + instanceOf( + LlvmLoad.class, + has("target", x -> x.target(), isLlvmVariableLocal("closureFunctionPointer__0")), + has("type", x -> x.type(), equalTo(LlvmCodeGenClosures.CALLABLE_TYPES.closureFunctionPointer())), + has("pointer", x -> x.pointer(), isLlvmVariableLocal("closureFunctionPointerPointer__0")) + ), + instanceOf( + LlvmCall.class, + has("target", x -> x.target(), isOptionalOf(isLlvmVariableLocal("tmp__0"))), + has("returnType", x -> x.returnType(), equalTo(LlvmCodeGenTypes.VALUE_TYPE)), + has("functionPointer", x -> x.functionPointer(), isLlvmVariableLocal("closureFunctionPointer__0")), + has("args", x -> x.args(), isSequence( + isLlvmTypedOperand( + LlvmCodeGenClosures.CALLABLE_TYPES.closurePointer(), + isLlvmVariableLocal("closurePointer__0") + ), + isLlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, isLlvmVariableLocal("positional1")), + isLlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, isLlvmVariableLocal("positional2")), + isLlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, isLlvmVariableLocal("namedA")), + isLlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, isLlvmVariableLocal("namedB")) + )) + ) + )); + assertThat(result.stack(), isSequence( + isLlvmVariableLocal("tmp__0"), + isLlvmVariableLocal("x") + )); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenDefineFunctionTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenDefineFunctionTests.java new file mode 100644 index 00000000..f0e3cf23 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenDefineFunctionTests.java @@ -0,0 +1,136 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.ast.typed.FreeVariables; +import org.shedlang.compiler.backends.llvm.ir.LlvmIrSerializer; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; +import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; +import org.shedlang.compiler.sources.Sources; +import org.shedlang.compiler.stackir.instructions.DefineFunctionInstruction; +import org.shedlang.compiler.stackir.instructions.Instructions; +import org.zwobble.precisely.Matcher; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmVariableLocal; +import static org.shedlang.compiler.util.Iterables.forEachInterspersed; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class LlvmCodeGenDefineFunctionTests { + @Test + public void canDefineMinimalFunction() throws IOException { + var instruction = new DefineFunctionInstruction( + "f", + List.of(), + List.of(), + FreeVariables.empty(), + List.of( + Instructions.pushUnit(), + Instructions.return_() + ), + Sources.NULL + ); + var context = LlvmCodeGenContext.EMPTY; + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + var topLevelEntities = new StringBuilder(); + forEachInterspersed( + result.topLevelEntities(), + topLevelEntity -> LlvmIrSerializer.serializeTopLevelEntity(topLevelEntity, topLevelEntities), + () -> topLevelEntities.append("\n") + ); + assertThat(topLevelEntities.toString(), equalTo(""" + define i64 @shed__fun__f__0(ptr %closurePointer__0) { + ret i64 0 + } + """)); + + var instructions = new StringBuilder(); + forEachInterspersed( + result.instructions(), + x -> LlvmIrSerializer.serializeInstruction(x, instructions), + () -> instructions.append("\n") + ); + assertThat(instructions.toString(), equalTo(""" + %sizePtr__0 = getelementptr {ptr, [0 x i64]}, ptr null, i64 0 + %size__0 = ptrtoint ptr %sizePtr__0 to i64 + %closurePointer__0 = call ptr @shed__runtime__alloc(i64 %size__0) + %closureFunctionPointerPointer__0 = getelementptr {ptr, [0 x i64]}, ptr %closurePointer__0, i64 0, i32 0 + store ptr @shed__fun__f__0, ptr %closureFunctionPointerPointer__0 + %closureValue__0 = ptrtoint ptr %closurePointer__0 to i64""")); + + assertThat(result.stack(), isSequence( + isLlvmVariableLocal("closureValue__0") + )); + assertThat(result.locals().entrySet(), isSequence()); + } + + @Test + public void freeVariablesAreStoredInAndLoadedFromEnvironment() throws IOException { + var instruction = new DefineFunctionInstruction( + "f", + List.of(), + List.of(), + FreeVariables.of("a", "b"), + List.of( + Instructions.localLoad("a"), + Instructions.return_() + ), + Sources.NULL + ); + var context = LlvmCodeGenContext.EMPTY + .addLocal("a", LlvmIr.operandInt(1)) + .addLocal("b", LlvmIr.operandInt(2)); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + var topLevelEntities = new StringBuilder(); + forEachInterspersed( + result.topLevelEntities(), + topLevelEntity -> LlvmIrSerializer.serializeTopLevelEntity(topLevelEntity, topLevelEntities), + () -> topLevelEntities.append("\n") + ); + assertThat(topLevelEntities.toString(), equalTo(""" + define i64 @shed__fun__f__0(ptr %closurePointer__0) { + %closureFreeVariablePointer__a__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 1, i64 0 + %closureFreeVariable__a__0 = load i64, ptr %closureFreeVariablePointer__a__0 + %closureFreeVariablePointer__b__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 1, i64 1 + %closureFreeVariable__b__0 = load i64, ptr %closureFreeVariablePointer__b__0 + ret i64 %closureFreeVariable__a__0 + } + """)); + + var instructions = new StringBuilder(); + forEachInterspersed( + result.instructions(), + x -> LlvmIrSerializer.serializeInstruction(x, instructions), + () -> instructions.append("\n") + ); + assertThat(instructions.toString(), equalTo(""" + %sizePtr__0 = getelementptr {ptr, [2 x i64]}, ptr null, i64 0 + %size__0 = ptrtoint ptr %sizePtr__0 to i64 + %closurePointer__0 = call ptr @shed__runtime__alloc(i64 %size__0) + %closureFunctionPointerPointer__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 0 + store ptr @shed__fun__f__0, ptr %closureFunctionPointerPointer__0 + %closureFreeVariablePointer__a__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 1, i64 0 + store i64 1, ptr %closureFreeVariablePointer__a__0 + %closureFreeVariablePointer__b__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 1, i64 1 + store i64 2, ptr %closureFreeVariablePointer__b__0 + %closureValue__0 = ptrtoint ptr %closurePointer__0 to i64""")); + + assertThat(result.stack(), isSequence( + isLlvmVariableLocal("closureValue__0") + )); + } + + private static Matcher> isLocal(String name, Matcher operand) { + return allOf( + has("name", x -> x.getKey(), equalTo(name)), + has("operand", x -> x.getValue(), operand) + ); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenDiscardTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenDiscardTests.java new file mode 100644 index 00000000..799442eb --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenDiscardTests.java @@ -0,0 +1,24 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; +import org.shedlang.compiler.stackir.instructions.Instructions; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.isSequence; + +public class LlvmCodeGenDiscardTests { + @Test + public void discardRemovesTopElementFromStack() { + var instruction = Instructions.discard(); + var context = LlvmCodeGenContext.EMPTY + .push(LlvmIr.operandInt(1)) + .push(LlvmIr.operandInt(2)); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence(isLlvmOperandInt(1))); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenLocalLoadTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenLocalLoadTests.java new file mode 100644 index 00000000..487e184e --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenLocalLoadTests.java @@ -0,0 +1,35 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; +import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; +import org.shedlang.compiler.stackir.instructions.Instructions; +import org.zwobble.precisely.Matcher; + +import java.util.Map; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class LlvmCodeGenLocalLoadTests { + @Test + public void localLoadPushsOperandFromLocalsToStack() { + var instruction = Instructions.localLoad("x"); + var context = LlvmCodeGenContext.EMPTY + .addLocal("x", LlvmIr.operandInt(42)); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence(isLlvmOperandInt(42))); + assertThat(result.locals().entrySet(), isSequence(isLocal("x", isLlvmOperandInt(42)))); + } + + private static Matcher> isLocal(String name, Matcher operand) { + return allOf( + has("name", x -> x.getKey(), equalTo(name)), + has("operand", x -> x.getValue(), operand) + ); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenLocalStoreTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenLocalStoreTests.java new file mode 100644 index 00000000..1461db1b --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenLocalStoreTests.java @@ -0,0 +1,36 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; +import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; +import org.shedlang.compiler.stackir.instructions.Instructions; +import org.zwobble.precisely.Matcher; + +import java.util.Map; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class LlvmCodeGenLocalStoreTests { + @Test + public void localStorePopsFromStackAndUpdatesLocals() { + var instruction = Instructions.localStore("x"); + var context = LlvmCodeGenContext.EMPTY + .push(LlvmIr.operandInt(0)) + .push(LlvmIr.operandInt(1)); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence(isLlvmOperandInt(0))); + assertThat(result.locals().entrySet(), isSequence(isLocal("x", isLlvmOperandInt(1)))); + } + + private static Matcher> isLocal(String name, Matcher operand) { + return allOf( + has("name", x -> x.getKey(), equalTo(name)), + has("operand", x -> x.getValue(), operand) + ); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenNamespaceFieldStoreTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenNamespaceFieldStoreTests.java new file mode 100644 index 00000000..191361e7 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenNamespaceFieldStoreTests.java @@ -0,0 +1,71 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmGetElementPtr; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmStore; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; +import org.shedlang.compiler.stackir.instructions.Instructions; +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.util.List; +import java.util.Map; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.*; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class LlvmCodeGenNamespaceFieldStoreTests { + @Test + public void namespaceFieldStorePopsFromStackAndUpdatesFieldOnNamespace() { + var namespaceName = new NamespaceName(List.of("Example", "Project")); + var instruction = Instructions.namespaceFieldStore(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(LlvmIr.operandInt(0)) + .push(LlvmIr.operandInt(1)); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence( + instanceOf( + LlvmGetElementPtr.class, + has("target", x -> x.target(), isLlvmVariableLocal("fieldPointer__y__0")), + has( + "pointerType", + x -> x.pointerType(), + equalTo(LlvmTypes.pointer(LlvmTypes.structure(List.of( + LlvmTypes.INT_64, + LlvmTypes.INT_64, + LlvmTypes.INT_64 + )))) + ), + has( + "pointer", + x -> x.pointer(), + isLlvmVariableGlobal("shed__namespace__Example_Project") + ), + has("indexes", x -> x.indexes(), isSequence( + isLlvmTypedOperand(LlvmTypes.INT_64, isLlvmOperandInt(0)), + isLlvmTypedOperand(LlvmTypes.INT_32, isLlvmOperandInt(1)) + )) + ), + instanceOf( + LlvmStore.class, + has("type", x -> x.type(), equalTo(LlvmTypes.INT_64)), + has("value", x -> x.value(), isLlvmOperandInt(1)), + has("pointer", x -> x.pointer(), isLlvmVariableLocal("fieldPointer__y__0")) + ) + )); + assertThat(result.stack(), isSequence(isLlvmOperandInt(0))); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushBoolTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushBoolTests.java new file mode 100644 index 00000000..cf6bb76a --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushBoolTests.java @@ -0,0 +1,32 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.stackir.instructions.Instructions; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.isSequence; + +public class LlvmCodeGenPushBoolTests { + @Test + public void pushFalseIsCompiledToOperandInStack() { + var instruction = Instructions.pushBool(false); + var context = LlvmCodeGenContext.EMPTY; + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence(isLlvmOperandInt(0))); + } + + @Test + public void pushTrueIsCompiledToOperandInStack() { + var instruction = Instructions.pushBool(true); + var context = LlvmCodeGenContext.EMPTY; + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence(isLlvmOperandInt(1))); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushIntTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushIntTests.java new file mode 100644 index 00000000..cb4711d9 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushIntTests.java @@ -0,0 +1,23 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.stackir.instructions.Instructions; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.isSequence; + +public class LlvmCodeGenPushIntTests { + // TODO: handle larger ints + + @Test + public void pushIntIsCompiledToOperandInStack() { + var instruction = Instructions.pushInt(42); + var context = LlvmCodeGenContext.EMPTY; + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence(isLlvmOperandInt(42))); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushStringTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushStringTests.java new file mode 100644 index 00000000..0504084e --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushStringTests.java @@ -0,0 +1,57 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmGlobalDefinition; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; +import org.shedlang.compiler.stackir.instructions.Instructions; + +import java.util.List; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.*; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class LlvmCodeGenPushStringTests { + @Test + public void pushStringIsCompiledToTopLevelEntityAndReferenceToTopLevelEntity() { + var instruction = Instructions.pushString("hello"); + var context = LlvmCodeGenContext.EMPTY; + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence( + isLlvmOperandPtrToInt( + isLlvmVariableGlobal("shed__string__0"), + equalTo(LlvmTypes.INT_64) + ) + )); + assertThat(result.topLevelEntities(), isSequence( + instanceOf( + LlvmGlobalDefinition.class, + has("name", x -> x.name(), equalTo("shed__string__0")), + has("type", x -> x.type(), equalTo(LlvmTypes.structure(List.of( + LlvmTypes.INT_64, + LlvmTypes.array(5, LlvmTypes.INT_8) + )))), + has("value", x -> x.value(), isOptionalOf(equalTo(LlvmIr.operandStructure(List.of( + LlvmIr.typedOperand(LlvmTypes.INT_64, LlvmIr.operandInt(5)), + LlvmIr.typedOperand( + LlvmTypes.array(5, LlvmTypes.INT_8), + LlvmIr.operandArray(LlvmTypes.INT_8, List.of( + LlvmIr.operandInt(104), + LlvmIr.operandInt(101), + LlvmIr.operandInt(108), + LlvmIr.operandInt(108), + LlvmIr.operandInt(111) + )) + ) + ))))), + has("constant", x -> x.constant(), equalTo(true)), + has("isPrivate", x -> x.isPrivate(), equalTo(true)), + has("unnamedAddr", x -> x.unnamedAddr(), equalTo(true)) + ) + )); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushUnitTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushUnitTests.java new file mode 100644 index 00000000..2da03372 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenPushUnitTests.java @@ -0,0 +1,21 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.stackir.instructions.Instructions; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.isSequence; + +public class LlvmCodeGenPushUnitTests { + @Test + public void pushUnitIsCompiledToOperandInStack() { + var instruction = Instructions.pushUnit(); + var context = LlvmCodeGenContext.EMPTY; + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence(isLlvmOperandInt(0))); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenReturnTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenReturnTests.java new file mode 100644 index 00000000..66afa268 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenReturnTests.java @@ -0,0 +1,43 @@ +package org.shedlang.compiler.backends.llvm; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; +import org.shedlang.compiler.stackir.instructions.Instructions; + +import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.*; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.equalTo; +import static org.zwobble.precisely.Matchers.isSequence; + +public class LlvmCodeGenReturnTests { + @Test + public void returnCompilesToReturnInstruction() { + var instruction = Instructions.return_(); + var add = LlvmIr.add( + LlvmIr.variableLocal("x"), + LlvmTypes.INT_64, + LlvmIr.variableLocal("left"), + LlvmIr.variableLocal("right") + ); + var context = LlvmCodeGenContext.EMPTY + .addInstruction(add) + .push(LlvmIr.variableLocal("a")) + .push(LlvmIr.variableLocal("b")); + + var result = LlvmCodeGen.generateInstruction(instruction, context); + + assertThat(result.basicBlocks(), isSequence( + isLlvmBasicBlock( + isSequence( + equalTo(add) + ), + isLlvmReturn(LlvmCodeGenTypes.VALUE_TYPE, isLlvmVariableLocal("b")) + ) + )); + assertThat(result.instructions(), isSequence()); + assertThat(result.stack(), isSequence( + isLlvmVariableLocal("a") + )); + } +} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerCallTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerCallTests.java deleted file mode 100644 index f43c7bf6..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerCallTests.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmCall; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmGetElementPtr; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmIntToPtr; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmLoad; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; -import org.shedlang.compiler.stackir.instructions.Instructions; - -import java.util.List; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.*; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.*; - -public class LlvmCompilerCallTests { - @Test - public void canCallFunctionWithNoArgs() { - var instruction = Instructions.call(0, List.of()); - var context = LlvmCompilerContext.EMPTY - .push(LlvmIr.variableLocal("x")) - .push(LlvmIr.variableLocal("f")); - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence( - instanceOf( - LlvmIntToPtr.class, - has("target", x -> x.target(), isLlvmVariableLocal("closurePointer__0")), - has("sourceType", x -> x.sourceType(), equalTo(LlvmCompilerTypes.VALUE_TYPE)), - has("value", x -> x.value(), isLlvmVariableLocal("f")) - ), - instanceOf( - LlvmGetElementPtr.class, - has("target", x -> x.target(), isLlvmVariableLocal("closureFunctionPointerPointer__0")), - has("pointerType", x -> x.pointerType(), equalTo(LlvmCompilerClosures.CALLABLE_TYPES.closurePointer())), - has("pointer", x -> x.pointer(), isLlvmVariableLocal("closurePointer__0")), - has("indexes", x -> x.indexes(), isSequence( - isLlvmTypedOperand(LlvmTypes.INT_64, isLlvmOperandInt(0)), - isLlvmTypedOperand(LlvmTypes.INT_32, isLlvmOperandInt(0)) - )) - ), - instanceOf( - LlvmLoad.class, - has("target", x -> x.target(), isLlvmVariableLocal("closureFunctionPointer__0")), - has("type", x -> x.type(), equalTo(LlvmCompilerClosures.CALLABLE_TYPES.closureFunctionPointer())), - has("pointer", x -> x.pointer(), isLlvmVariableLocal("closureFunctionPointerPointer__0")) - ), - instanceOf( - LlvmCall.class, - has("target", x -> x.target(), isOptionalOf(isLlvmVariableLocal("tmp__0"))), - has("returnType", x -> x.returnType(), equalTo(LlvmCompilerTypes.VALUE_TYPE)), - has("functionPointer", x -> x.functionPointer(), isLlvmVariableLocal("closureFunctionPointer__0")), - has("args", x -> x.args(), isSequence( - isLlvmTypedOperand( - LlvmCompilerClosures.CALLABLE_TYPES.closurePointer(), - isLlvmVariableLocal("closurePointer__0") - ) - )) - ) - )); - assertThat(result.stack(), isSequence( - isLlvmVariableLocal("tmp__0"), - isLlvmVariableLocal("x") - )); - } - - @Test - public void canCallFunctionWithArgs() { - var instruction = Instructions.call(2, List.of("b", "a")); - var context = LlvmCompilerContext.EMPTY - .push(LlvmIr.variableLocal("x")) - .push(LlvmIr.variableLocal("f")) - .push(LlvmIr.variableLocal("positional1")) - .push(LlvmIr.variableLocal("positional2")) - .push(LlvmIr.variableLocal("namedB")) - .push(LlvmIr.variableLocal("namedA")); - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence( - instanceOf( - LlvmIntToPtr.class, - has("target", x -> x.target(), isLlvmVariableLocal("closurePointer__0")), - has("sourceType", x -> x.sourceType(), equalTo(LlvmCompilerTypes.VALUE_TYPE)), - has("value", x -> x.value(), isLlvmVariableLocal("f")) - ), - instanceOf( - LlvmGetElementPtr.class, - has("target", x -> x.target(), isLlvmVariableLocal("closureFunctionPointerPointer__0")), - has("pointerType", x -> x.pointerType(), equalTo(LlvmCompilerClosures.CALLABLE_TYPES.closurePointer())), - has("pointer", x -> x.pointer(), isLlvmVariableLocal("closurePointer__0")), - has("indexes", x -> x.indexes(), isSequence( - isLlvmTypedOperand(LlvmTypes.INT_64, isLlvmOperandInt(0)), - isLlvmTypedOperand(LlvmTypes.INT_32, isLlvmOperandInt(0)) - )) - ), - instanceOf( - LlvmLoad.class, - has("target", x -> x.target(), isLlvmVariableLocal("closureFunctionPointer__0")), - has("type", x -> x.type(), equalTo(LlvmCompilerClosures.CALLABLE_TYPES.closureFunctionPointer())), - has("pointer", x -> x.pointer(), isLlvmVariableLocal("closureFunctionPointerPointer__0")) - ), - instanceOf( - LlvmCall.class, - has("target", x -> x.target(), isOptionalOf(isLlvmVariableLocal("tmp__0"))), - has("returnType", x -> x.returnType(), equalTo(LlvmCompilerTypes.VALUE_TYPE)), - has("functionPointer", x -> x.functionPointer(), isLlvmVariableLocal("closureFunctionPointer__0")), - has("args", x -> x.args(), isSequence( - isLlvmTypedOperand( - LlvmCompilerClosures.CALLABLE_TYPES.closurePointer(), - isLlvmVariableLocal("closurePointer__0") - ), - isLlvmTypedOperand(LlvmCompilerTypes.VALUE_TYPE, isLlvmVariableLocal("positional1")), - isLlvmTypedOperand(LlvmCompilerTypes.VALUE_TYPE, isLlvmVariableLocal("positional2")), - isLlvmTypedOperand(LlvmCompilerTypes.VALUE_TYPE, isLlvmVariableLocal("namedA")), - isLlvmTypedOperand(LlvmCompilerTypes.VALUE_TYPE, isLlvmVariableLocal("namedB")) - )) - ) - )); - assertThat(result.stack(), isSequence( - isLlvmVariableLocal("tmp__0"), - isLlvmVariableLocal("x") - )); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerDefineFunctionTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerDefineFunctionTests.java deleted file mode 100644 index c80787c0..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerDefineFunctionTests.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.ast.typed.FreeVariables; -import org.shedlang.compiler.backends.llvm.ir.LlvmIrSerializer; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.sources.Sources; -import org.shedlang.compiler.stackir.instructions.DefineFunctionInstruction; -import org.shedlang.compiler.stackir.instructions.Instructions; -import org.zwobble.precisely.Matcher; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmVariableLocal; -import static org.shedlang.compiler.util.Iterables.forEachInterspersed; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.*; - -public class LlvmCompilerDefineFunctionTests { - @Test - public void canDefineMinimalFunction() throws IOException { - var instruction = new DefineFunctionInstruction( - "f", - List.of(), - List.of(), - FreeVariables.empty(), - List.of( - Instructions.pushUnit(), - Instructions.return_() - ), - Sources.NULL - ); - var context = LlvmCompilerContext.EMPTY; - - var result = LlvmCompiler.compileInstruction(instruction, context); - - var topLevelEntities = new StringBuilder(); - forEachInterspersed( - result.topLevelEntities(), - topLevelEntity -> LlvmIrSerializer.serializeTopLevelEntity(topLevelEntity, topLevelEntities), - () -> topLevelEntities.append("\n") - ); - assertThat(topLevelEntities.toString(), equalTo(""" - define i64 @shed__fun__f__0(ptr %closurePointer__0) { - ret i64 0 - } - """)); - - var instructions = new StringBuilder(); - forEachInterspersed( - result.instructions(), - x -> LlvmIrSerializer.serializeInstruction(x, instructions), - () -> instructions.append("\n") - ); - assertThat(instructions.toString(), equalTo(""" - %sizePtr__0 = getelementptr {ptr, [0 x i64]}, ptr null, i64 0 - %size__0 = ptrtoint ptr %sizePtr__0 to i64 - %closurePointer__0 = call ptr @shed__runtime__alloc(i64 %size__0) - %closureFunctionPointerPointer__0 = getelementptr {ptr, [0 x i64]}, ptr %closurePointer__0, i64 0, i32 0 - store ptr @shed__fun__f__0, ptr %closureFunctionPointerPointer__0 - %closureValue__0 = ptrtoint ptr %closurePointer__0 to i64""")); - - assertThat(result.stack(), isSequence( - isLlvmVariableLocal("closureValue__0") - )); - assertThat(result.locals().entrySet(), isSequence()); - } - - @Test - public void freeVariablesAreStoredInAndLoadedFromEnvironment() throws IOException { - var instruction = new DefineFunctionInstruction( - "f", - List.of(), - List.of(), - FreeVariables.of("a", "b"), - List.of( - Instructions.localLoad("a"), - Instructions.return_() - ), - Sources.NULL - ); - var context = LlvmCompilerContext.EMPTY - .addLocal("a", LlvmIr.operandInt(1)) - .addLocal("b", LlvmIr.operandInt(2)); - - var result = LlvmCompiler.compileInstruction(instruction, context); - - var topLevelEntities = new StringBuilder(); - forEachInterspersed( - result.topLevelEntities(), - topLevelEntity -> LlvmIrSerializer.serializeTopLevelEntity(topLevelEntity, topLevelEntities), - () -> topLevelEntities.append("\n") - ); - assertThat(topLevelEntities.toString(), equalTo(""" - define i64 @shed__fun__f__0(ptr %closurePointer__0) { - %closureFreeVariablePointer__a__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 1, i64 0 - %closureFreeVariable__a__0 = load i64, ptr %closureFreeVariablePointer__a__0 - %closureFreeVariablePointer__b__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 1, i64 1 - %closureFreeVariable__b__0 = load i64, ptr %closureFreeVariablePointer__b__0 - ret i64 %closureFreeVariable__a__0 - } - """)); - - var instructions = new StringBuilder(); - forEachInterspersed( - result.instructions(), - x -> LlvmIrSerializer.serializeInstruction(x, instructions), - () -> instructions.append("\n") - ); - assertThat(instructions.toString(), equalTo(""" - %sizePtr__0 = getelementptr {ptr, [2 x i64]}, ptr null, i64 0 - %size__0 = ptrtoint ptr %sizePtr__0 to i64 - %closurePointer__0 = call ptr @shed__runtime__alloc(i64 %size__0) - %closureFunctionPointerPointer__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 0 - store ptr @shed__fun__f__0, ptr %closureFunctionPointerPointer__0 - %closureFreeVariablePointer__a__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 1, i64 0 - store i64 1, ptr %closureFreeVariablePointer__a__0 - %closureFreeVariablePointer__b__0 = getelementptr {ptr, [2 x i64]}, ptr %closurePointer__0, i64 0, i32 1, i64 1 - store i64 2, ptr %closureFreeVariablePointer__b__0 - %closureValue__0 = ptrtoint ptr %closurePointer__0 to i64""")); - - assertThat(result.stack(), isSequence( - isLlvmVariableLocal("closureValue__0") - )); - } - - private static Matcher> isLocal(String name, Matcher operand) { - return allOf( - has("name", x -> x.getKey(), equalTo(name)), - has("operand", x -> x.getValue(), operand) - ); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerDiscardTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerDiscardTests.java deleted file mode 100644 index c263caa1..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerDiscardTests.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; -import org.shedlang.compiler.stackir.instructions.Instructions; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.isSequence; - -public class LlvmCompilerDiscardTests { - @Test - public void discardRemovesTopElementFromStack() { - var instruction = Instructions.discard(); - var context = LlvmCompilerContext.EMPTY - .push(LlvmIr.operandInt(1)) - .push(LlvmIr.operandInt(2)); - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence(isLlvmOperandInt(1))); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalLoadTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalLoadTests.java deleted file mode 100644 index 74f5114f..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalLoadTests.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.stackir.instructions.Instructions; -import org.zwobble.precisely.Matcher; - -import java.util.Map; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.*; - -public class LlvmCompilerLocalLoadTests { - @Test - public void localLoadPushsOperandFromLocalsToStack() { - var instruction = Instructions.localLoad("x"); - var context = LlvmCompilerContext.EMPTY - .addLocal("x", LlvmIr.operandInt(42)); - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence(isLlvmOperandInt(42))); - assertThat(result.locals().entrySet(), isSequence(isLocal("x", isLlvmOperandInt(42)))); - } - - private static Matcher> isLocal(String name, Matcher operand) { - return allOf( - has("name", x -> x.getKey(), equalTo(name)), - has("operand", x -> x.getValue(), operand) - ); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalStoreTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalStoreTests.java deleted file mode 100644 index 2f20ec85..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalStoreTests.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.stackir.instructions.Instructions; -import org.zwobble.precisely.Matcher; - -import java.util.Map; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.*; - -public class LlvmCompilerLocalStoreTests { - @Test - public void localStorePopsFromStackAndUpdatesLocals() { - var instruction = Instructions.localStore("x"); - var context = LlvmCompilerContext.EMPTY - .push(LlvmIr.operandInt(0)) - .push(LlvmIr.operandInt(1)); - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence(isLlvmOperandInt(0))); - assertThat(result.locals().entrySet(), isSequence(isLocal("x", isLlvmOperandInt(1)))); - } - - private static Matcher> isLocal(String name, Matcher operand) { - return allOf( - has("name", x -> x.getKey(), equalTo(name)), - has("operand", x -> x.getValue(), operand) - ); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerNamespaceFieldStoreTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerNamespaceFieldStoreTests.java deleted file mode 100644 index 96118890..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerNamespaceFieldStoreTests.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmGetElementPtr; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmStore; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; -import org.shedlang.compiler.stackir.instructions.Instructions; -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.util.List; -import java.util.Map; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.*; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.*; - -public class LlvmCompilerNamespaceFieldStoreTests { - @Test - public void namespaceFieldStorePopsFromStackAndUpdatesFieldOnNamespace() { - var namespaceName = new NamespaceName(List.of("Example", "Project")); - var instruction = Instructions.namespaceFieldStore(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 = LlvmCompilerContext.fromTypeInfo(typeInfo) - .push(LlvmIr.operandInt(0)) - .push(LlvmIr.operandInt(1)); - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence( - instanceOf( - LlvmGetElementPtr.class, - has("target", x -> x.target(), isLlvmVariableLocal("fieldPointer__y__0")), - has( - "pointerType", - x -> x.pointerType(), - equalTo(LlvmTypes.pointer(LlvmTypes.structure(List.of( - LlvmTypes.INT_64, - LlvmTypes.INT_64, - LlvmTypes.INT_64 - )))) - ), - has( - "pointer", - x -> x.pointer(), - isLlvmVariableGlobal("shed__namespace__Example_Project") - ), - has("indexes", x -> x.indexes(), isSequence( - isLlvmTypedOperand(LlvmTypes.INT_64, isLlvmOperandInt(0)), - isLlvmTypedOperand(LlvmTypes.INT_32, isLlvmOperandInt(1)) - )) - ), - instanceOf( - LlvmStore.class, - has("type", x -> x.type(), equalTo(LlvmTypes.INT_64)), - has("value", x -> x.value(), isLlvmOperandInt(1)), - has("pointer", x -> x.pointer(), isLlvmVariableLocal("fieldPointer__y__0")) - ) - )); - assertThat(result.stack(), isSequence(isLlvmOperandInt(0))); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushBoolTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushBoolTests.java deleted file mode 100644 index b677704a..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushBoolTests.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.stackir.instructions.Instructions; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.isSequence; - -public class LlvmCompilerPushBoolTests { - @Test - public void pushFalseIsCompiledToOperandInStack() { - var instruction = Instructions.pushBool(false); - var context = LlvmCompilerContext.EMPTY; - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence(isLlvmOperandInt(0))); - } - - @Test - public void pushTrueIsCompiledToOperandInStack() { - var instruction = Instructions.pushBool(true); - var context = LlvmCompilerContext.EMPTY; - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence(isLlvmOperandInt(1))); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushIntTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushIntTests.java deleted file mode 100644 index 983a1661..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushIntTests.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.stackir.instructions.Instructions; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.isSequence; - -public class LlvmCompilerPushIntTests { - // TODO: handle larger ints - - @Test - public void pushIntIsCompiledToOperandInStack() { - var instruction = Instructions.pushInt(42); - var context = LlvmCompilerContext.EMPTY; - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence(isLlvmOperandInt(42))); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushStringTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushStringTests.java deleted file mode 100644 index 761fbd18..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushStringTests.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmGlobalDefinition; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; -import org.shedlang.compiler.stackir.instructions.Instructions; - -import java.util.List; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.*; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.*; - -public class LlvmCompilerPushStringTests { - @Test - public void pushStringIsCompiledToTopLevelEntityAndReferenceToTopLevelEntity() { - var instruction = Instructions.pushString("hello"); - var context = LlvmCompilerContext.EMPTY; - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence( - isLlvmOperandPtrToInt( - isLlvmVariableGlobal("shed__string__0"), - equalTo(LlvmTypes.INT_64) - ) - )); - assertThat(result.topLevelEntities(), isSequence( - instanceOf( - LlvmGlobalDefinition.class, - has("name", x -> x.name(), equalTo("shed__string__0")), - has("type", x -> x.type(), equalTo(LlvmTypes.structure(List.of( - LlvmTypes.INT_64, - LlvmTypes.array(5, LlvmTypes.INT_8) - )))), - has("value", x -> x.value(), isOptionalOf(equalTo(LlvmIr.operandStructure(List.of( - LlvmIr.typedOperand(LlvmTypes.INT_64, LlvmIr.operandInt(5)), - LlvmIr.typedOperand( - LlvmTypes.array(5, LlvmTypes.INT_8), - LlvmIr.operandArray(LlvmTypes.INT_8, List.of( - LlvmIr.operandInt(104), - LlvmIr.operandInt(101), - LlvmIr.operandInt(108), - LlvmIr.operandInt(108), - LlvmIr.operandInt(111) - )) - ) - ))))), - has("constant", x -> x.constant(), equalTo(true)), - has("isPrivate", x -> x.isPrivate(), equalTo(true)), - has("unnamedAddr", x -> x.unnamedAddr(), equalTo(true)) - ) - )); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushUnitTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushUnitTests.java deleted file mode 100644 index 7a3da398..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerPushUnitTests.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.stackir.instructions.Instructions; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.isLlvmOperandInt; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.isSequence; - -public class LlvmCompilerPushUnitTests { - @Test - public void pushUnitIsCompiledToOperandInStack() { - var instruction = Instructions.pushUnit(); - var context = LlvmCompilerContext.EMPTY; - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence(isLlvmOperandInt(0))); - } -} diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerReturnTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerReturnTests.java deleted file mode 100644 index f76383af..00000000 --- a/src/test/java/org/shedlang/compiler/backends/llvm/LlvmCompilerReturnTests.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmIr; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; -import org.shedlang.compiler.stackir.instructions.Instructions; - -import static org.shedlang.compiler.backends.llvm.ir.ast.LlvmIrMatchers.*; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.equalTo; -import static org.zwobble.precisely.Matchers.isSequence; - -public class LlvmCompilerReturnTests { - @Test - public void returnCompilesToReturnInstruction() { - var instruction = Instructions.return_(); - var add = LlvmIr.add( - LlvmIr.variableLocal("x"), - LlvmTypes.INT_64, - LlvmIr.variableLocal("left"), - LlvmIr.variableLocal("right") - ); - var context = LlvmCompilerContext.EMPTY - .addInstruction(add) - .push(LlvmIr.variableLocal("a")) - .push(LlvmIr.variableLocal("b")); - - var result = LlvmCompiler.compileInstruction(instruction, context); - - assertThat(result.basicBlocks(), isSequence( - isLlvmBasicBlock( - isSequence( - equalTo(add) - ), - isLlvmReturn(LlvmCompilerTypes.VALUE_TYPE, isLlvmVariableLocal("b")) - ) - )); - assertThat(result.instructions(), isSequence()); - assertThat(result.stack(), isSequence( - isLlvmVariableLocal("a") - )); - } -} -- cgit v1.2.3