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) 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) { return when (expr) {
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth) is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
is KtPostfixExpression -> evaluatePostfixExpression(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) return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth)
} }
private fun evaluateExtensionExpression(receiver: KtExpression, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? { private fun evaluateExtensionExpression(receiver: KtExpression, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver) val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)
val standardType = LLVMMapStandardType(receiverType!!.type!!) val standardType = LLVMMapStandardType(receiverType!!.type!!)
@@ -229,7 +230,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return result 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 type = receiver.type as LLVMReferenceType
val clazz = resolveClassOrObjectLocation(type) val clazz = resolveClassOrObjectLocation(type)
val field = clazz.fieldsIndex[selectorName] val field = clazz.fieldsIndex[selectorName]
@@ -240,7 +241,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return result return result
} }
val names = parseArgList(call as KtCallExpression, scopeDepth) val names = parseArgList(call!! as KtCallExpression, scopeDepth)
val typePath = type.location.joinToString(".") val typePath = type.location.joinToString(".")
val types = if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else "" 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" 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) = addPrimitiveBinaryOperation(operator, referenceName, left, right)
private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable { private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable {
@@ -1,7 +1,9 @@
package org.kotlinnative.translator package org.kotlinnative.translator
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import jdk.nashorn.internal.ir.Block
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -28,6 +30,7 @@ abstract class StructCodegen(open val state: TranslationState,
val enumFields = HashMap<String, LLVMVariable>() val enumFields = HashMap<String, LLVMVariable>()
val constructorFields = ArrayList<LLVMVariable>() val constructorFields = ArrayList<LLVMVariable>()
val initializedFields = HashMap<LLVMVariable, KtExpression>()
abstract val type: LLVMReferenceType abstract val type: LLVMReferenceType
abstract var size: Int abstract var size: Int
@@ -64,11 +67,15 @@ abstract class StructCodegen(open val state: TranslationState,
for (declaration in declarations) { for (declaration in declarations) {
when (declaration) { when (declaration) {
is KtProperty -> { 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) val field = resolveType(declaration, ktType)
field.offset = offset field.offset = offset
offset++ offset++
if ((declaration.initializer != null) && !(this is ObjectCodegen)){
initializedFields.put(field, declaration.initializer!!)
}
fields.add(field) fields.add(field)
fieldsIndex[field.label] = field fieldsIndex[field.label] = field
size += field.type.size size += field.type.size
@@ -133,7 +140,6 @@ abstract class StructCodegen(open val state: TranslationState,
} }
private fun generateLoadArguments(thisField: LLVMVariable) { private fun generateLoadArguments(thisField: LLVMVariable) {
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0) val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
codeBuilder.loadArgument(thisVariable, false) 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() { 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
}