From 5cc56e98310c9e0492c7f1e38dde26244597a054 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Thu, 14 Jul 2016 15:39:47 +0300 Subject: [PATCH] translator: add LLVMArray, access to string by index, basic type for string --- .../translator/FunctionCodegen.kt | 26 ++++++++++++++----- .../translator/llvm/LLVMBuilder.kt | 5 ++++ .../translator/llvm/generators.kt | 3 ++- .../translator/llvm/types/LLVMArray.kt | 9 +++++++ .../translator/llvm/types/LLVMString.kt | 6 +++-- 5 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMArray.kt diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index 5e9bd499f90..dadd3d26ff4 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -136,22 +136,24 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction is KtConstantExpression -> evaluateConstantExpression(expr) is KtCallExpression -> evaluateCallExpression(expr, scopeDepth) is KtCallableReferenceExpression -> evaluateCallableReferenceExpression(expr) - is KtReferenceExpression -> evaluateReferenceExpression(expr) + is KtReferenceExpression -> evaluateReferenceExpression(expr, scopeDepth) is KtIfExpression -> evaluateIfOperator(expr.firstChild as LeafPsiElement, scopeDepth + 1, true) is KtDotQualifiedExpression -> evaluateDotExpression(expr) - is PsiWhiteSpace -> null is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr, scopeDepth + 1) + is PsiWhiteSpace -> null is PsiElement -> evaluatePsiElement(expr, scopeDepth) null -> null else -> throw UnsupportedOperationException() } } + fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression, scope: Int): LLVMSingleValue? { val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr) val type = (receiveValue as TypedCompileTimeConstant).type val value = receiveValue.getValue(type) ?: return null val variable = variableManager.receiveVariable(".str", LLVMStringType(value.toString().length), LLVMGlobalScope(), pointer = false) + codeBuilder.addStringConstant(variable, value.toString()) return variable } @@ -175,9 +177,19 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction return result } - private fun evaluateReferenceExpression(expr: KtReferenceExpression): LLVMSingleValue? { - val variableName = expr.firstChild.text - return variableManager.getLLVMvalue(variableName) + fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, scope: Int): LLVMSingleValue? { + val arrayNameVariable = evaluateReferenceExpression(expr.arrayExpression as KtReferenceExpression, scope) as LLVMVariable + val arrayIndex = evaluateConstantExpression(expr.indexExpressions.first() as KtConstantExpression) + val arrayReceivedVariable = codeBuilder.loadAndGetVariable(arrayNameVariable) + val arrayElementType = (arrayNameVariable.type as LLVMArray).basicType() + val indexVariable = codeBuilder.getNewVariable(arrayElementType, pointer = true) + codeBuilder.loadVariableOffset(indexVariable, arrayReceivedVariable, arrayIndex); + return indexVariable + } + + private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int): LLVMSingleValue? = when (expr) { + is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1) + else -> variableManager.getLLVMvalue(expr.firstChild.text) } private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int): LLVMSingleValue? { @@ -286,8 +298,8 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction val result = ArrayList() for (arg in args) { - val expr = evaluateExpression(arg.getArgumentExpression(), scopeDepth) as LLVMSingleValue - result.add(expr) + val currentExpression = evaluateExpression(arg.getArgumentExpression(), scopeDepth) as LLVMSingleValue + result.add(currentExpression) } return result 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 3a8daf181ca..bf7f43cfc78 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -131,6 +131,11 @@ class LLVMBuilder(val arm: Boolean) { llvmLocalCode.appendln(code) } + fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) { + val code = "$target = getelementptr inbounds ${target.type}, ${source.type} $source, ${index.type} ${index.value}" + llvmLocalCode.appendln(code) + } + fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) { val tmp = getNewVariable(source.type, source.pointer) llvmLocalCode.appendln("$tmp = load ${tmp.type}, ${source.getType()} $source, align ${tmp.type.align}") 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 d02bf2110a4..47d1c1d69cf 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -10,12 +10,13 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List?, returnTy "${if (declare) "declare" else "define"} $returnType @$name(${ argTypes?.mapIndexed { i: Int, s: LLVMVariable -> "${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).isReturn) "byval" else ""} %${s.label}" - }?.joinToString() }) ${ if (arm) "#0" else ""}" + }?.joinToString()}) ${if (arm) "#0" else ""}" fun LLVMMapStandardType(name: String, type: KotlinType): LLVMVariable = when { type.isFunctionType -> LLVMVariable(name, LLVMFunctionType(type), type.toString(), pointer = true) type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), type.toString()) type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), type.toString()) + type.toString() == "Char" -> LLVMVariable(name, LLVMCharType(), type.toString()) type.isUnit() -> LLVMVariable("", LLVMVoidType()) else -> LLVMVariable(name, LLVMReferenceType("$type"), name, pointer = true) } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMArray.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMArray.kt new file mode 100644 index 00000000000..370b1370ea2 --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMArray.kt @@ -0,0 +1,9 @@ +package org.kotlinnative.translator.llvm.types + +interface LLVMArray { + + fun basicType(): LLVMType + fun fullType(): String + + val length: Int +} \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMString.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMString.kt index 04825564e8c..c74d623af1b 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMString.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMString.kt @@ -1,10 +1,12 @@ package org.kotlinnative.translator.llvm.types -class LLVMStringType(val length : Int) : LLVMType() { +class LLVMStringType(override val length: Int) : LLVMArray, LLVMType() { + override val size: Byte = 1 override val align = 8 override val defaultValue = "" + override fun basicType() = LLVMCharType() override fun toString(): String = "i8*" - fun fullType() = "[${length+1} x i8]" + override fun fullType() = "[${length + 1} x i8]" }