JVM IR: write inherited multifile parts flag to kotlin.Metadata

This flag is unused at the moment, but might be used one day to support
proper incremental compilation for multifile classes.
This commit is contained in:
Alexander Udalov
2021-02-15 18:34:50 +01:00
parent 35008df969
commit adb05ab076
6 changed files with 87 additions and 7 deletions
@@ -24010,6 +24010,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/multifileClasses/kt16077.kt"); runTest("compiler/testData/codegen/box/multifileClasses/kt16077.kt");
} }
@Test
@TestMetadata("metadataFlag.kt")
public void testMetadataFlag() throws Exception {
runTest("compiler/testData/codegen/box/multifileClasses/metadataFlag.kt");
}
@Test @Test
@TestMetadata("multifileClassPartsInitialization.kt") @TestMetadata("multifileClassPartsInitialization.kt")
public void testMultifileClassPartsInitialization() throws Exception { public void testMultifileClassPartsInitialization() throws Exception {
@@ -10,8 +10,12 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
import org.jetbrains.kotlin.backend.jvm.lower.buildAssertionsDisabledField import org.jetbrains.kotlin.backend.jvm.lower.buildAssertionsDisabledField
import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.DescriptorAsmUtil
import org.jetbrains.kotlin.codegen.VersionIndependentOpcodes
import org.jetbrains.kotlin.codegen.addRecordComponent
import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.writeKotlinMetadata
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -194,9 +198,6 @@ class ClassCodegen private constructor(
) )
private fun generateKotlinMetadataAnnotation() { private fun generateKotlinMetadataAnnotation() {
// TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt].
val extraFlags = context.backendExtension.generateMetadataExtraFlags(state.abiStability)
val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId] val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId]
val metadata = irClass.metadata val metadata = irClass.metadata
val entry = irClass.fileParent.fileEntry val entry = irClass.fileParent.fileEntry
@@ -208,6 +209,14 @@ class ClassCodegen private constructor(
entry is MultifileFacadeFileEntry -> KotlinClassHeader.Kind.MULTIFILE_CLASS entry is MultifileFacadeFileEntry -> KotlinClassHeader.Kind.MULTIFILE_CLASS
else -> KotlinClassHeader.Kind.SYNTHETIC_CLASS else -> KotlinClassHeader.Kind.SYNTHETIC_CLASS
} }
val isMultifileClassOrPart = kind == KotlinClassHeader.Kind.MULTIFILE_CLASS || kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART
var extraFlags = context.backendExtension.generateMetadataExtraFlags(state.abiStability)
if (isMultifileClassOrPart && state.languageVersionSettings.getFlag(JvmAnalysisFlags.inheritMultifileParts)) {
extraFlags = extraFlags or JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG
}
writeKotlinMetadata(visitor, state, kind, extraFlags) { writeKotlinMetadata(visitor, state, kind, extraFlags) {
if (metadata != null) { if (metadata != null) {
metadataSerializer.serialize(metadata)?.let { (proto, stringTable) -> metadataSerializer.serialize(metadata)?.let { (proto, stringTable) ->
@@ -229,9 +238,7 @@ class ClassCodegen private constructor(
} }
if (irClass in context.classNameOverride) { if (irClass in context.classNameOverride) {
val isFileClass = kind == KotlinClassHeader.Kind.MULTIFILE_CLASS || val isFileClass = isMultifileClassOrPart || kind == KotlinClassHeader.Kind.FILE_FACADE
kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART ||
kind == KotlinClassHeader.Kind.FILE_FACADE
assert(isFileClass) { "JvmPackageName is not supported for classes: ${irClass.render()}" } assert(isFileClass) { "JvmPackageName is not supported for classes: ${irClass.render()}" }
it.visit(JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME, irClass.fqNameWhenAvailable!!.parent().asString()) it.visit(JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME, irClass.fqNameWhenAvailable!!.parent().asString())
} }
@@ -0,0 +1,50 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FIR reports unresolved reference on `extraInt`.
// IGNORE_BACKEND_FIR: JVM_IR
// MODULE: optimized
// !INHERIT_MULTIFILE_PARTS
// FILE: optimized.kt
@file:JvmMultifileClass
@file:JvmName("Optimized")
package optimized
fun test() {}
class RandomClass
// MODULE: main(optimized)
// FILE: default.kt
@file:JvmMultifileClass
@file:JvmName("Default")
package default
fun test() {}
// FILE: box.kt
fun isFlagSet(className: String): Boolean {
val extraInt = Class.forName(className).getAnnotation(Metadata::class.java).extraInt
return (extraInt and (1 shl 0)) != 0
}
fun box(): String {
if (isFlagSet("default.Default"))
return "Fail: inherited multifile parts flag should NOT be set by default for the facade"
if (isFlagSet("default.Default__DefaultKt"))
return "Fail: inherited multifile parts flag should NOT be set by default for the part"
if (!isFlagSet("optimized.Optimized"))
return "Fail: inherited multifile parts flag SHOULD be set by default for the facade"
if (!isFlagSet("optimized.Optimized__OptimizedKt"))
return "Fail: inherited multifile parts flag SHOULD be set by default for the part"
if (isFlagSet("optimized.RandomClass"))
return "Fail: inherited multifile parts flag should NOT be set by default for some random class if -Xmultifile-part-inherit is enabled"
return "OK"
}
@@ -24010,6 +24010,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/multifileClasses/kt16077.kt"); runTest("compiler/testData/codegen/box/multifileClasses/kt16077.kt");
} }
@Test
@TestMetadata("metadataFlag.kt")
public void testMetadataFlag() throws Exception {
runTest("compiler/testData/codegen/box/multifileClasses/metadataFlag.kt");
}
@Test @Test
@TestMetadata("multifileClassPartsInitialization.kt") @TestMetadata("multifileClassPartsInitialization.kt")
public void testMultifileClassPartsInitialization() throws Exception { public void testMultifileClassPartsInitialization() throws Exception {
@@ -24010,6 +24010,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/multifileClasses/kt16077.kt"); runTest("compiler/testData/codegen/box/multifileClasses/kt16077.kt");
} }
@Test
@TestMetadata("metadataFlag.kt")
public void testMetadataFlag() throws Exception {
runTest("compiler/testData/codegen/box/multifileClasses/metadataFlag.kt");
}
@Test @Test
@TestMetadata("multifileClassPartsInitialization.kt") @TestMetadata("multifileClassPartsInitialization.kt")
public void testMultifileClassPartsInitialization() throws Exception { public void testMultifileClassPartsInitialization() throws Exception {
@@ -20367,6 +20367,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/multifileClasses/kt16077.kt"); runTest("compiler/testData/codegen/box/multifileClasses/kt16077.kt");
} }
@TestMetadata("metadataFlag.kt")
public void testMetadataFlag() throws Exception {
runTest("compiler/testData/codegen/box/multifileClasses/metadataFlag.kt");
}
@TestMetadata("multifileClassPartsInitialization.kt") @TestMetadata("multifileClassPartsInitialization.kt")
public void testMultifileClassPartsInitialization() throws Exception { public void testMultifileClassPartsInitialization() throws Exception {
runTest("compiler/testData/codegen/box/multifileClasses/multifileClassPartsInitialization.kt"); runTest("compiler/testData/codegen/box/multifileClasses/multifileClassPartsInitialization.kt");