diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-09-16 15:20:50 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-09-16 15:20:50 +0100 |
| commit | 410d51abc96defa8b16d1041e9cfe8668221798a (patch) | |
| tree | b9c164f0d13b56041dc2e081a3d12889426822eb /src/main/java | |
| parent | d2d6019cabed6e04a04bef402442697f9c32df11 (diff) | |
Remove direct LLVM backend
Diffstat (limited to 'src/main/java')
13 files changed, 57 insertions, 1932 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/Backend.java b/src/main/java/org/shedlang/compiler/backends/Backend.java index 3bfb77ab..aba5fe1b 100644 --- a/src/main/java/org/shedlang/compiler/backends/Backend.java +++ b/src/main/java/org/shedlang/compiler/backends/Backend.java @@ -9,12 +9,12 @@ import java.nio.file.Path; import java.util.List; public interface Backend { + String name(); + void compile( ProjectConfig config, List<StackIrNamespace> namespaces, TypeInfo typeInfo, Path targetDir ) throws IOException, InterruptedException; - - String name(); } diff --git a/src/main/java/org/shedlang/compiler/backends/Backends.java b/src/main/java/org/shedlang/compiler/backends/Backends.java index 02a3e60d..4d53cee8 100644 --- a/src/main/java/org/shedlang/compiler/backends/Backends.java +++ b/src/main/java/org/shedlang/compiler/backends/Backends.java @@ -9,8 +9,7 @@ public class Backends { } public static final OrderedPMap<String, Backend> BACKENDS = OrderedPMap.<String, Backend>empty() - .plus("llvm", LlvmBackend.DIRECT) - .plus("llvm-patio", LlvmBackend.PATIO) + .plus("llvm", LlvmBackend.INSTANCE) .plus("wasm", WasmBackend.DIRECT) .plus("wasm-patio", WasmBackend.PATIO); } diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java index a3d2af91..2cb22612 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java @@ -28,89 +28,14 @@ import java.util.Optional; import static org.shedlang.compiler.util.processes.ProcessRunner.runInheritIo; public class LlvmBackend implements Backend { - public static final LlvmBackend DIRECT = new LlvmBackend("llvm", new CodeGen() { - @Override - public LlvmModule generateNamespace(StackIrNamespace stackIrNamespace, TypeInfo typeInfo) { - return LlvmCodeGen.generateNamespace(stackIrNamespace, typeInfo); - } - - @Override - public LlvmModule generateMain(NamespaceName main, TypeInfo typeInfo) { - return LlvmCodeGen.generateMain(main, typeInfo); - } - }); - - public static final LlvmBackend PATIO = new LlvmBackend("llvm-patio", new CodeGen() { - @Override - public LlvmModule generateNamespace(StackIrNamespace stackIrNamespace, TypeInfo typeInfo) { - var patioCompilationUnit = PatioCodeGen.generateNamespace( - stackIrNamespace, - PatioCodeGenContext.forTypeInfo(typeInfo) - ); - - return LlvmPatioCodeGen.generateCompilationUnit(patioCompilationUnit); - } - - @Override - public LlvmModule generateMain(NamespaceName main, TypeInfo typeInfo) { - // TODO: use more appropriate source - var source = Sources.NULL; - - var context = PatioCodeGenContext.forTypeInfo(typeInfo); - - var generateMainResult = PatioCodeGen.generateMain(main, source, context); - var mainFunctionName = generateMainResult.value(); - context = generateMainResult.context(); - - var patioCompilationUnit = context.toCompilationUnit(source); - - var llvmModule = LlvmPatioCodeGen.generateCompilationUnit(patioCompilationUnit); - - llvmModule = llvmModule.addTopLevelEntity(new LlvmFunctionDefinition( - "main", - LlvmTypes.INT_32, - List.of(), - List.of( - new LlvmBasicBlock( - Optional.empty(), - List.of( - new LlvmCall( - new LlvmVariableLocal("exitCode"), - LlvmTypes.INT_64, - new LlvmVariableGlobal(mainFunctionName), - List.of() - ), - new LlvmTrunc( - new LlvmVariableLocal("exitCode32"), - LlvmTypes.INT_64, - new LlvmVariableLocal("exitCode"), - LlvmTypes.INT_32 - ) - ), - new LlvmReturn(LlvmTypes.INT_32, new LlvmVariableLocal("exitCode32")) - ) - ) - )); + public static final LlvmBackend INSTANCE = new LlvmBackend(); - return llvmModule; - } - }); - - interface CodeGen { - LlvmModule generateNamespace( - StackIrNamespace stackIrNamespace, - TypeInfo typeInfo - ); - - LlvmModule generateMain(NamespaceName main, TypeInfo typeInfo); + private LlvmBackend() { } - private final String name; - private final CodeGen codeGen; - - private LlvmBackend(String name, CodeGen codeGen) { - this.name = name; - this.codeGen = codeGen; + @Override + public String name() { + return "llvm"; } @Override @@ -122,18 +47,24 @@ public class LlvmBackend implements Backend { ) throws IOException, InterruptedException { var objectFilePaths = new ArrayList<Path>(); for (var namespace : namespaces) { - var llvmModule = this.codeGen.generateNamespace(namespace, typeInfo); + var patioCompilationUnit = PatioCodeGen.generateNamespace( + namespace, + PatioCodeGenContext.forTypeInfo(typeInfo) + ); + + var llvmModule = LlvmPatioCodeGen.generateCompilationUnit(patioCompilationUnit); var objectPath = compileLlvmModule( llvmModule, targetDir.resolve("namespaces"), String.join("_", namespace.namespaceName().parts()) ); + objectFilePaths.add(objectPath); } for (var bin : config.bins()) { - var mainModule = this.codeGen.generateMain(config.main(), typeInfo); + var mainModule = this.generateMain(config.main(), typeInfo); var mainObjectPath = compileLlvmModule(mainModule, targetDir.resolve("bins"), bin.name()); var gccArgs = new ArrayList<String>(); @@ -153,9 +84,47 @@ public class LlvmBackend implements Backend { } } - @Override - public String name() { - return name; + private LlvmModule generateMain(NamespaceName main, TypeInfo typeInfo) { + // TODO: use more appropriate source + var source = Sources.NULL; + + var context = PatioCodeGenContext.forTypeInfo(typeInfo); + + var generateMainResult = PatioCodeGen.generateMain(main, source, context); + var mainFunctionName = generateMainResult.value(); + context = generateMainResult.context(); + + var patioCompilationUnit = context.toCompilationUnit(source); + + var llvmModule = LlvmPatioCodeGen.generateCompilationUnit(patioCompilationUnit); + + llvmModule = llvmModule.addTopLevelEntity(new LlvmFunctionDefinition( + "main", + LlvmTypes.INT_32, + List.of(), + List.of( + new LlvmBasicBlock( + Optional.empty(), + List.of( + new LlvmCall( + new LlvmVariableLocal("exitCode"), + LlvmTypes.INT_64, + new LlvmVariableGlobal(mainFunctionName), + List.of() + ), + new LlvmTrunc( + new LlvmVariableLocal("exitCode32"), + LlvmTypes.INT_64, + new LlvmVariableLocal("exitCode"), + LlvmTypes.INT_32 + ) + ), + new LlvmReturn(LlvmTypes.INT_32, new LlvmVariableLocal("exitCode32")) + ) + ) + )); + + return llvmModule; } private static Path compileLlvmModule( diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java deleted file mode 100644 index a0d04143..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java +++ /dev/null @@ -1,405 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmFunctionDeclaration; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmModule; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmParam; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.*; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperandInt; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariable; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableLocal; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; -import org.shedlang.compiler.stackir.StackIrNamespace; -import org.shedlang.compiler.stackir.instructions.*; -import org.shedlang.compiler.typechecker.TypeInfo; -import org.shedlang.compiler.types.NamespaceName; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.shedlang.compiler.util.Lists.reversed; - -public class LlvmCodeGen { - public static LlvmModule generateMain(NamespaceName main, TypeInfo typeInfo) { - var context = LlvmCodeGenContext.fromTypeInfo(typeInfo); - - context = context.createFunction(mainContext -> { - var namespaceResult = LlvmCodeGenNamespaces.importValue(main, mainContext); - var namespace = namespaceResult.value(); - mainContext = namespaceResult.context(); - - var fieldResult = LlvmCodeGenNamespaces.fieldLoad( - main, - namespace, - // TODO: check there is a main function - "main", - mainContext - ); - var field = fieldResult.value(); - mainContext = fieldResult.context(); - - mainContext = LlvmCodeGenClosures.call(field, List.of(), List.of(), mainContext); - - mainContext = mainContext.addTerminatorInstruction( - new LlvmReturn(LlvmTypes.INT_32, new LlvmOperandInt(0)) - ); - - var function = mainContext.toFunction("main", LlvmTypes.INT_32, List.of()); - - return mainContext.toResult(function); - }); - - return context.toModule(); - } - - public static LlvmModule generateNamespace( - StackIrNamespace namespace, - TypeInfo typeInfo - ) { - var context = defaultContext(typeInfo); - - context = LlvmCodeGenNamespaces.define( - namespace.namespaceName(), - initContext -> generateInstructions(namespace.instructions(), initContext), - context - ); - - return context.toModule(); - } - - private static LlvmCodeGenContext defaultContext(TypeInfo typeInfo) { - return LlvmCodeGenContext.fromTypeInfo(typeInfo) - .addTopLevelEntity(new LlvmFunctionDeclaration( - "shed__runtime__alloc", - LlvmTypes.pointer(LlvmTypes.INT_8), - List.of(new LlvmParam(LlvmTypes.INT_64, "size")) - )); - } - - public static LlvmCodeGenContext generateInstruction(Instruction instruction, LlvmCodeGenContext context) { - return switch (instruction) { - case CallInstruction call -> { - var namedArgsByName = new ArrayList<Map.Entry<String, LlvmOperand>>(); - for (var argName : reversed(call.namedArgNames())) { - var argResult = context.pop(); - var arg = argResult.value(); - context = argResult.context(); - namedArgsByName.add(Map.entry(argName, arg)); - } - - var positionalArgs = new ArrayList<LlvmOperand>(); - for (var i = 0; i < call.positionalArgCount(); i++) { - var argResult = context.pop(); - var arg = argResult.value(); - context = argResult.context(); - positionalArgs.add(arg); - } - Collections.reverse(positionalArgs); - - var receiverResult = context.pop(); - var receiver = receiverResult.value(); - context = receiverResult.context(); - - yield LlvmCodeGenClosures.call( - receiver, - positionalArgs, - namedArgsByName, - context - ); - } - case DefineFunctionInstruction defineFunction -> { - yield LlvmCodeGenClosures.create( - defineFunction.name(), - defineFunction.positionalParams(), - defineFunction.namedParams(), - defineFunction.freeVariables(), - functionContext -> - generateInstructions(defineFunction.body(), functionContext), - context - ); - } - case DiscardInstruction discardInstruction -> - context.pop().context(); - - case FieldLoadInstruction fieldLoad -> { - var receiverResult = context.pop(); - var receiver = receiverResult.value(); - context = receiverResult.context(); - - var fieldLoadResult = LlvmCodeGenNamespaces.fieldLoad( - fieldLoad.namespaceName(), - receiver, - fieldLoad.fieldName(), - context - ); - var fieldValue = fieldLoadResult.value(); - context = fieldLoadResult.context(); - - yield context.push(fieldValue); - } - - case IfInstruction if_ -> { - if (if_.resultCount() != 1) { - throw new UnsupportedOperationException("TODO"); - } - - var conditionResult = context.pop(); - var condition = conditionResult.value(); - context = conditionResult.context(); - - var condition1Result = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CONDITION - ); - var condition1 = condition1Result.value(); - context = condition1Result.context(); - - var ifTrueLabelResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.IF_TRUE_START - ); - var ifTrueLabel = ifTrueLabelResult.value(); - context = ifTrueLabelResult.context(); - - var ifFalseLabelResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.IF_FALSE_START - ); - var ifFalseLabel = ifFalseLabelResult.value(); - context = ifFalseLabelResult.context(); - - var endLabelResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.IF_END - ); - var endLabel = endLabelResult.value(); - context = endLabelResult.context(); - - context = context - .addInstruction(new LlvmTrunc( - condition1, - LlvmCodeGenTypes.VALUE_TYPE, - condition, - LlvmTypes.INT_1 - )) - .addTerminatorInstruction(new LlvmBr(condition1, ifTrueLabel.name(), ifFalseLabel.name())); - - context = context.setBasicBlockLabel(ifTrueLabel.name()); - context = generateInstructions(if_.trueBody(), context); - var trueValueResult = context.pop(); - var trueValue = trueValueResult.value(); - context = trueValueResult.context(); - // TODO: remove this hack! - var ifTrueEndLabel = context.functionContext().basicBlockLabel().orElseThrow(); - context = context.addTerminatorInstruction(new LlvmBrUnconditional(endLabel.name())); - - context = context.setBasicBlockLabel(ifFalseLabel.name()); - context = generateInstructions(if_.falseBody(), context); - var falseValueResult = context.pop(); - var falseValue = falseValueResult.value(); - context = falseValueResult.context(); - // TODO: remove this hack! - var ifFalseEndLabel = context.functionContext().basicBlockLabel().orElseThrow(); - context = context.addTerminatorInstruction(new LlvmBrUnconditional(endLabel.name())); - - context = context.setBasicBlockLabel(endLabel.name()); - - var phiResult = context.generateVariableLocal(LlvmCodeGenLocalVariableSpace.PHI); - var phi = phiResult.value(); - context = phiResult.context(); - - context = context.addInstruction(new LlvmPhi( - phi, - LlvmCodeGenTypes.VALUE_TYPE, - List.of( - new LlvmPhiPair(trueValue, new LlvmVariableLocal(ifTrueEndLabel)), - new LlvmPhiPair(falseValue, new LlvmVariableLocal(ifFalseEndLabel)) - ) - )).push(phi); - - yield context; - } - - case IntAddInstruction intAdd -> - generateBinaryOperation( - (target, left, right, operationContext) -> - operationContext.addInstruction( - new LlvmAdd(target, LlvmCodeGenTypes.INT_TYPE, left, right) - ), - context - ); - - case IntEqualsInstruction intEquals -> - generateBinaryComparison(LlvmConditionCode.EQ, context); - - case IntNotEqualInstruction intNotEqual -> - generateBinaryComparison(LlvmConditionCode.NE, context); - - case IntSubInstruction intSub -> - generateBinaryOperation( - (target, left, right, operationContext) -> - operationContext.addInstruction( - new LlvmSub(target, LlvmCodeGenTypes.INT_TYPE, left, right) - ), - context - ); - - case LocalLoadInstruction localLoad -> - context.push(context.shedLocal(localLoad.name())); - - case LocalStoreInstruction localStore -> { - var result = context.pop(); - var value = result.value(); - context = result.context(); - - yield context.addShedLocal(localStore.name(), value); - } - - case LoopInstruction loop -> - throw new UnsupportedOperationException("TODO"); - - case LoopBreakInstruction loopBreak -> - throw new UnsupportedOperationException("TODO"); - - case LoopContinueInstruction loopContinue -> - throw new UnsupportedOperationException("TODO"); - - case NamespaceFieldStoreInstruction namespaceFieldStore -> { - var popResult = context.pop(); - var fieldValue = popResult.value(); - context = popResult.context(); - - yield LlvmCodeGenNamespaces.fieldStore( - namespaceFieldStore.namespaceName(), - namespaceFieldStore.fieldName(), - fieldValue, - context - ); - } - - case NamespaceImportInstruction namespaceImport -> { - var importValueResult = LlvmCodeGenNamespaces.importValue( - namespaceImport.namespaceName(), - context - ); - var importValue = importValueResult.value(); - context = importValueResult.context(); - - yield context.push(importValue); - } - - case PushBoolInstruction pushBool -> - context.push(new LlvmOperandInt(pushBool.value() ? 1 : 0)); - - case PushIntInstruction pushInt -> - context.push(new LlvmOperandInt(pushInt.value().longValueExact())); - - case PushStringInstruction pushString -> { - var result = LlvmCodeGenStrings.defineString(pushString.value(), context); - var globalDefinition = result.value(); - context = result.context(); - - yield context.push(LlvmCodeGenStrings.operandAsShedObject(globalDefinition)); - } - - case PushUnitInstruction pushUnit -> - context.push(new LlvmOperandInt(0)); - - case ReturnInstruction returnInstruction -> { - var result = context.pop(); - var value = result.value(); - context = result.context(); - - yield context.addTerminatorInstruction( - new LlvmReturn(LlvmCodeGenTypes.VALUE_TYPE, value) - ); - } - - case StringAddInstruction stringAdd -> - generateBinaryOperation( - (target, left, right, operationContext) -> - LlvmCodeGenStrings.add(target, left, right, operationContext), - context - ); - - case VarLoadInstruction varLoad -> - throw new UnsupportedOperationException(); - - case VarStoreInstruction varStore -> - throw new UnsupportedOperationException(); - }; - } - - private static LlvmCodeGenContext generateInstructions( - List<Instruction> instructions, - LlvmCodeGenContext functionContext - ) { - for (var bodyInstruction : instructions) { - functionContext = generateInstruction(bodyInstruction, functionContext); - } - return functionContext; - } - - interface BinaryOperation { - LlvmCodeGenContext generate( - LlvmVariable target, - LlvmOperand left, - LlvmOperand right, - LlvmCodeGenContext context - ); - } - - private static LlvmCodeGenContext generateBinaryOperation( - BinaryOperation operation, - LlvmCodeGenContext context - ) { - var rightResult = context.pop(); - var right = rightResult.value(); - context = rightResult.context(); - - var leftResult = context.pop(); - var left = leftResult.value(); - context = leftResult.context(); - - var targetResult = context.generateVariableLocal(LlvmCodeGenLocalVariableSpace.TEMPORARY); - var target = targetResult.value(); - context = targetResult.context(); - - return operation.generate(target, left, right, context).push(target); - } - - private static LlvmCodeGenContext generateBinaryComparison( - LlvmConditionCode conditionCode, - LlvmCodeGenContext context - ) { - var rightResult = context.pop(); - var right = rightResult.value(); - context = rightResult.context(); - - var leftResult = context.pop(); - var left = leftResult.value(); - context = leftResult.context(); - - var targetI1Result = context.generateVariableLocal(LlvmCodeGenLocalVariableSpace.TEMPORARY); - var targetI1 = targetI1Result.value(); - context = targetI1Result.context(); - - var targetResult = context.generateVariableLocal(LlvmCodeGenLocalVariableSpace.TEMPORARY); - var target = targetResult.value(); - context = targetResult.context(); - - return context - .addInstruction(new LlvmIcmp( - targetI1, - conditionCode, - LlvmCodeGenTypes.INT_TYPE, - left, - right - )) - .addInstruction(new LlvmZext( - target, - LlvmTypes.INT_1, - targetI1, - LlvmCodeGenTypes.VALUE_TYPE - )) - .push(target); - } -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenClosures.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenClosures.java deleted file mode 100644 index 9ec1b97a..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenClosures.java +++ /dev/null @@ -1,421 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.shedlang.compiler.ast.typed.FreeVariable; -import org.shedlang.compiler.ast.typed.FreeVariables; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmParam; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.*; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmTypedOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableGlobal; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableLocal; -import org.shedlang.compiler.backends.llvm.ir.ast.types.*; -import org.shedlang.compiler.stackir.instructions.DefineFunctionInstruction; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Stream; - -import static org.shedlang.compiler.util.Iterables.sortedBy; - -public class LlvmCodeGenClosures { - private LlvmCodeGenClosures() { - } - - public record Types(Optional<FreeVariables> freeVariables) { - public LlvmTypePointer closurePointer() { - return LlvmTypes.pointer(closureStruct()); - } - - public LlvmTypeStructure closureStruct() { - return LlvmTypes.structure(List.of( - closureFunctionPointer(), - closureEnvironment() - )); - } - - public LlvmTypePointer closureFunctionPointer() { - return LlvmTypes.pointer(closureFunction()); - } - - public LlvmTypeFunction closureFunction() { - return LlvmTypes.function( - LlvmCodeGenTypes.VALUE_TYPE, - List.of(closureEnvironmentPointer()) - ); - } - - public LlvmTypePointer closureEnvironmentPointer() { - return LlvmTypes.pointer(closureEnvironment()); - } - - public LlvmTypeArray closureEnvironment() { - return LlvmTypes.array(freeVariables.map(x -> x.size()).orElse(0), LlvmCodeGenTypes.VALUE_TYPE); - } - } - - public static final Types CALLABLE_TYPES = new Types(Optional.empty()); - - public static Types types(FreeVariables freeVariables) { - return new Types(Optional.of(freeVariables)); - } - - public static Types types(Optional<FreeVariables> freeVariables) { - return new Types(freeVariables); - } - - public static LlvmCodeGenContext create( - String name, - List<DefineFunctionInstruction.Param> positionalParams, - List<DefineFunctionInstruction.Param> namedParams, - FreeVariables freeVariables, - Function<LlvmCodeGenContext, LlvmCodeGenContext> compileBody, - LlvmCodeGenContext context - ) { - var closureTypes = LlvmCodeGenClosures.types(freeVariables); - - var topLevelEntityName = context.generateTopLevelEntityName( - LlvmCodeGenTopLevelEntitySpace.FUNCTION, - name - ); - - context = context.createFunction(bodyContext -> { - var functionClosurePointerResult = bodyContext.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_POINTER - ); - var functionClosurePointer = functionClosurePointerResult.value(); - bodyContext = functionClosurePointerResult.context(); - - var shedParams = Stream.concat(positionalParams.stream(), namedParams.stream()).toList(); - var llvmParams = new ArrayList<LlvmParam>(); - llvmParams.add(new LlvmParam( - closureTypes.closurePointer(), - functionClosurePointer.name() - )); - - for (var shedParam : shedParams) { - var paramResult = bodyContext.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.PARAM, - shedParam.name() - ); - var llvmParamVariable = paramResult.value(); - bodyContext = paramResult.context(); - - bodyContext = bodyContext.addShedLocal(shedParam.name(), llvmParamVariable); - llvmParams.add(new LlvmParam(LlvmCodeGenTypes.VALUE_TYPE, llvmParamVariable.name())); - } - - for (var freeVariable : freeVariables) { - bodyContext = loadClosureFreeVariable( - functionClosurePointer, - freeVariable, - closureTypes, - bodyContext - ); - } - - bodyContext = compileBody.apply(bodyContext); - - var function = bodyContext.toFunction( - topLevelEntityName, - LlvmCodeGenTypes.VALUE_TYPE, - llvmParams - ); - return bodyContext.toResult(function); - }); - - var closurePointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_POINTER - ); - var closurePointer = closurePointerResult.value(); - context = closurePointerResult.context(); - - var closureSizeResult = LlvmSizeOf.sizeOf( - closureTypes.closureStruct(), - context - ); - var closureSize = closureSizeResult.value(); - context = closureSizeResult.context(); - - context = LlvmCodeGenRuntime.callAlloc( - closurePointer, - closureTypes.closurePointer(), - closureSize, - context - ); - - context = storeClosureFunctionPointer( - closurePointer, - closureTypes, - new LlvmVariableGlobal(topLevelEntityName), - context - ); - - for (var freeVariable : freeVariables) { - context = storeClosureFreeVariable( - closurePointer, - freeVariable, - closureTypes, - context - ); - } - - var closureValueResult = castClosurePointerToValue(closurePointer, context); - var closureValue = closureValueResult.value(); - context = closureValueResult.context(); - - context = context.push(closureValue); - - return context; - } - - public static LlvmCodeGenContext call( - LlvmOperand closure, - List<LlvmOperand> positionalArgs, - List<Map.Entry<String, LlvmOperand>> namedArgsByName, - LlvmCodeGenContext context - ) { - var closurePointerResult = castValueToClosurePointer(closure, context); - var closurePointer = closurePointerResult.value(); - context = closurePointerResult.context(); - - var functionPointerResult = loadClosureFunctionPointer(closurePointer, context); - var functionPointer = functionPointerResult.value(); - context = functionPointerResult.context(); - - var callTargetResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.TEMPORARY - ); - var callTarget = callTargetResult.value(); - context = callTargetResult.context(); - - var fullArgs = new ArrayList<LlvmTypedOperand>(); - fullArgs.add(new LlvmTypedOperand(CALLABLE_TYPES.closurePointer(), closurePointer)); - - for (var arg : positionalArgs) { - fullArgs.add(new LlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, arg)); - } - - for (var arg : sortedBy(namedArgsByName, x -> x.getKey())) { - fullArgs.add(new LlvmTypedOperand(LlvmCodeGenTypes.VALUE_TYPE, arg.getValue())); - } - - return context.addInstruction(new LlvmCall( - callTarget, - LlvmCodeGenTypes.VALUE_TYPE, - functionPointer, - fullArgs - )).push(callTarget); - } - - private static LlvmCodeGenResult<LlvmVariableLocal> castClosurePointerToValue( - LlvmOperand closurePointer, - LlvmCodeGenContext context - ) { - var closureValueResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_VALUE - ); - var closureValue = closureValueResult.value(); - context = closureValueResult.context(); - - context = context.addInstruction(new LlvmPtrToInt( - closureValue, - closurePointer, - LlvmCodeGenTypes.VALUE_TYPE - )); - - return context.toResult(closureValue); - } - - private static LlvmCodeGenResult<LlvmVariableLocal> castValueToClosurePointer( - LlvmOperand value, - LlvmCodeGenContext context - ) { - var closurePointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_POINTER - ); - var closurePointer = closurePointerResult.value(); - context = closurePointerResult.context(); - - context = context.addInstruction(new LlvmIntToPtr( - closurePointer, - LlvmCodeGenTypes.VALUE_TYPE, - value - )); - - return context.toResult(closurePointer); - } - - private static LlvmCodeGenContext storeClosureFunctionPointer( - LlvmOperand closurePointer, - Types closureTypes, - LlvmOperand function, - LlvmCodeGenContext context - ) { - var closureFunctionPointerPointerResult = getClosureFunctionPointerPointer( - closurePointer, - closureTypes, - context - ); - var closureFunctionPointerPointer = closureFunctionPointerPointerResult.value(); - context = closureFunctionPointerPointerResult.context(); - - return context.addInstruction(new LlvmStore( - closureTypes.closureFunctionPointer(), - function, - closureFunctionPointerPointer - )); - } - - private static LlvmCodeGenResult<LlvmVariableLocal> loadClosureFunctionPointer( - LlvmOperand closurePointer, - LlvmCodeGenContext context - ) { - var functionPointerPointerResult = getClosureFunctionPointerPointer( - closurePointer, - CALLABLE_TYPES, - context - ); - var functionPointerPointer = functionPointerPointerResult.value(); - context = functionPointerPointerResult.context(); - - var functionPointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_FUNCTION_POINTER - ); - var functionPointer = functionPointerResult.value(); - context = functionPointerResult.context(); - - return context.addInstruction(new LlvmLoad( - functionPointer, - CALLABLE_TYPES.closureFunctionPointer(), - functionPointerPointer - )).toResult(functionPointer); - } - - private static LlvmCodeGenResult<LlvmVariableLocal> getClosureFunctionPointerPointer( - LlvmOperand closurePointer, - Types closureTypes, - LlvmCodeGenContext context - ) { - var functionPointerPointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_FUNCTION_POINTER_POINTER - ); - var functionPointerPointer = functionPointerPointerResult.value(); - context = functionPointerPointerResult.context(); - - context = context.addInstruction(new LlvmGetElementPtr( - functionPointerPointer, - closureTypes.closurePointer(), - closurePointer, - List.of(LlvmTypedOperand.arrayIndex(0), LlvmTypedOperand.structureIndex(0)) - )); - - return context.toResult(functionPointerPointer); - } - - private static LlvmCodeGenResult<LlvmVariableLocal> getClosureEnvironmentPointer( - LlvmOperand closurePointer, - LlvmCodeGenContext context - ) { - var environmentPointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_ENVIRONMENT_POINTER - ); - var environmentPointer = environmentPointerResult.value(); - context = environmentPointerResult.context(); - - context = context.addInstruction(new LlvmGetElementPtr( - environmentPointer, - CALLABLE_TYPES.closurePointer(), - closurePointer, - List.of(LlvmTypedOperand.arrayIndex(0), LlvmTypedOperand.structureIndex(1)) - )); - - return context.toResult(environmentPointer); - } - - private static LlvmCodeGenContext storeClosureFreeVariable( - LlvmOperand closurePointer, - FreeVariable freeVariable, - Types closureTypes, - LlvmCodeGenContext context - ) { - var closureEnvironmentPointerResult = getClosureFreeVariablePointer( - closurePointer, - freeVariable, - closureTypes, - context - ); - var closureEnvironmentPointer = closureEnvironmentPointerResult.value(); - context = closureEnvironmentPointerResult.context(); - - // TODO: test behaviour when local is defined later - return context.onceShedLocalDefined( - freeVariable.name(), - c -> c.addInstruction(new LlvmStore( - LlvmCodeGenTypes.VALUE_TYPE, - c.shedLocal(freeVariable.name()), - closureEnvironmentPointer - )) - ); - } - - private static LlvmCodeGenContext loadClosureFreeVariable( - LlvmOperand closurePointer, - FreeVariable freeVariable, - Types closureTypes, - LlvmCodeGenContext context - ) { - var closureFreeVariablePointerResult = getClosureFreeVariablePointer( - closurePointer, - freeVariable, - closureTypes, - context - ); - var closureFreeVariablePointer = closureFreeVariablePointerResult.value(); - context = closureFreeVariablePointerResult.context(); - - var closureFreeVariableResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_FREE_VARIABLE, - freeVariable.name() - ); - var closureFreeVariable = closureFreeVariableResult.value(); - context = closureFreeVariableResult.context(); - - context = context.addInstruction(new LlvmLoad( - closureFreeVariable, - LlvmCodeGenTypes.VALUE_TYPE, - closureFreeVariablePointer - )); - - return context.addShedLocal(freeVariable.name(), closureFreeVariable); - } - - private static LlvmCodeGenResult<LlvmVariableLocal> getClosureFreeVariablePointer( - LlvmOperand closurePointer, - FreeVariable freeVariable, - Types closureTypes, - LlvmCodeGenContext context - ) { - var freeVariablePointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.CLOSURE_FREE_VARIABLE_POINTER, - freeVariable.name() - ); - var freeVariablePointer = freeVariablePointerResult.value(); - context = freeVariablePointerResult.context(); - - context = context.addInstruction(new LlvmGetElementPtr( - freeVariablePointer, - closureTypes.closurePointer(), - closurePointer, - List.of( - LlvmTypedOperand.arrayIndex(0), - LlvmTypedOperand.structureIndex(1), - LlvmTypedOperand.arrayIndex(freeVariable.index()) - ) - )); - - return context.toResult(freeVariablePointer); - } -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenContext.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenContext.java deleted file mode 100644 index d0fea22f..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenContext.java +++ /dev/null @@ -1,438 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.pcollections.Empty; -import org.pcollections.PMap; -import org.pcollections.PStack; -import org.pcollections.PVector; -import org.shedlang.compiler.backends.llvm.ir.ast.*; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmInstruction; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmTerminatorInstruction; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableLocal; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmType; -import org.shedlang.compiler.typechecker.TypeInfo; -import org.shedlang.compiler.util.P; -import org.shedlang.compiler.util.POrderedMap; - -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; - -public record LlvmCodeGenContext( - ModuleContext moduleContext, - FunctionContext functionContext -) { - record ModuleContext( - TypeInfo typeInfo, - POrderedMap<String, LlvmTopLevelEntity> topLevelEntitiesByName - ) { - public static ModuleContext fromTypeInfo(TypeInfo typeInfo) { - return new ModuleContext(typeInfo, POrderedMap.empty()); - } - - public ModuleContext addTopLevelEntity(LlvmTopLevelEntity topLevelEntity) { - return new ModuleContext( - typeInfo, - topLevelEntitiesByName.plus(topLevelEntity.name(), topLevelEntity) - ); - } - - public String generateTopLevelEntityName( - LlvmCodeGenTopLevelEntitySpace space, - Optional<String> name - ) { - return NameAllocator.allocateName( - topLevelEntitiesByName::containsKey, - "shed__" + space, - name - ); - } - - public boolean hasTopLevelEntity(String name) { - return topLevelEntitiesByName.containsKey(name); - } - - public LlvmModule toModule() { - return new LlvmModule(topLevelEntitiesByName.toValues()); - } - - public <T> Result<T> toResult(T value) { - return new Result<>(value, this); - } - - record Result<T>(T value, ModuleContext context) {} - } - - record FunctionContext( - PStack<LlvmOperand> stack, - PMap<String, LlvmOperand> shedLocalNameToOperand, - PMap<String, PVector<Function<LlvmCodeGenContext, LlvmCodeGenContext>>> waitingForShedLocal, - PVector<LlvmBasicBlock> basicBlocks, - Optional<String> basicBlockLabel, - PVector<LlvmInstruction> instructions, - NameAllocator<LlvmCodeGenLocalVariableSpace> localVariableNames - ) { - public static final FunctionContext EMPTY = new FunctionContext( - Empty.stack(), - Empty.map(), - P.map(), - Empty.vector(), - Optional.empty(), - Empty.vector(), - NameAllocator.empty() - ); - - public FunctionContext push(LlvmOperand operand) { - return new FunctionContext( - stack.plus(operand), - shedLocalNameToOperand, - waitingForShedLocal, - basicBlocks, - basicBlockLabel, - instructions, - localVariableNames - ); - } - - public Result<LlvmOperand> pop() { - return new FunctionContext( - stack.minus(0), - shedLocalNameToOperand, - waitingForShedLocal, - basicBlocks, - basicBlockLabel, - instructions, - localVariableNames - ).toResult(stack.get(0)); - } - - public Result<PVector<Function<LlvmCodeGenContext, LlvmCodeGenContext>>> addShedLocal(String name, LlvmOperand value) { - var funcs = this.waitingForShedLocal.getOrDefault(name, P.vector()); - - return new FunctionContext( - stack, - shedLocalNameToOperand.plus(name, value), - waitingForShedLocal.minus(name), - basicBlocks, - basicBlockLabel, - instructions, - localVariableNames - ).toResult(funcs); - } - - public Optional<LlvmOperand> shedLocalOrNone(String name) { - return Optional.ofNullable(shedLocalNameToOperand.get(name)); - } - - public LlvmOperand shedLocal(String name) { - var local = shedLocalNameToOperand.get(name); - if (local == null) { - // TODO: better error - throw new RuntimeException("unrecognised local: " + name); - } else { - return local; - } - } - - public FunctionContext addWaitingForShedLocal(String name, Function<LlvmCodeGenContext, LlvmCodeGenContext> func) { - return new FunctionContext( - stack, - shedLocalNameToOperand, - waitingForShedLocal.plus( - name, - waitingForShedLocal.getOrDefault(name, P.vector()).plus(func) - ), - basicBlocks, - basicBlockLabel, - instructions, - localVariableNames - ); - } - - public FunctionContext setBasicBlockLabel(String basicBlockLabel) { - if (this.basicBlockLabel.isPresent()) { - // TODO: better error - throw new RuntimeException("basic block label is already set"); - } - - return new FunctionContext( - stack, - shedLocalNameToOperand, - waitingForShedLocal, - basicBlocks, - Optional.of(basicBlockLabel), - instructions, - localVariableNames - ); - } - - public FunctionContext addInstruction(LlvmInstruction instruction) { - return new FunctionContext( - stack, - shedLocalNameToOperand, - waitingForShedLocal, - basicBlocks, - basicBlockLabel, - instructions.plus(instruction), - localVariableNames - ); - } - - public FunctionContext addTerminatorInstruction( - LlvmTerminatorInstruction terminatorInstruction - ) { - return new FunctionContext( - stack, - shedLocalNameToOperand, - waitingForShedLocal, - basicBlocks.plus(new LlvmBasicBlock( - basicBlockLabel, - instructions, - terminatorInstruction - )), - Optional.empty(), - Empty.vector(), - localVariableNames - ); - } - - public Result<LlvmVariableLocal> generateVariableLocal( - LlvmCodeGenLocalVariableSpace space, - Optional<String> name - ) { - var result = localVariableNames.allocateName(space, name); - return new FunctionContext( - stack, - shedLocalNameToOperand, - waitingForShedLocal, - basicBlocks, - basicBlockLabel, - instructions, - result.allocator() - ).toResult(new LlvmVariableLocal(result.name())); - } - - public LlvmFunctionDefinition toFunction( - String name, - LlvmType returnType, - List<LlvmParam> params - ) { - if (!instructions.isEmpty()) { - // TODO: better error - throw new RuntimeException("unterminated basic block"); - } - - return new LlvmFunctionDefinition( - name, - returnType, - params, - basicBlocks - ); - } - - public <T> Result<T> toResult(T value) { - return new Result<>(value, this); - } - - record Result<T>(T value, FunctionContext context) {} - } - - public static LlvmCodeGenContext EMPTY = fromTypeInfo(TypeInfo.EMPTY); - - public static LlvmCodeGenContext fromTypeInfo(TypeInfo typeInfo) { - return new LlvmCodeGenContext( - ModuleContext.fromTypeInfo(typeInfo), - FunctionContext.EMPTY - ); - } - - public TypeInfo typeInfo() { - return moduleContext.typeInfo; - } - - public List<LlvmTopLevelEntity> topLevelEntities() { - return moduleContext.topLevelEntitiesByName.toValues(); - } - - public LlvmCodeGenResult<LlvmGlobalDefinition> addGlobalDefinition( - LlvmGlobalDefinitionBuilder builder - ) { - var globalDefinition = new LlvmGlobalDefinition( - generateTopLevelEntityName(builder.namePrefix().orElseThrow()), - builder.type().orElseThrow(), - builder.value(), - builder.constant(), - builder.isPrivate(), - builder.unnamedAddr() - ); - - return addTopLevelEntity(globalDefinition).toResult(globalDefinition); - } - - public LlvmCodeGenContext addTopLevelEntity(LlvmTopLevelEntity topLevelEntity) { - return new LlvmCodeGenContext( - this.moduleContext.addTopLevelEntity(topLevelEntity), - this.functionContext - ); - } - - public String generateTopLevelEntityName(LlvmCodeGenTopLevelEntitySpace space, String name) { - return generateTopLevelEntityName(space, Optional.of(name)); - } - - private String generateTopLevelEntityName(LlvmCodeGenTopLevelEntitySpace space) { - return generateTopLevelEntityName(space, Optional.empty()); - } - - private String generateTopLevelEntityName( - LlvmCodeGenTopLevelEntitySpace space, - Optional<String> name - ) { - return moduleContext.generateTopLevelEntityName(space, name); - } - - public boolean hasTopLevelEntity(String name) { - return moduleContext.hasTopLevelEntity(name); - } - - public LlvmModule toModule() { - return moduleContext.toModule(); - } - - public PStack<LlvmOperand> stack() { - return functionContext.stack; - } - - public LlvmCodeGenContext push(LlvmOperand operand) { - return new LlvmCodeGenContext( - moduleContext, - functionContext.push(operand) - ); - } - - public LlvmCodeGenResult<LlvmOperand> pop() { - var result = functionContext.pop(); - - return new LlvmCodeGenContext(moduleContext, result.context).toResult(result.value); - } - - public LlvmCodeGenContext addShedLocal(String name, LlvmOperand value) { - var result = this.functionContext.addShedLocal(name, value); - - var context = new LlvmCodeGenContext( - this.moduleContext, - result.context - ); - - for (var func : result.value) { - context = func.apply(context); - } - - return context; - } - - public LlvmCodeGenContext onceShedLocalDefined( - String name, - Function<LlvmCodeGenContext, LlvmCodeGenContext> func - ) { - var local = this.functionContext.shedLocalOrNone(name); - - if (local.isEmpty()) { - return new LlvmCodeGenContext( - this.moduleContext, - this.functionContext.addWaitingForShedLocal(name, func) - ); - } else { - return func.apply(this); - } - } - - public LlvmOperand shedLocal(String name) { - return this.functionContext.shedLocal(name); - } - - public Map<String, LlvmOperand> shedLocalNameToOperand() { - return this.functionContext.shedLocalNameToOperand; - } - - public List<LlvmBasicBlock> basicBlocks() { - return functionContext.basicBlocks; - } - - public LlvmCodeGenContext setBasicBlockLabel(String label) { - return new LlvmCodeGenContext( - this.moduleContext, - this.functionContext.setBasicBlockLabel(label) - ); - } - - public List<LlvmInstruction> instructions() { - return functionContext.instructions; - } - - public LlvmCodeGenContext addInstruction(LlvmInstruction instruction) { - return new LlvmCodeGenContext( - this.moduleContext, - this.functionContext.addInstruction(instruction) - ); - } - - public LlvmCodeGenContext addTerminatorInstruction( - LlvmTerminatorInstruction terminatorInstruction - ) { - return new LlvmCodeGenContext( - this.moduleContext, - this.functionContext.addTerminatorInstruction(terminatorInstruction) - ); - } - - public LlvmCodeGenResult<LlvmVariableLocal> generateVariableLocal( - LlvmCodeGenLocalVariableSpace space - ) { - return generateVariableLocal(space, Optional.empty()); - } - - public LlvmCodeGenResult<LlvmVariableLocal> generateVariableLocal( - LlvmCodeGenLocalVariableSpace space, - String name - ) { - return generateVariableLocal(space, Optional.of(name)); - } - - private LlvmCodeGenResult<LlvmVariableLocal> generateVariableLocal( - LlvmCodeGenLocalVariableSpace space, - Optional<String> name - ) { - var result = this.functionContext.generateVariableLocal(space, name); - return new LlvmCodeGenContext(this.moduleContext, result.context).toResult(result.value); - } - - public LlvmFunctionDefinition toFunction( - String name, - LlvmType returnType, - List<LlvmParam> params - ) { - return functionContext.toFunction(name, returnType, params); - } - - public <T> LlvmCodeGenResult<T> toResult(T value) { - return new LlvmCodeGenResult<>(value, this); - } - - public LlvmCodeGenContext createFunction( - Function<LlvmCodeGenContext, LlvmCodeGenResult<LlvmFunctionDefinition>> create - ) { - var bodyContext = new LlvmCodeGenContext( - this.moduleContext, - FunctionContext.EMPTY - ); - - var result = create.apply(bodyContext); - - return new LlvmCodeGenContext( - result.context().moduleContext(), - this.functionContext - ).addTopLevelEntity(result.value()); - } -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenNamespaces.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenNamespaces.java deleted file mode 100644 index b3ef2010..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenNamespaces.java +++ /dev/null @@ -1,288 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmBasicBlock; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmFunctionDeclaration; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmFunctionDefinition; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmGlobalDefinition; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.*; -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.LlvmTypePointer; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypeStructure; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; -import org.shedlang.compiler.types.NamespaceName; -import org.shedlang.compiler.types.NamespaceTypeInfo; - -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.IntStream; - -public class LlvmCodeGenNamespaces { - private LlvmCodeGenNamespaces() { - } - - private static LlvmTypePointer typeNamespacePointer(NamespaceTypeInfo namespaceTypeInfo) { - return new LlvmTypePointer(typeNamespaceStruct(namespaceTypeInfo)); - } - - private static LlvmType typeNamespaceStruct(NamespaceTypeInfo namespaceTypeInfo) { - return new LlvmTypeStructure(Collections.nCopies( - namespaceTypeInfo.fieldCount(), - LlvmCodeGenTypes.VALUE_TYPE - )); - } - - private static LlvmOperand operandNamespaceValue(NamespaceName namespaceName) { - return new LlvmOperandPtrToInt( - operandNamespaceStruct(namespaceName), - LlvmCodeGenTypes.VALUE_TYPE - ); - } - - private static LlvmOperand operandNamespaceStruct(NamespaceName namespaceName) { - return new LlvmVariableGlobal(globalNameNamespaceValue(namespaceName)); - } - - private static String globalNameNamespaceValue(NamespaceName namespaceName) { - return "shed__namespace__" + namespaceNameToLlvmIdentifier(namespaceName); - } - - public static String globalNameNamespaceImport(NamespaceName namespaceName) { - return "shed__namespaceImport__" + namespaceNameToLlvmIdentifier(namespaceName); - } - - private static String globalNameNamespaceInit(NamespaceName namespaceName) { - return "shed__namespaceInit__" + namespaceNameToLlvmIdentifier(namespaceName); - } - - private static String globalNameNamespaceIsInited(NamespaceName namespaceName) { - return "shed__namespaceIsInited__" + namespaceNameToLlvmIdentifier(namespaceName); - } - - private static String namespaceNameToLlvmIdentifier(NamespaceName namespaceName) { - return String.join("_", namespaceName.parts()); - } - - public static LlvmCodeGenResult<LlvmOperand> importValue( - NamespaceName namespaceName, - LlvmCodeGenContext context - ) { - var importName = globalNameNamespaceImport(namespaceName); - - if (!context.hasTopLevelEntity(importName)) { - context = context.addTopLevelEntity(new LlvmFunctionDeclaration( - importName, - LlvmCodeGenTypes.VALUE_TYPE, - List.of() - )); - } - - var namespaceResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.NAMESPACE, - namespaceNameToLlvmIdentifier(namespaceName) - ); - var namespace = namespaceResult.value(); - context = namespaceResult.context(); - - return context.addInstruction(new LlvmCall( - namespace, - LlvmCodeGenTypes.VALUE_TYPE, - new LlvmVariableGlobal(importName), - List.of() - )).toResult(namespace); - } - - public static LlvmCodeGenContext define( - NamespaceName namespaceName, - Function<LlvmCodeGenContext, LlvmCodeGenContext> generateInitBody, - LlvmCodeGenContext context - ) { - context = context.addTopLevelEntity(defineNamespaceIsInited(namespaceName)); - - context = context.addTopLevelEntity(defineNamespaceValue( - namespaceName, - context.typeInfo().namespaceTypeInfo(namespaceName) - )); - - context = context.createFunction(initContext -> { - initContext = generateInitBody.apply(initContext); - - initContext = initContext.addInstruction(new LlvmStore( - LlvmTypes.INT_1, - new LlvmOperandInt(1), - new LlvmVariableGlobal(globalNameNamespaceIsInited(namespaceName)) - )); - - initContext = initContext.addTerminatorInstruction(new LlvmReturnVoid()); - - var namespaceInitFunction = initContext.toFunction( - globalNameNamespaceInit(namespaceName), - LlvmTypes.VOID, - List.of() - ); - - return initContext.toResult(namespaceInitFunction); - }); - - var namespaceImportFunction = new LlvmFunctionDefinition( - globalNameNamespaceImport(namespaceName), - LlvmCodeGenTypes.VALUE_TYPE, - List.of(), - List.of( - new LlvmBasicBlock( - Optional.empty(), - List.of( - new LlvmLoad( - new LlvmVariableLocal("isInited"), - LlvmTypes.INT_1, - new LlvmVariableGlobal(globalNameNamespaceIsInited(namespaceName)) - ) - ), - new LlvmBr( - new LlvmVariableLocal("isInited"), - "inited", - "init" - ) - ), - new LlvmBasicBlock( - Optional.of("init"), - List.of( - new LlvmCall( - Optional.empty(), - LlvmTypes.VOID, - new LlvmVariableGlobal(globalNameNamespaceInit(namespaceName)), - List.of() - ) - ), - new LlvmBrUnconditional("inited") - ), - new LlvmBasicBlock( - Optional.of("inited"), - List.of(), - new LlvmReturn( - LlvmCodeGenTypes.VALUE_TYPE, - operandNamespaceValue(namespaceName) - ) - ) - ) - ); - - return context.addTopLevelEntity(namespaceImportFunction); - } - - private static LlvmGlobalDefinition defineNamespaceIsInited( - NamespaceName namespaceName - ) { - return new LlvmGlobalDefinition( - globalNameNamespaceIsInited(namespaceName), - LlvmTypes.INT_1, - Optional.of(new LlvmOperandInt(0)), - false, - true, - true - ); - } - - private static LlvmGlobalDefinition defineNamespaceValue( - NamespaceName namespaceName, - NamespaceTypeInfo namespaceTypeInfo - ) { - return new LlvmGlobalDefinition( - globalNameNamespaceValue(namespaceName), - typeNamespaceStruct(namespaceTypeInfo), - Optional.of(new LlvmOperandStructure( - IntStream.range(0, namespaceTypeInfo.fieldCount()) - .mapToObj(ignored -> new LlvmTypedOperand( - LlvmCodeGenTypes.VALUE_TYPE, - new LlvmOperandInt(0) - )) - .toList() - )), - false, - true, - true - ); - } - - public static LlvmCodeGenContext fieldStore( - NamespaceName namespaceName, - String fieldName, - LlvmOperand fieldValue, - LlvmCodeGenContext context - ) { - var namespaceTypeInfo = context.typeInfo().namespaceTypeInfo(namespaceName); - - var fieldPointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.FIELD_POINTER, - fieldName - ); - var fieldPointer = fieldPointerResult.value(); - context = fieldPointerResult.context(); - - return context.addInstruction(new LlvmGetElementPtr( - fieldPointer, - typeNamespacePointer(namespaceTypeInfo), - operandNamespaceStruct(namespaceName), - List.of( - LlvmTypedOperand.arrayIndex(0), - LlvmTypedOperand.structureIndex(namespaceTypeInfo.fieldIndex(fieldName)) - ) - )).addInstruction(new LlvmStore( - LlvmCodeGenTypes.VALUE_TYPE, - fieldValue, - fieldPointer - )); - } - - public static LlvmCodeGenResult<LlvmVariableLocal> fieldLoad( - NamespaceName namespaceName, - LlvmOperand namespace, - String fieldName, - LlvmCodeGenContext context - ) { - var namespaceTypeInfo = context.typeInfo().namespaceTypeInfo(namespaceName); - - var namespaceStructPointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.NAMESPACE_STRUCT_POINTER, - String.join("_", namespaceName.parts()) - ); - var namespaceStructPointer = namespaceStructPointerResult.value(); - context = namespaceStructPointerResult.context(); - - context = context.addInstruction(new LlvmIntToPtr( - namespaceStructPointer, - LlvmCodeGenTypes.VALUE_TYPE, - namespace - )); - - var fieldPointerResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.FIELD_POINTER, - fieldName - ); - var fieldPointer = fieldPointerResult.value(); - context = fieldPointerResult.context(); - - var fieldResult = context.generateVariableLocal( - LlvmCodeGenLocalVariableSpace.FIELD, - fieldName - ); - var field = fieldResult.value(); - context = fieldResult.context(); - - return context.addInstruction(new LlvmGetElementPtr( - fieldPointer, - typeNamespacePointer(namespaceTypeInfo), - namespaceStructPointer, - List.of( - LlvmTypedOperand.arrayIndex(0), - LlvmTypedOperand.structureIndex(namespaceTypeInfo.fieldIndex(fieldName)) - ) - )).addInstruction(new LlvmLoad( - field, - LlvmCodeGenTypes.VALUE_TYPE, - fieldPointer - )).toResult(field); - } -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenResult.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenResult.java deleted file mode 100644 index f52c05ec..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenResult.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -public record LlvmCodeGenResult<T>( - T value, - LlvmCodeGenContext context -) { -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenRuntime.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenRuntime.java deleted file mode 100644 index 3e9c86de..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenRuntime.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmCall; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmTypedOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariable; -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.LlvmTypes; - -import java.util.List; - -public class LlvmCodeGenRuntime { - private LlvmCodeGenRuntime() { - } - - public static LlvmCodeGenContext callAlloc( - LlvmVariable target, - LlvmType type, - LlvmOperand size, - LlvmCodeGenContext context - ) { - return context.addInstruction(new LlvmCall( - target, - type, - new LlvmVariableGlobal("shed__runtime__alloc"), - List.of( - new LlvmTypedOperand(LlvmTypes.INT_64, size) - ) - )); - } -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenStrings.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenStrings.java deleted file mode 100644 index 6c9c782d..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenStrings.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmFunctionDeclaration; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmGlobalDefinition; -import org.shedlang.compiler.backends.llvm.ir.ast.LlvmParam; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmCall; -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.LlvmTypePointer; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -public class LlvmCodeGenStrings { - private LlvmCodeGenStrings() { - } - - public static final LlvmType TYPE_STRING_LENGTH = LlvmTypes.INT_64; - - public static LlvmType typeStringCodeUnits(int size) { - return LlvmTypes.array(size, LlvmTypes.INT_8); - } - - public static LlvmType typeStringStruct(int size) { - return LlvmTypes.structure(List.of( - TYPE_STRING_LENGTH, - typeStringCodeUnits(size) - )); - } - - public static LlvmTypePointer typeStringPointer(int size) { - return LlvmTypes.pointer(typeStringStruct(size)); - } - - public static LlvmCodeGenResult<LlvmGlobalDefinition> defineString(String value, LlvmCodeGenContext context) { - var codeUnits = value.getBytes(StandardCharsets.UTF_8); - - var codeUnitOperands = new ArrayList<LlvmOperand>(); - for (var codeUnit : codeUnits) { - codeUnitOperands.add(new LlvmOperandInt(codeUnit)); - } - - var llvmValue = new LlvmOperandStructure(List.of( - new LlvmTypedOperand(TYPE_STRING_LENGTH, new LlvmOperandInt(codeUnits.length)), - new LlvmTypedOperand( - typeStringCodeUnits(codeUnits.length), - new LlvmOperandArray( - LlvmTypes.INT_8, - codeUnitOperands - ) - ) - )); - - var globalDefinitionBuilder = LlvmGlobalDefinitionBuilder.builder() - .namePrefix(LlvmCodeGenTopLevelEntitySpace.STRING) - .type(typeStringStruct(codeUnits.length)) - .value(llvmValue) - .isPrivate(true) - .unnamedAddr(true) - .constant(true); - - return context.addGlobalDefinition(globalDefinitionBuilder); - } - - public static LlvmOperand operandAsShedObject(LlvmGlobalDefinition globalDefinition) { - return new LlvmOperandPtrToInt( - new LlvmVariableGlobal(globalDefinition.name()), - LlvmCodeGenTypes.VALUE_TYPE - ); - } - - public static LlvmCodeGenContext add( - LlvmVariable target, - LlvmOperand left, - LlvmOperand right, - LlvmCodeGenContext context - ) { - var runtimeAddName = "shed__runtime__string_add"; - - if (!context.hasTopLevelEntity(runtimeAddName)) { - context = context.addTopLevelEntity(new LlvmFunctionDeclaration( - runtimeAddName, - LlvmCodeGenTypes.STRING_TYPE, - List.of( - new LlvmParam(LlvmCodeGenTypes.STRING_TYPE, "left"), - new LlvmParam(LlvmCodeGenTypes.STRING_TYPE, "right") - ) - )); - } - - return context.addInstruction(new LlvmCall( - target, - LlvmCodeGenTypes.STRING_TYPE, - new LlvmVariableGlobal(runtimeAddName), - List.of( - new LlvmTypedOperand(LlvmCodeGenTypes.STRING_TYPE, left), - new LlvmTypedOperand(LlvmCodeGenTypes.STRING_TYPE, right) - ) - )); - } -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenTypes.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenTypes.java deleted file mode 100644 index e2d37a8a..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenTypes.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypeScalar; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; - -public class LlvmCodeGenTypes { - private LlvmCodeGenTypes() { - } - - public static final LlvmTypeScalar VALUE_TYPE = LlvmTypes.INT_64; - public static final LlvmTypeScalar INT_TYPE = LlvmTypes.INT_64; - public static final LlvmTypeScalar STRING_TYPE = VALUE_TYPE; -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmGlobalDefinitionBuilder.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmGlobalDefinitionBuilder.java deleted file mode 100644 index b559c315..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmGlobalDefinitionBuilder.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.shedlang.compiler.backends.llvm; - -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmType; - -import java.util.Optional; - -public record LlvmGlobalDefinitionBuilder( - Optional<LlvmCodeGenTopLevelEntitySpace> namePrefix, - Optional<LlvmType> type, - Optional<LlvmOperand> value, - boolean constant, - boolean isPrivate, - boolean unnamedAddr -) { - public static LlvmGlobalDefinitionBuilder builder() { - return new LlvmGlobalDefinitionBuilder( - Optional.empty(), - Optional.empty(), - Optional.empty(), - false, - false, - false - ); - } - - public LlvmGlobalDefinitionBuilder namePrefix(LlvmCodeGenTopLevelEntitySpace namePrefix) { - return new LlvmGlobalDefinitionBuilder( - Optional.of(namePrefix), - this.type, - this.value, - this.constant, - this.isPrivate, - this.unnamedAddr - ); - } - - public LlvmGlobalDefinitionBuilder type(LlvmType type) { - return new LlvmGlobalDefinitionBuilder( - this.namePrefix, - Optional.of(type), - this.value, - this.constant, - this.isPrivate, - this.unnamedAddr - ); - } - - public LlvmGlobalDefinitionBuilder value(LlvmOperand value) { - return new LlvmGlobalDefinitionBuilder( - this.namePrefix, - this.type, - Optional.of(value), - this.constant, - this.isPrivate, - this.unnamedAddr - ); - } - - public LlvmGlobalDefinitionBuilder constant(boolean constant) { - return new LlvmGlobalDefinitionBuilder( - this.namePrefix, - this.type, - this.value, - constant, - this.isPrivate, - this.unnamedAddr - ); - } - - public LlvmGlobalDefinitionBuilder isPrivate(boolean isPrivate) { - return new LlvmGlobalDefinitionBuilder( - this.namePrefix, - this.type, - this.value, - this.constant, - isPrivate, - this.unnamedAddr - ); - } - - public LlvmGlobalDefinitionBuilder unnamedAddr(boolean unnamedAddr) { - return new LlvmGlobalDefinitionBuilder( - this.namePrefix, - this.type, - this.value, - this.constant, - this.isPrivate, - unnamedAddr - ); - } -} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmSizeOf.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmSizeOf.java deleted file mode 100644 index d59ea616..00000000 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmSizeOf.java +++ /dev/null @@ -1,44 +0,0 @@ -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.LlvmPtrToInt; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperandNull; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmTypedOperand; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmType; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; - -import java.util.List; - -public class LlvmSizeOf { - private LlvmSizeOf() { - } - - public static LlvmCodeGenResult<LlvmOperand> sizeOf(LlvmType type, LlvmCodeGenContext context) { - var sizePtrResult = context.generateVariableLocal(LlvmCodeGenLocalVariableSpace.SIZE_PTR); - var sizePtr = sizePtrResult.value(); - context = sizePtrResult.context(); - - var sizeResult = context.generateVariableLocal(LlvmCodeGenLocalVariableSpace.SIZE); - var size = sizeResult.value(); - context = sizeResult.context(); - - return context - .addInstruction( - new LlvmGetElementPtr( - sizePtr, - LlvmTypes.pointer(type), - new LlvmOperandNull(), - List.of(LlvmTypedOperand.arrayIndex(0)) - ) - ) - .addInstruction( - new LlvmPtrToInt( - size, - sizePtr, - LlvmTypes.INT_64 - ) - ) - .toResult(size); - } -} |
