translator: add LLVMArray, access to string by index, basic type for string

This commit is contained in:
Alexey Stepanov
2016-07-14 15:39:47 +03:00
parent 64c88ffe03
commit 5cc56e9831
5 changed files with 39 additions and 10 deletions
@@ -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<LLVMSingleValue>()
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
@@ -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}")
@@ -10,12 +10,13 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, 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)
}
@@ -0,0 +1,9 @@
package org.kotlinnative.translator.llvm.types
interface LLVMArray {
fun basicType(): LLVMType
fun fullType(): String
val length: Int
}
@@ -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]"
}