aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-07-22 12:07:44 +0100
committerMichael Williamson <mike@zwobble.org>2023-07-22 12:07:44 +0100
commit58df49a98d2a8b4a36ea1188f03327f67095b0b0 (patch)
treec3c105c486da56153c0b532d807223d2def59f12 /src/main/java
parent90c08384a3b129f970295aa2a02df032900b800f (diff)
Add partial code gen from Patio to LLVM
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java244
1 files changed, 241 insertions, 3 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java
index 76b6a1b9..cc1dfeff 100644
--- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java
+++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java
@@ -1,10 +1,248 @@
package org.shedlang.compiler.backends.llvm;
-import org.shedlang.compiler.backends.llvm.ir.ast.LlvmModule;
-import org.shedlang.compiler.patio.ast.PatioCompilationUnit;
+import org.pcollections.PVector;
+import org.shedlang.compiler.backends.llvm.ir.ast.*;
+import 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;
+import org.shedlang.compiler.patio.ast.*;
+import org.shedlang.compiler.patio.ast.types.*;
+import org.shedlang.compiler.util.Lists;
+import org.shedlang.compiler.util.P;
+
+import java.util.List;
+import java.util.Optional;
public class LlvmPatioCodeGen {
public static LlvmModule generateCompilationUnit(PatioCompilationUnit patioCompilationUnit) {
- throw new UnsupportedOperationException();
+ var context = Context.EMPTY;
+
+ for (var patioCompilationUnitElement : patioCompilationUnit.elements()) {
+ context = generateCompilationUnitElement(patioCompilationUnitElement, context);
+ }
+
+ return context.toModule();
+ }
+
+ private static Context generateCompilationUnitElement(
+ PatioCompilationUnitElement patioCompilationUnitElement,
+ Context context
+ ) {
+ return switch (patioCompilationUnitElement) {
+ case PatioDataElementImmutable patioDataElementImmutable ->
+ generateDataElementImmutable(patioDataElementImmutable, context);
+
+ case PatioDataElementMutable patioDataElementMutable ->
+ generateDataElementMutable(patioDataElementMutable, context);
+
+ case PatioFunctionDeclaration patioFunctionDeclaration ->
+ generateFunctionDeclaration(patioFunctionDeclaration, context);
+
+ case PatioFunctionDefinition patioFunctionDefinition ->
+ generateFunctionDefinition(patioFunctionDefinition, context);
+ };
+ }
+
+ private static Context generateDataElementImmutable(
+ PatioDataElementImmutable patioDataElementImmutable,
+ Context context
+ ) {
+ return context.addTopLevelEntity(new LlvmGlobalDefinition(
+ patioDataElementImmutable.name(),
+ patioDataLayoutToType(patioDataElementImmutable.value().layout()),
+ Optional.of(patioDataValueToOperand(patioDataElementImmutable.value())),
+ true,
+ true,
+ true
+ ));
+ }
+
+ private static Context generateDataElementMutable(
+ PatioDataElementMutable patioDataElementMutable,
+ Context context
+ ) {
+ return context.addTopLevelEntity(new LlvmGlobalDefinition(
+ patioDataElementMutable.name(),
+ patioDataLayoutToType(patioDataElementMutable.layout()),
+ Optional.of(patioDataLayoutToZeroedOperand(patioDataElementMutable.layout())),
+ false,
+ true,
+ true
+ ));
+ }
+
+ private static Context generateFunctionDeclaration(
+ PatioFunctionDeclaration patioFunctionDeclaration,
+ Context context
+ ) {
+ return context.addTopLevelEntity(new LlvmFunctionDeclaration(
+ patioFunctionDeclaration.name(),
+ patioTypeToType(patioFunctionDeclaration.returnType()),
+ patioFunctionDeclaration.params().stream()
+ .map(patioParam -> new LlvmParam(
+ patioTypeToType(patioParam.type()),
+ patioParam.name()
+ ))
+ .toList()
+ ));
+ }
+
+ private static Context generateFunctionDefinition(
+ PatioFunctionDefinition patioFunctionDefinition,
+ Context context
+ ) {
+ var llvmBody = List.<LlvmBasicBlock>of();
+
+ return context.addTopLevelEntity(new LlvmFunctionDefinition(
+ patioFunctionDefinition.name(),
+ patioTypeToType(patioFunctionDefinition.returnType()),
+ patioFunctionDefinition.params().stream()
+ .map(patioParam -> new LlvmParam(
+ patioTypeToType(patioParam.type()),
+ patioParam.name()
+ ))
+ .toList(),
+ llvmBody
+ ));
+ }
+
+
+ private static LlvmType patioTypeToType(PatioType patioType) {
+ return switch (patioType) {
+ case PatioBoolType patioBoolType ->
+ LlvmTypes.INT_1;
+
+ case PatioByteType patioByteType ->
+ LlvmTypes.INT_8;
+
+ case PatioDataPointerType patioDataPointerType ->
+ LlvmTypes.pointer(LlvmTypes.VOID);
+
+ case PatioFunctionPointerType patioFunctionPointerType ->
+ LlvmTypes.pointer(LlvmTypes.VOID);
+
+ case PatioIntType patioIntType ->
+ LlvmTypes.INT_64;
+
+ case PatioVoidType patioVoidType ->
+ LlvmTypes.VOID;
+ };
+ }
+
+ private static LlvmType patioDataLayoutToType(PatioDataLayout layout) {
+ return switch (layout) {
+ case PatioDataLayoutArray patioDataLayoutArray ->
+ LlvmTypes.array(
+ patioDataLayoutArray.size(),
+ patioDataLayoutToType(patioDataLayoutArray.element())
+ );
+
+ case PatioDataLayoutBool patioDataLayoutBool ->
+ LlvmTypes.INT_1;
+
+ case PatioDataLayoutByte patioDataLayoutByte ->
+ LlvmTypes.INT_8;
+
+ case PatioDataLayoutFunctionPointer patioDataLayoutFunctionPointer ->
+ LlvmTypes.pointer(LlvmTypes.VOID);
+
+ case PatioDataLayoutInt patioDataLayoutInt ->
+ LlvmTypes.INT_64;
+
+ case PatioDataLayoutStruct patioDataLayoutStruct ->
+ LlvmTypes.structure(
+ patioDataLayoutStruct.elements().stream()
+ .map(element -> patioDataLayoutToType(element))
+ .toList()
+ );
+ };
+ }
+
+ private static LlvmOperand patioDataLayoutToZeroedOperand(PatioDataLayout layout) {
+ return switch (layout) {
+ case PatioDataLayoutArray patioDataLayoutArray ->
+ new LlvmOperandArray(
+ patioDataLayoutToType(patioDataLayoutArray.element()),
+ Lists.repeat(
+ patioDataLayoutToZeroedOperand(patioDataLayoutArray.element()),
+ patioDataLayoutArray.size()
+ )
+ );
+
+ case PatioDataLayoutBool patioDataLayoutBool ->
+ new LlvmOperandInt(0);
+
+ case PatioDataLayoutByte patioDataLayoutByte ->
+ new LlvmOperandInt(0);
+
+ case PatioDataLayoutFunctionPointer patioDataLayoutFunctionPointer ->
+ new LlvmOperandNull();
+
+ case PatioDataLayoutInt patioDataLayoutInt ->
+ new LlvmOperandInt(0);
+
+ case PatioDataLayoutStruct patioDataLayoutStruct ->
+ new LlvmOperandStructure(
+ patioDataLayoutStruct.elements().stream()
+ .map(element -> new LlvmTypedOperand(
+ patioDataLayoutToType(element),
+ patioDataLayoutToZeroedOperand(element)
+ ))
+ .toList()
+ );
+ };
+ }
+
+ private static LlvmOperand patioDataValueToOperand(PatioDataValue value) {
+ return switch (value) {
+ case PatioDataValueArray patioDataValueArray -> {
+ var patioElement = patioDataValueArray.elements().get(0);
+ var llvmType = patioDataLayoutToType(patioElement.layout());
+
+ var llvmElements = patioDataValueArray.elements().stream()
+ .map(element -> patioDataValueToOperand(element))
+ .toList();
+
+ yield new LlvmOperandArray(llvmType, llvmElements);
+ }
+
+ case PatioDataValueByte patioDataValueByte ->
+ new LlvmOperandInt(patioDataValueByte.value());
+
+ case PatioDataValueInt patioDataValueInt ->
+ new LlvmOperandInt(patioDataValueInt.value());
+
+ case PatioDataValueStruct patioDataValueStruct ->
+ new LlvmOperandStructure(
+ patioDataValueStruct.elements().stream()
+ .map(element -> new LlvmTypedOperand(
+ patioDataLayoutToType(element.layout()),
+ patioDataValueToOperand(element)
+ ))
+ .toList()
+ );
+ };
+ }
+
+ private static class Context {
+ private static final Context EMPTY = new Context(P.vector());
+
+ private final PVector<LlvmTopLevelEntity> topLevelEntities;
+
+ private Context(
+ PVector<LlvmTopLevelEntity> topLevelEntities
+ ) {
+ this.topLevelEntities = topLevelEntities;
+ }
+
+ private LlvmModule toModule() {
+ return new LlvmModule(topLevelEntities);
+ }
+
+ public Context addTopLevelEntity(LlvmTopLevelEntity topLevelEntity) {
+ return new Context(
+ this.topLevelEntities.plus(topLevelEntity)
+ );
+ }
}
}