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

View File

@@ -24010,6 +24010,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
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
@TestMetadata("multifileClassPartsInitialization.kt")
public void testMultifileClassPartsInitialization() throws Exception {

View File

@@ -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.buildAssertionsDisabledField
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.writeKotlinMetadata
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -194,9 +198,6 @@ class ClassCodegen private constructor(
)
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 metadata = irClass.metadata
val entry = irClass.fileParent.fileEntry
@@ -208,6 +209,14 @@ class ClassCodegen private constructor(
entry is MultifileFacadeFileEntry -> KotlinClassHeader.Kind.MULTIFILE_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) {
if (metadata != null) {
metadataSerializer.serialize(metadata)?.let { (proto, stringTable) ->
@@ -229,9 +238,7 @@ class ClassCodegen private constructor(
}
if (irClass in context.classNameOverride) {
val isFileClass = kind == KotlinClassHeader.Kind.MULTIFILE_CLASS ||
kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART ||
kind == KotlinClassHeader.Kind.FILE_FACADE
val isFileClass = isMultifileClassOrPart || kind == KotlinClassHeader.Kind.FILE_FACADE
assert(isFileClass) { "JvmPackageName is not supported for classes: ${irClass.render()}" }
it.visit(JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME, irClass.fqNameWhenAvailable!!.parent().asString())
}

View File

@@ -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"
}

View File

@@ -24010,6 +24010,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
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
@TestMetadata("multifileClassPartsInitialization.kt")
public void testMultifileClassPartsInitialization() throws Exception {

View File

@@ -24010,6 +24010,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
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
@TestMetadata("multifileClassPartsInitialization.kt")
public void testMultifileClassPartsInitialization() throws Exception {

View File

@@ -20367,6 +20367,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
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")
public void testMultifileClassPartsInitialization() throws Exception {
runTest("compiler/testData/codegen/box/multifileClasses/multifileClassPartsInitialization.kt");