diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-06-14 20:13:09 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-06-14 20:14:04 +0100 |
| commit | 57446428f678ebc2bc5ad34d04e41feabe35d28f (patch) | |
| tree | 9e619123ab79b69ed15b77f4b56a54c9ccb921aa /src/main/java | |
| parent | d4a8c7d7cba85e107b8532036b6e6838c57f4e2a (diff) | |
Compile zero-args to LLVM IR
Diffstat (limited to 'src/main/java')
4 files changed, 167 insertions, 14 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java index 0cd282cf..89cf70b7 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompiler.java @@ -1,6 +1,5 @@ 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.LlvmOperandInt; import org.shedlang.compiler.stackir.instructions.*; import org.shedlang.compiler.types.NamespaceName; @@ -19,18 +18,10 @@ public class LlvmCompiler { var receiver = receiverResult.value(); context = receiverResult.context(); - var temporaryResult = context.generateVariableLocal( - LlvmCompilerLocalVariableSpace.TEMPORARY - ); - var temporary = temporaryResult.value(); - context = temporaryResult.context(); - - yield context.addInstruction(new LlvmCall( - temporary, - LlvmCompilerTypes.VALUE_TYPE, + yield LlvmCompilerClosures.call( receiver, - List.of() - )).push(temporary); + context + ); } case DefineFunctionInstruction defineFunctionInstruction -> { throw new UnsupportedOperationException("TODO"); diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerClosures.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerClosures.java new file mode 100644 index 00000000..68f66719 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerClosures.java @@ -0,0 +1,158 @@ +package org.shedlang.compiler.backends.llvm; + +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmCall; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmGetElementPtr; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmIntToPtr; +import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmLoad; +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.LlvmVariableLocal; +import org.shedlang.compiler.backends.llvm.ir.ast.types.*; + +import java.util.List; + +public class LlvmCompilerClosures { + private LlvmCompilerClosures() { + } + + public static LlvmTypePointer typeClosurePointer() { + return LlvmTypes.pointer(typeClosureStruct()); + } + + public static LlvmTypeStructure typeClosureStruct() { + return LlvmTypes.structure(List.of( + typeClosureFunctionPointer(), + typeClosureEnvironment() + )); + } + + public static LlvmTypePointer typeClosureFunctionPointer() { + return LlvmTypes.pointer(typeClosureFunction()); + } + + public static LlvmTypeFunction typeClosureFunction() { + return LlvmTypes.function( + LlvmCompilerTypes.VALUE_TYPE, + List.of(typeClosureEnvironmentPointer()) + ); + } + + public static LlvmTypePointer typeClosureEnvironmentPointer() { + return LlvmTypes.pointer(typeClosureEnvironment()); + } + + public static LlvmTypeArray typeClosureEnvironment() { + return LlvmTypes.array(0, LlvmCompilerTypes.VALUE_TYPE); + } + + public static LlvmCompilerContext call( + LlvmOperand closure, + LlvmCompilerContext 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 environmentPointerResult = getClosureEnvironmentPointer(closurePointer, context); + var environmentPointer = environmentPointerResult.value(); + context = environmentPointerResult.context(); + + var callTargetResult = context.generateVariableLocal( + LlvmCompilerLocalVariableSpace.TEMPORARY + ); + var callTarget = callTargetResult.value(); + context = callTargetResult.context(); + + return context.addInstruction(new LlvmCall( + callTarget, + LlvmCompilerTypes.VALUE_TYPE, + functionPointer, + List.of(new LlvmTypedOperand(typeClosureEnvironmentPointer(), environmentPointer)) + )).push(callTarget); + } + + private static LlvmCompilerResult<LlvmVariableLocal> castValueToClosurePointer( + LlvmOperand value, + LlvmCompilerContext context + ) { + var closurePointerResult = context.generateVariableLocal( + LlvmCompilerLocalVariableSpace.CLOSURE_POINTER + ); + var closurePointer = closurePointerResult.value(); + context = closurePointerResult.context(); + + context = context.addInstruction(new LlvmIntToPtr( + closurePointer, + LlvmCompilerTypes.VALUE_TYPE, + value, + typeClosurePointer() + )); + + return context.toResult(closurePointer); + } + + private static LlvmCompilerResult<LlvmVariableLocal> loadClosureFunctionPointer( + LlvmOperand closurePointer, + LlvmCompilerContext context + ) { + var functionPointerPointerResult = getClosureFunctionPointerPointer(closurePointer, context); + var functionPointerPointer = functionPointerPointerResult.value(); + context = functionPointerPointerResult.context(); + + var functionPointerResult = context.generateVariableLocal( + LlvmCompilerLocalVariableSpace.CLOSURE_FUNCTION_POINTER + ); + var functionPointer = functionPointerResult.value(); + context = functionPointerResult.context(); + + return context.addInstruction(new LlvmLoad( + functionPointer, + typeClosureFunctionPointer(), + functionPointerPointer + )).toResult(functionPointer); + } + + private static LlvmCompilerResult<LlvmVariableLocal> getClosureFunctionPointerPointer( + LlvmOperand closurePointer, + LlvmCompilerContext context + ) { + var functionPointerPointerResult = context.generateVariableLocal( + LlvmCompilerLocalVariableSpace.CLOSURE_FUNCTION_POINTER_POINTER + ); + var functionPointerPointer = functionPointerPointerResult.value(); + context = functionPointerPointerResult.context(); + + context = context.addInstruction(new LlvmGetElementPtr( + functionPointerPointer, + typeClosurePointer(), + closurePointer, + List.of(LlvmTypedOperand.arrayIndex(0), LlvmTypedOperand.structureIndex(0)) + )); + + return context.toResult(functionPointerPointer); + } + + private static LlvmCompilerResult<LlvmVariableLocal> getClosureEnvironmentPointer( + LlvmOperand closurePointer, + LlvmCompilerContext context + ) { + var environmentPointerResult = context.generateVariableLocal( + LlvmCompilerLocalVariableSpace.CLOSURE_ENVIRONMENT_POINTER + ); + var environmentPointer = environmentPointerResult.value(); + context = environmentPointerResult.context(); + + context = context.addInstruction(new LlvmGetElementPtr( + environmentPointer, + typeClosurePointer(), + closurePointer, + List.of(LlvmTypedOperand.arrayIndex(0), LlvmTypedOperand.structureIndex(1)) + )); + + return context.toResult(environmentPointer); + } +} diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalVariableSpace.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalVariableSpace.java index 756e139b..457fa7c5 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalVariableSpace.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerLocalVariableSpace.java @@ -1,6 +1,10 @@ package org.shedlang.compiler.backends.llvm; public enum LlvmCompilerLocalVariableSpace { + CLOSURE_POINTER("closurePointer"), + CLOSURE_FUNCTION_POINTER("closureFunctionPointer"), + CLOSURE_FUNCTION_POINTER_POINTER("closureFunctionPointerPointer"), + CLOSURE_ENVIRONMENT_POINTER("closureEnvironmentPointer"), FIELD_POINTER("fieldPointer"), TEMPORARY("tmp"); diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerTypes.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerTypes.java index 773cbccd..3623d829 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerTypes.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCompilerTypes.java @@ -1,11 +1,11 @@ package org.shedlang.compiler.backends.llvm; -import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmType; +import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypeScalar; import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; public class LlvmCompilerTypes { private LlvmCompilerTypes() { } - public static final LlvmType VALUE_TYPE = LlvmTypes.INT_64; + public static final LlvmTypeScalar VALUE_TYPE = LlvmTypes.INT_64; } |
