From 75d386aede1086574b562ba9a44db611c4ff52d8 Mon Sep 17 00:00:00 2001 From: e5l Date: Tue, 19 Jul 2016 16:07:10 +0300 Subject: [PATCH] translator: Nullable types support --- .../translator/FunctionCodegen.kt | 37 +++++++++---------- .../translator/llvm/LLVMBuilder.kt | 11 +++--- .../translator/llvm/generators.kt | 1 + .../{LLVMCharType.kt => LLVMByteType.kt} | 0 .../translator/llvm/types/LLVMNullType.kt | 7 ++++ 5 files changed, 31 insertions(+), 25 deletions(-) rename translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/{LLVMCharType.kt => LLVMByteType.kt} (100%) create mode 100644 translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMNullType.kt diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index 93f53b57009..6a15e6b1248 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -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) } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt index 593dabf8fe5..bc221fa5efe 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -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) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt index c771a198549..3f8b2afc7c2 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -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) } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMCharType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMByteType.kt similarity index 100% rename from translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMCharType.kt rename to translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMByteType.kt diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMNullType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMNullType.kt new file mode 100644 index 00000000000..2df2887b72c --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMNullType.kt @@ -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" +}