translator: Nullable types support
This commit is contained in:
@@ -332,6 +332,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
||||
KtNodeTypes.INTEGER_CONSTANT -> LLVMIntType()
|
||||
KtNodeTypes.FLOAT_CONSTANT -> LLVMDoubleType()
|
||||
KtNodeTypes.CHARACTER_CONSTANT -> LLVMCharType()
|
||||
KtNodeTypes.NULL -> LLVMNullType()
|
||||
else -> throw IllegalArgumentException("Unknown type")
|
||||
}
|
||||
return LLVMConstant(node.firstChildNode.text, type, pointer = 0)
|
||||
@@ -341,29 +342,11 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
||||
return when (element) {
|
||||
is LeafPsiElement -> evaluateLeafPsiElement(element, scopeDepth)
|
||||
is KtConstantExpression -> evaluateConstantExpression(element)
|
||||
is KtTypeReference -> evaluateTypeReference(element)
|
||||
KtTokens.INTEGER_LITERAL -> null
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateTypeReference(element: KtTypeReference): LLVMSingleValue? {
|
||||
val type = element.typeElement
|
||||
val operator = element.getNextSiblingIgnoringWhitespaceAndComments()
|
||||
val value = operator?.getNextSiblingIgnoringWhitespaceAndComments() as KtConstantExpression
|
||||
|
||||
when (type) {
|
||||
is KtUserType -> {
|
||||
val i = 1
|
||||
}
|
||||
}
|
||||
|
||||
// return when (operator) {
|
||||
// else -> throw UnsupportedOperationException()
|
||||
// }
|
||||
return null
|
||||
}
|
||||
|
||||
private fun evaluateLeafPsiElement(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
|
||||
return when (element.elementType) {
|
||||
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth)
|
||||
@@ -451,7 +434,6 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
||||
|
||||
private fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) {
|
||||
is LLVMStringType -> codeBuilder.storeString(to, from, 0)
|
||||
is LLVMReferenceType -> codeBuilder.copyVariableRef(to, from)
|
||||
else -> codeBuilder.copyVariableValue(to, from)
|
||||
}
|
||||
|
||||
@@ -474,8 +456,23 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
||||
}
|
||||
}
|
||||
is LLVMConstant -> {
|
||||
val newVar = variableManager.receiveVariable(identifier, assignExpression.type!!, LLVMRegisterScope(), pointer = 1)
|
||||
if (assignExpression.type is LLVMNullType) {
|
||||
val reference = LLVMMapStandardType(identifier, variable.type)
|
||||
if (state.classes.containsKey(variable.type.toString().dropLast(1))) {
|
||||
(reference.type as LLVMReferenceType).prefix = "class"
|
||||
}
|
||||
|
||||
codeBuilder.allocStackVar(reference)
|
||||
reference.pointer += 1
|
||||
|
||||
codeBuilder.storeNull(reference)
|
||||
val result = codeBuilder.loadAndGetVariable(reference)
|
||||
|
||||
variableManager.addVariable(identifier, result, scopeDepth)
|
||||
return null
|
||||
}
|
||||
|
||||
val newVar = variableManager.receiveVariable(identifier, assignExpression.type!!, LLVMRegisterScope(), pointer = 1)
|
||||
codeBuilder.addConstant(newVar, assignExpression)
|
||||
variableManager.addVariable(identifier, newVar, scopeDepth)
|
||||
}
|
||||
|
||||
@@ -148,11 +148,16 @@ class LLVMBuilder(val arm: Boolean) {
|
||||
localCode.appendln(getNewVariable(LLVMIntType()).toString() + " = add i1 0, 0 ; nop instruction")
|
||||
}
|
||||
|
||||
fun storeVariable(target: LLVMVariable, source: LLVMSingleValue) {
|
||||
fun storeVariable(target: LLVMSingleValue, source: LLVMSingleValue) {
|
||||
val code = "store ${source.getType()} $source, ${target.getType()} $target, align ${source.type?.align!!}"
|
||||
localCode.appendln(code)
|
||||
}
|
||||
|
||||
fun storeNull(result: LLVMVariable) {
|
||||
val code = "store ${result.getType().dropLast(1)} null, ${result.getType()} $result, align $POINTER_SIZE"
|
||||
localCode.appendln(code)
|
||||
}
|
||||
|
||||
fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) {
|
||||
val code = "$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}"
|
||||
localCode.appendln(code)
|
||||
@@ -167,10 +172,6 @@ class LLVMBuilder(val arm: Boolean) {
|
||||
localCode.appendln("store ${target.type} $from, ${target.getType()} $target, align ${from.type.align}")
|
||||
}
|
||||
|
||||
fun copyVariableRef(to: LLVMVariable, from: LLVMVariable) {
|
||||
var i = 1
|
||||
}
|
||||
|
||||
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable {
|
||||
val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = llvmVariable.pointer + 1)
|
||||
addVariableByRef(allocVar, llvmVariable, store)
|
||||
|
||||
@@ -17,5 +17,6 @@ fun LLVMMapStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMR
|
||||
type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), type.toString(), scope)
|
||||
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), type.toString(), scope)
|
||||
type.isUnit() -> LLVMVariable("", LLVMVoidType(), "", scope)
|
||||
type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType("${type.toString().dropLast(1)}"), name, scope, pointer = 1)
|
||||
else -> LLVMVariable(name, LLVMReferenceType("$type"), name, scope, pointer = 1)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
class LLVMNullType() : LLVMType() {
|
||||
override val align: Int = 0
|
||||
override val size: Byte = 0
|
||||
override val defaultValue: String = "0"
|
||||
}
|
||||
Reference in New Issue
Block a user