translator: add type detection and initializing on class variables

This commit is contained in:
Alexey Stepanov
2016-08-08 18:55:13 +03:00
parent 02225601e2
commit 5fb10e68bd
5 changed files with 47 additions and 6 deletions
@@ -78,7 +78,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
executeWhileBlock(condition.firstChild as KtBinaryExpression, bodyExpression.firstChild, scopeDepth, checkConditionBeforeExecute = false)
}
private fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? {
fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? {
return when (expr) {
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
is KtPostfixExpression -> evaluatePostfixExpression(expr, scopeDepth)
@@ -191,6 +191,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth)
}
private fun evaluateExtensionExpression(receiver: KtExpression, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)
val standardType = LLVMMapStandardType(receiverType!!.type!!)
@@ -229,7 +230,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return result
}
private fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement): LLVMSingleValue? {
fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement?): LLVMSingleValue? {
val type = receiver.type as LLVMReferenceType
val clazz = resolveClassOrObjectLocation(type)
val field = clazz.fieldsIndex[selectorName]
@@ -240,7 +241,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return result
}
val names = parseArgList(call as KtCallExpression, scopeDepth)
val names = parseArgList(call!! as KtCallExpression, scopeDepth)
val typePath = type.location.joinToString(".")
val types = if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""
val methodName = "${if (typePath.length > 0) "$typePath." else ""}${clazz.structName}.${selectorName.substringBefore('(')}$types"
@@ -486,7 +487,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
}
}
private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue)
fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue)
= addPrimitiveBinaryOperation(operator, referenceName, left, right)
private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable {
@@ -1,7 +1,9 @@
package org.kotlinnative.translator
import com.intellij.psi.PsiElement
import jdk.nashorn.internal.ir.Block
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.KotlinType
@@ -28,6 +30,7 @@ abstract class StructCodegen(open val state: TranslationState,
val enumFields = HashMap<String, LLVMVariable>()
val constructorFields = ArrayList<LLVMVariable>()
val initializedFields = HashMap<LLVMVariable, KtExpression>()
abstract val type: LLVMReferenceType
abstract var size: Int
@@ -64,11 +67,15 @@ abstract class StructCodegen(open val state: TranslationState,
for (declaration in declarations) {
when (declaration) {
is KtProperty -> {
val ktType = state.bindingContext.get(BindingContext.TYPE, declaration.typeReference)!!
val ktType = state.bindingContext.get(BindingContext.TYPE, declaration.typeReference)
?: state.bindingContext.get(BindingContext.VARIABLE, declaration)!!.type
val field = resolveType(declaration, ktType)
field.offset = offset
offset++
if ((declaration.initializer != null) && !(this is ObjectCodegen)){
initializedFields.put(field, declaration.initializer!!)
}
fields.add(field)
fieldsIndex[field.label] = field
size += field.type.size
@@ -133,7 +140,6 @@ abstract class StructCodegen(open val state: TranslationState,
}
private fun generateLoadArguments(thisField: LLVMVariable) {
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
codeBuilder.loadArgument(thisVariable, false)
@@ -163,6 +169,16 @@ abstract class StructCodegen(open val state: TranslationState,
}
}
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {}
val receiverThis = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
for ((variable, initializer) in initializedFields) {
val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevel, call = null)!!
val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevel)!!
blockCodegen.executeBinaryExpression(KtTokens.EQ, referenceName = null, left = left, right = right)
}
}
private fun generateReturn() {
@@ -0,0 +1,15 @@
/*package org.kotlinnative.translator.llvm.types
class LLVMStringType(override val length: Int) : LLVMArray, LLVMType() {
override var size: Int = 1
override val align = 8
override val defaultValue = ""
override fun mangle() = "String"
override fun basicType() = LLVMCharType()
override fun toString(): String = "i8*"
override fun fullType() = "[${length + 1} x i8]"
}
*/
@@ -0,0 +1 @@
initialized_class_fields_1() == 524
@@ -0,0 +1,8 @@
class initialized_class_fields_1_class {
var pos: Int = 524
}
fun initialized_class_fields_1(): Int {
val instance = initialized_class_fields_1_class()
return instance.pos
}