aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-09-16 15:20:50 +0100
committerMichael Williamson <mike@zwobble.org>2023-09-16 15:20:50 +0100
commit410d51abc96defa8b16d1041e9cfe8668221798a (patch)
treeb9c164f0d13b56041dc2e081a3d12889426822eb /src/main/java
parentd2d6019cabed6e04a04bef402442697f9c32df11 (diff)
Remove direct LLVM backend
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/backends/Backend.java4
-rw-r--r--src/main/java/org/shedlang/compiler/backends/Backends.java3
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmBackend.java139
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java405
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenClosures.java421
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenContext.java438
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenNamespaces.java288
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenResult.java7
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenRuntime.java32
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenStrings.java103
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGenTypes.java13
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmGlobalDefinitionBuilder.java92
-rw-r--r--src/main/java/org/shedlang/compiler/backends/llvm/LlvmSizeOf.java44
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);
- }
-}