JVM IR: generate JVM signatures of companion object properties
This commit is contained in:
+28
-7
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
||||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
@@ -106,8 +107,22 @@ open class ClassCodegen protected constructor(
|
|||||||
val shortName = File(fileEntry.name).name
|
val shortName = File(fileEntry.name).name
|
||||||
visitor.visitSource(shortName, null)
|
visitor.visitSource(shortName, null)
|
||||||
|
|
||||||
irClass.declarations.forEach {
|
val nestedClasses = irClass.declarations.mapNotNull { declaration ->
|
||||||
generateDeclaration(it)
|
if (declaration is IrClass) {
|
||||||
|
ClassCodegen(declaration, context, this)
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
|
||||||
|
val companionObjectCodegen = nestedClasses.firstOrNull { it.irClass.isCompanion }
|
||||||
|
|
||||||
|
for (declaration in irClass.declarations) {
|
||||||
|
generateDeclaration(declaration, companionObjectCodegen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate nested classes at the end, to ensure that codegen for companion object will have the necessary JVM signatures in its
|
||||||
|
// trace for properties moved to the outer class
|
||||||
|
for (codegen in nestedClasses) {
|
||||||
|
codegen.generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
generateKotlinMetadataAnnotation()
|
generateKotlinMetadataAnnotation()
|
||||||
@@ -174,10 +189,10 @@ open class ClassCodegen protected constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateDeclaration(declaration: IrDeclaration) {
|
private fun generateDeclaration(declaration: IrDeclaration, companionObjectCodegen: ClassCodegen?) {
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
is IrField ->
|
is IrField ->
|
||||||
generateField(declaration)
|
generateField(declaration, companionObjectCodegen)
|
||||||
is IrFunction -> {
|
is IrFunction -> {
|
||||||
generateMethod(declaration)
|
generateMethod(declaration)
|
||||||
}
|
}
|
||||||
@@ -188,14 +203,17 @@ open class ClassCodegen protected constructor(
|
|||||||
// skip
|
// skip
|
||||||
}
|
}
|
||||||
is IrClass -> {
|
is IrClass -> {
|
||||||
ClassCodegen(declaration, context, this).generate()
|
// Nested classes are generated separately
|
||||||
}
|
}
|
||||||
else -> throw RuntimeException("Unsupported declaration $declaration")
|
else -> throw RuntimeException("Unsupported declaration $declaration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun generateLocalClass(klass: IrClass) {
|
||||||
|
ClassCodegen(klass, context, this).generate()
|
||||||
|
}
|
||||||
|
|
||||||
private fun generateField(field: IrField) {
|
private fun generateField(field: IrField, companionObjectCodegen: ClassCodegen?) {
|
||||||
if (field.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return
|
if (field.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return
|
||||||
|
|
||||||
val fieldType = typeMapper.mapType(field.descriptor)
|
val fieldType = typeMapper.mapType(field.descriptor)
|
||||||
@@ -212,7 +230,10 @@ open class ClassCodegen protected constructor(
|
|||||||
|
|
||||||
val descriptor = field.metadata?.descriptor
|
val descriptor = field.metadata?.descriptor
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
visitor.serializationBindings.put(JvmSerializationBindings.FIELD_FOR_PROPERTY, descriptor, fieldType to fieldName)
|
val codegen = if (JvmAbi.isPropertyWithBackingFieldInOuterClass(descriptor)) {
|
||||||
|
companionObjectCodegen ?: error("Class with a property moved from the companion must have a companion:\n${irClass.dump()}")
|
||||||
|
} else this
|
||||||
|
codegen.visitor.serializationBindings.put(JvmSerializationBindings.FIELD_FOR_PROPERTY, descriptor, fieldType to fieldName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -557,7 +557,7 @@ class ExpressionCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass, data: BlockInfo): StackValue {
|
override fun visitClass(declaration: IrClass, data: BlockInfo): StackValue {
|
||||||
classCodegen.generateDeclaration(declaration)
|
classCodegen.generateLocalClass(declaration)
|
||||||
return none()
|
return none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +JvmFieldInInterface
|
// !LANGUAGE: +JvmFieldInInterface
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
|
|||||||
Reference in New Issue
Block a user