translator: object and class fields
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user