From edff0de2d08ed5a4bab9c1f3f748d7478fc0de1d Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 13 Jun 2023 23:10:45 +0100 Subject: Compile namespace-field-store to LLVM IR --- .../compiler/backends/llvm/LlvmCompiler.java | 28 +++++++++++++++++- .../backends/llvm/LlvmCompilerContext.java | 24 +++++++++++---- .../backends/llvm/LlvmCompilerNamespaces.java | 34 ++++++++++++++++++++++ .../llvm/ir/ast/operands/LlvmTypedOperand.java | 8 +++++ .../compiler/typechecker/TypeCheckerContext.java | 4 +++ .../shedlang/compiler/typechecker/TypeInfo.java | 24 +++++++++++++++ .../org/shedlang/compiler/util/POrderedMap.java | 4 +++ 7 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerNamespaces.java create mode 100644 src/main/java/org/shedlang/compiler/typechecker/TypeInfo.java (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java index 322c9a4f..8b933bad 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java @@ -1,6 +1,10 @@ package org.shedlang.compiler.backends.llvm; +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.operands.LlvmOperandInt; +import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmTypedOperand; +import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableLocal; import org.shedlang.compiler.stackir.instructions.*; import org.shedlang.compiler.types.NamespaceName; @@ -34,8 +38,29 @@ public class LlvmCompiler { } case NamespaceFieldStoreInstruction namespaceFieldStore -> { - throw new UnsupportedOperationException("TODO"); + var popResult = context.pop(); + var fieldValue = popResult.value(); + context = popResult.context(); + + var namespaceFields = context.typeInfo().namespaceFields( + namespaceFieldStore.namespaceName() + ); + var fieldPointerName = "fieldPointer__" + namespaceFieldStore.fieldName(); + yield context.addInstruction(new LlvmGetElementPtr( + new LlvmVariableLocal(fieldPointerName), + LlvmCompilerNamespaces.typeNamespacePointer(namespaceFields), + LlvmCompilerNamespaces.operandNamespaceValue(namespaceFieldStore.namespaceName()), + List.of( + LlvmTypedOperand.arrayIndex(0), + LlvmTypedOperand.structureIndex(namespaceFields.keys().indexOf(namespaceFieldStore.fieldName())) + ) + )).addInstruction(new LlvmStore( + LlvmCompilerTypes.VALUE_TYPE, + fieldValue, + new LlvmVariableLocal(fieldPointerName) + )); } + case PushBoolInstruction pushBool -> context.push(new LlvmOperandInt(pushBool.value() ? 1 : 0)); @@ -49,6 +74,7 @@ public class LlvmCompiler { yield context.push(LlvmCompilerStrings.operandAsShedObject(globalDefinition)); } + case PushUnitInstruction pushUnit -> context.push(new LlvmOperandInt(0)); }; diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerContext.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerContext.java index b24025b6..144575c0 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerContext.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerContext.java @@ -8,25 +8,33 @@ import org.shedlang.compiler.backends.llvm.ir.ast.LlvmGlobalDefinition; import org.shedlang.compiler.backends.llvm.ir.ast.LlvmTopLevelEntity; import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmInstruction; import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; +import org.shedlang.compiler.typechecker.TypeInfo; import org.shedlang.compiler.util.POrderedMap; import java.util.Collection; public record LlvmCompilerContext( + TypeInfo typeInfo, PStack stack, PMap locals, PVector instructions, POrderedMap topLevelEntitiesByName ) { - public static LlvmCompilerContext EMPTY = new LlvmCompilerContext( - Empty.stack(), - Empty.map(), - Empty.vector(), - POrderedMap.empty() - ); + public static LlvmCompilerContext EMPTY = fromTypeInfo(TypeInfo.EMPTY); + + public static LlvmCompilerContext fromTypeInfo(TypeInfo typeInfo) { + return new LlvmCompilerContext( + typeInfo, + Empty.stack(), + Empty.map(), + Empty.vector(), + POrderedMap.empty() + ); + } public LlvmCompilerContext push(LlvmOperand operand) { return new LlvmCompilerContext( + typeInfo, stack.plus(operand), locals, instructions, @@ -36,6 +44,7 @@ public record LlvmCompilerContext( public LlvmCompilerResult pop() { return new LlvmCompilerContext( + typeInfo, stack.minus(0), locals, instructions, @@ -45,6 +54,7 @@ public record LlvmCompilerContext( public LlvmCompilerContext addLocal(String name, LlvmOperand value) { return new LlvmCompilerContext( + typeInfo, stack, locals.plus(name, value), instructions, @@ -58,6 +68,7 @@ public record LlvmCompilerContext( public LlvmCompilerContext addInstruction(LlvmInstruction instruction) { return new LlvmCompilerContext( + typeInfo, stack, locals, instructions.plus(instruction), @@ -78,6 +89,7 @@ public record LlvmCompilerContext( ); return new LlvmCompilerContext( + typeInfo, stack, locals, instructions, diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerNamespaces.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerNamespaces.java new file mode 100644 index 00000000..85caf95e --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerNamespaces.java @@ -0,0 +1,34 @@ +package org.shedlang.compiler.backends.llvm; + +import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableGlobal; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmType; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypePointer; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypeStructure; +import org.shedlang.compiler.types.NamespaceName; +import org.shedlang.compiler.types.Type; +import org.shedlang.compiler.util.POrderedMap; + +public class LlvmCompilerNamespaces { + private LlvmCompilerNamespaces() { + } + + public static LlvmTypePointer typeNamespacePointer(POrderedMap namespaceFields) { + return new LlvmTypePointer(typeNamespaceStruct(namespaceFields)); + } + + public static LlvmType typeNamespaceStruct(POrderedMap namespaceFields) { + return new LlvmTypeStructure( + namespaceFields.values().stream() + .map(x -> LlvmCompilerTypes.VALUE_TYPE) + .toList() + ); + } + + public static LlvmVariableGlobal operandNamespaceValue(NamespaceName namespaceName) { + return new LlvmVariableGlobal(globalNameNamespaceValue(namespaceName)); + } + + private static String globalNameNamespaceValue(NamespaceName namespaceName) { + return "shed__namespace__" + String.join("_", namespaceName.parts()); + } +} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/ir/ast/operands/LlvmTypedOperand.java b/src/main/java/org/shedlang/compiler/backends/llvm/ir/ast/operands/LlvmTypedOperand.java index 91be449f..85e39cad 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/ir/ast/operands/LlvmTypedOperand.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/ir/ast/operands/LlvmTypedOperand.java @@ -1,9 +1,17 @@ package org.shedlang.compiler.backends.llvm.ir.ast.operands; import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmType; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; public record LlvmTypedOperand( LlvmType type, LlvmOperand operand ) { + public static LlvmTypedOperand arrayIndex(long index) { + return new LlvmTypedOperand(LlvmTypes.INT_64, new LlvmOperandInt(index)); + } + + public static LlvmTypedOperand structureIndex(long index) { + return new LlvmTypedOperand(LlvmTypes.INT_32, new LlvmOperandInt(index)); + } } diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java index 3429be63..93207cd3 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java @@ -113,4 +113,8 @@ public class TypeCheckerContext { return new TypeCheckerResult<>(mappedValues, context); } + + public TypeInfo toTypeInfo() { + return new TypeInfo(namespaceFields); + } } diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeInfo.java b/src/main/java/org/shedlang/compiler/typechecker/TypeInfo.java new file mode 100644 index 00000000..cfce56ef --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeInfo.java @@ -0,0 +1,24 @@ +package org.shedlang.compiler.typechecker; + +import org.pcollections.Empty; +import org.pcollections.PMap; +import org.shedlang.compiler.types.NamespaceName; +import org.shedlang.compiler.types.Type; +import org.shedlang.compiler.util.POrderedMap; + +public class TypeInfo { + public static final TypeInfo EMPTY = new TypeInfo(Empty.map()); + + private final PMap> namespaceFields; + + public TypeInfo( + PMap> namespaceFields + ) { + this.namespaceFields = namespaceFields; + } + + public POrderedMap namespaceFields(NamespaceName namespaceName) { + // TODO: handle missing key + return namespaceFields.get(namespaceName); + } +} diff --git a/src/main/java/org/shedlang/compiler/util/POrderedMap.java b/src/main/java/org/shedlang/compiler/util/POrderedMap.java index aabec1d7..6d273cdc 100644 --- a/src/main/java/org/shedlang/compiler/util/POrderedMap.java +++ b/src/main/java/org/shedlang/compiler/util/POrderedMap.java @@ -30,6 +30,10 @@ public class POrderedMap { return map.containsKey(key); } + public PVector keys() { + return keys; + } + public Collection values() { return map.values(); } -- cgit v1.2.3