From c92c50aa98766b2ac1acbb99393d9fd75e17fb08 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 8 Feb 2019 16:14:23 +0100 Subject: [PATCH] JVM IR: generate JVM signatures of companion object properties --- .../backend/jvm/codegen/ClassCodegen.kt | 35 +++++++++++++++---- .../backend/jvm/codegen/ExpressionCodegen.kt | 2 +- .../properties/jvmField/interfaceCompanion.kt | 1 - 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 06379292ebd..893eefb78f0 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.getPackageFragment 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.name.SpecialNames import org.jetbrains.kotlin.psi.KtElement @@ -106,8 +107,22 @@ open class ClassCodegen protected constructor( val shortName = File(fileEntry.name).name visitor.visitSource(shortName, null) - irClass.declarations.forEach { - generateDeclaration(it) + val nestedClasses = irClass.declarations.mapNotNull { declaration -> + 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() @@ -174,10 +189,10 @@ open class ClassCodegen protected constructor( } } - fun generateDeclaration(declaration: IrDeclaration) { + private fun generateDeclaration(declaration: IrDeclaration, companionObjectCodegen: ClassCodegen?) { when (declaration) { is IrField -> - generateField(declaration) + generateField(declaration, companionObjectCodegen) is IrFunction -> { generateMethod(declaration) } @@ -188,14 +203,17 @@ open class ClassCodegen protected constructor( // skip } is IrClass -> { - ClassCodegen(declaration, context, this).generate() + // Nested classes are generated separately } 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 val fieldType = typeMapper.mapType(field.descriptor) @@ -212,7 +230,10 @@ open class ClassCodegen protected constructor( val descriptor = field.metadata?.descriptor 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) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 5411455d8af..46e32d09501 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -557,7 +557,7 @@ class ExpressionCodegen( } override fun visitClass(declaration: IrClass, data: BlockInfo): StackValue { - classCodegen.generateDeclaration(declaration) + classCodegen.generateLocalClass(declaration) return none() } diff --git a/compiler/testData/codegen/box/reflection/properties/jvmField/interfaceCompanion.kt b/compiler/testData/codegen/box/reflection/properties/jvmField/interfaceCompanion.kt index 8159e5ca883..1e99f213aab 100644 --- a/compiler/testData/codegen/box/reflection/properties/jvmField/interfaceCompanion.kt +++ b/compiler/testData/codegen/box/reflection/properties/jvmField/interfaceCompanion.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +JvmFieldInInterface // TARGET_BACKEND: JVM -// IGNORE_BACKEND: JVM_IR // WITH_REFLECT import kotlin.reflect.KProperty1