diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-07-22 12:07:44 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-07-22 12:07:44 +0100 |
| commit | 58df49a98d2a8b4a36ea1188f03327f67095b0b0 (patch) | |
| tree | c3c105c486da56153c0b532d807223d2def59f12 /src/main/java | |
| parent | 90c08384a3b129f970295aa2a02df032900b800f (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.java | 244 |
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) + ); + } } } |
