translator: object and class fields

This commit is contained in:
e5l
2016-07-19 18:07:16 +03:00
parent e9a7d75e0e
commit a1ee214c90
6 changed files with 70 additions and 39 deletions
@@ -138,7 +138,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
if (state.classes.containsKey(function)) { if (state.classes.containsKey(function)) {
val descriptor = state.classes[function] ?: return null val descriptor = state.classes[function] ?: return null
val args = loadArgsIfRequired(names, descriptor.fields) val args = loadArgsIfRequired(names, descriptor.constructorFields)
return evaluateConstructorCallExpression(LLVMVariable(function, descriptor.type, scope = LLVMVariableScope()), args) return evaluateConstructorCallExpression(LLVMVariable(function, descriptor.type, scope = LLVMVariableScope()), args)
} }
@@ -17,7 +17,7 @@ class ClassCodegen(override val state: TranslationState, override val variableMa
val annotation: Boolean val annotation: Boolean
override val size: Int override var size: Int = 0
override val structName: String override val structName: String
override val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true) override val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
@@ -27,52 +27,42 @@ class ClassCodegen(override val state: TranslationState, override val variableMa
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf() val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
size = indexFields(descriptor, parameterList) indexFields(descriptor, parameterList)
generateInnerFields(clazz.declarations)
} }
private fun indexFields(descriptor: ClassDescriptor, parameters: MutableList<KtParameter>): Int { private fun indexFields(descriptor: ClassDescriptor, parameters: MutableList<KtParameter>) {
if (annotation) { if (annotation) {
return 0 return
} }
var offset = 0
var currentSize = 0
for (field in parameters) { for (field in parameters) {
val item = resolveType(field) val item = resolveType(field, state.bindingContext.get(BindingContext.TYPE, field.typeReference)!!)
item.offset = offset item.offset = fields.size
constructorFields.add(item)
fields.add(item) fields.add(item)
fieldsIndex[item.label] = item fieldsIndex[item.label] = item
size += type.size
currentSize += type.size
offset++
} }
when (descriptor.kind) { when (descriptor.kind) {
ClassKind.ENUM_CLASS -> { ClassKind.ENUM_CLASS -> {
val item = LLVMClassVariable("enum_item", LLVMEnumItemType()) val item = LLVMClassVariable("enum_item", LLVMEnumItemType())
item.offset = offset item.offset = fields.size
fields.add(item) fields.add(item)
fieldsIndex["enum_item"] = item fieldsIndex["enum_item"] = item
currentSize += type.size size += type.size
offset++
} }
} }
return currentSize
} }
fun generate() { fun generate() {
if (annotation) { if (annotation) {
return return
} }
generate(clazz.declarations) generate(clazz.declarations)
} }
private fun generateStruct() {
val name = clazz.name!!
codeBuilder.createClass(name, fields)
}
} }
@@ -12,12 +12,13 @@ import org.kotlinnative.translator.llvm.types.LLVMType
class ObjectCodegen(override val state: TranslationState, override val variableManager: VariableManager, val objectDeclaration: KtObjectDeclaration, override val codeBuilder: LLVMBuilder) : class ObjectCodegen(override val state: TranslationState, override val variableManager: VariableManager, val objectDeclaration: KtObjectDeclaration, override val codeBuilder: LLVMBuilder) :
StructCodegen(state, variableManager, objectDeclaration, state.bindingContext.get(BindingContext.CLASS, objectDeclaration) ?: throw TranslationException(), StructCodegen(state, variableManager, objectDeclaration, state.bindingContext.get(BindingContext.CLASS, objectDeclaration) ?: throw TranslationException(),
codeBuilder) { codeBuilder) {
override val size: Int = 0 override var size: Int = 0
override val structName: String override val structName: String
override val type: LLVMType = LLVMReferenceType(objectDeclaration.name.toString(), "class", byRef = true) override val type: LLVMType = LLVMReferenceType(objectDeclaration.name.toString(), "class", byRef = true)
init { init {
structName = objectDeclaration.name!! structName = objectDeclaration.name!!
generateInnerFields(objectDeclaration.declarations)
} }
fun generate() { fun generate() {
@@ -2,11 +2,9 @@ package org.kotlinnative.translator
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.KotlinType
import org.kotlinnative.translator.llvm.* import org.kotlinnative.translator.llvm.*
import org.kotlinnative.translator.llvm.types.LLVMCharType import org.kotlinnative.translator.llvm.types.LLVMCharType
import org.kotlinnative.translator.llvm.types.LLVMReferenceType import org.kotlinnative.translator.llvm.types.LLVMReferenceType
@@ -18,20 +16,21 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
val classDescriptor: ClassDescriptor, val classDescriptor: ClassDescriptor,
open val codeBuilder: LLVMBuilder) { open val codeBuilder: LLVMBuilder) {
val plain: Boolean = false // TODO
val fields = ArrayList<LLVMVariable>() val fields = ArrayList<LLVMVariable>()
val fieldsIndex = HashMap<String, LLVMClassVariable>() val fieldsIndex = HashMap<String, LLVMClassVariable>()
val constructorFields = ArrayList<LLVMVariable>()
abstract val type: LLVMType abstract val type: LLVMType
abstract val size: Int abstract var size: Int
var methods = HashMap<String, FunctionCodegen>() var methods = HashMap<String, FunctionCodegen>()
abstract val structName: String abstract val structName: String
fun generate(declarationList: List<KtDeclaration>) { fun generate(declarations: List<KtDeclaration>) {
generateStruct() generateStruct()
generatePrimaryConstructor() generatePrimaryConstructor()
for (declaration in declarationList) { for (declaration in declarations) {
when (declaration) { when (declaration) {
is KtNamedFunction -> { is KtNamedFunction -> {
val function = FunctionCodegen(state, variableManager, declaration, codeBuilder) val function = FunctionCodegen(state, variableManager, declaration, codeBuilder)
@@ -46,6 +45,25 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
} }
} }
fun generateInnerFields(declarations: List<KtDeclaration>) {
var offset = fields.size
for (declaration in declarations) {
when (declaration) {
is KtProperty -> {
val ktType = state.bindingContext.get(BindingContext.TYPE, declaration.typeReference)!!
val field = resolveType(declaration, ktType)
field.offset = offset
offset++
fields.add(field)
fieldsIndex[field.label] = field
size += field.type.size
}
}
}
}
private fun generateStruct() { private fun generateStruct() {
val name = classDescriptor.name.identifier val name = classDescriptor.name.identifier
@@ -62,7 +80,7 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
variableManager.addVariable("this", classVal, 0) variableManager.addVariable("this", classVal, 0)
argFields.add(classVal) argFields.add(classVal)
argFields.addAll(fields) argFields.addAll(constructorFields)
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(classDescriptor.name.identifier, argFields, LLVMVoidType(), arm = state.arm)) codeBuilder.addLLVMCode(LLVMFunctionDescriptor(classDescriptor.name.identifier, argFields, LLVMVoidType(), arm = state.arm))
@@ -80,7 +98,7 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
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)
fields.forEach { constructorFields.forEach {
if (it.type !is LLVMReferenceType) { if (it.type !is LLVMReferenceType) {
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope()) val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
codeBuilder.loadArgument(loadVariable) codeBuilder.loadArgument(loadVariable)
@@ -89,7 +107,7 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
} }
private fun generateAssignments() { private fun generateAssignments() {
fields.forEach { constructorFields.forEach {
when (it.type) { when (it.type) {
is LLVMReferenceType -> { is LLVMReferenceType -> {
val classField = codeBuilder.getNewVariable(it.type, pointer = it.pointer + 1) val classField = codeBuilder.getNewVariable(it.type, pointer = it.pointer + 1)
@@ -118,10 +136,9 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
codeBuilder.memcpy(castedDst, castedSrc, size) codeBuilder.memcpy(castedDst, castedSrc, size)
} }
protected fun resolveType(field: KtParameter): LLVMClassVariable { protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType): LLVMClassVariable {
val annotations = parseFieldAnnotations(field) val annotations = parseFieldAnnotations(field)
val ktType = state.bindingContext.get(BindingContext.TYPE, field.typeReference)!!
val result = LLVMMapStandardType(field.name!!, ktType, LLVMRegisterScope()) val result = LLVMMapStandardType(field.name!!, ktType, LLVMRegisterScope())
if (result.type is LLVMReferenceType) { if (result.type is LLVMReferenceType) {
@@ -137,7 +154,7 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
return LLVMClassVariable(result.label, result.type, result.pointer) return LLVMClassVariable(result.label, result.type, result.pointer)
} }
private fun parseFieldAnnotations(field: KtParameter): Set<String> { private fun parseFieldAnnotations(field: KtNamedDeclaration): Set<String> {
val result = HashSet<String>() val result = HashSet<String>()
for (annotation in field.annotationEntries) { for (annotation in field.annotationEntries) {
@@ -0,0 +1,2 @@
test_simple_field() == 0
test_field_assignment(10) == 10
@@ -0,0 +1,21 @@
class WithFields(var i: Int) {
var j: Int
init {
this.j = 0
}
}
fun test_simple_field(): Int {
val i = WithFields(1)
return i.j
}
fun test_field_assignment(i: Int): Int {
val k = WithFields(1)
k.j = i
return k.j
}