JVM_IR: write serialized IR to an annotation

This commit is contained in:
Georgy Bronnikov
2021-03-01 12:54:16 +03:00
committed by TeamCityServer
parent b177779b66
commit baaecaa052
2 changed files with 23 additions and 5 deletions
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.protobuf.MessageLite import org.jetbrains.kotlin.protobuf.MessageLite
@@ -241,6 +242,11 @@ 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 serializedIr = when (metadata) {
is MetadataSource.Class -> metadata.serializedIr
is MetadataSource.File -> metadata.serializedIr
else -> null
}
val isMultifileClassOrPart = kind == KotlinClassHeader.Kind.MULTIFILE_CLASS || kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART val isMultifileClassOrPart = kind == KotlinClassHeader.Kind.MULTIFILE_CLASS || kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART
@@ -252,15 +258,15 @@ class ClassCodegen private constructor(
extraFlags = extraFlags or JvmAnnotationNames.METADATA_SCRIPT_FLAG extraFlags = extraFlags or JvmAnnotationNames.METADATA_SCRIPT_FLAG
} }
writeKotlinMetadata(visitor, state, kind, extraFlags) { writeKotlinMetadata(visitor, state, kind, extraFlags) { av ->
if (metadata != null) { if (metadata != null) {
metadataSerializer.serialize(metadata)?.let { (proto, stringTable) -> metadataSerializer.serialize(metadata)?.let { (proto, stringTable) ->
DescriptorAsmUtil.writeAnnotationData(it, proto, stringTable) DescriptorAsmUtil.writeAnnotationData(av, proto, stringTable)
} }
} }
if (entry is MultifileFacadeFileEntry) { if (entry is MultifileFacadeFileEntry) {
val arv = it.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME) val arv = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME)
for (partFile in entry.partFiles) { for (partFile in entry.partFiles) {
val fileClass = partFile.declarations.singleOrNull { it.isFileClass } as IrClass? val fileClass = partFile.declarations.singleOrNull { it.isFileClass } as IrClass?
if (fileClass != null) arv.visit(null, typeMapper.mapClass(fileClass).internalName) if (fileClass != null) arv.visit(null, typeMapper.mapClass(fileClass).internalName)
@@ -269,14 +275,16 @@ class ClassCodegen private constructor(
} }
if (facadeClassName != null) { if (facadeClassName != null) {
it.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassName.internalName) av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassName.internalName)
} }
if (irClass in context.classNameOverride) { if (irClass in context.classNameOverride) {
val isFileClass = isMultifileClassOrPart || kind == KotlinClassHeader.Kind.FILE_FACADE val isFileClass = isMultifileClassOrPart || 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()) av.visit(JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME, irClass.fqNameWhenAvailable!!.parent().asString())
} }
serializedIr?.let { storeSerializedIr(av, it) }
} }
} }
@@ -562,3 +570,12 @@ private val Modality.flags: Int
private val DescriptorVisibility.flags: Int private val DescriptorVisibility.flags: Int
get() = DescriptorAsmUtil.getVisibilityAccessFlag(this) ?: throw AssertionError("Unsupported visibility $this") get() = DescriptorAsmUtil.getVisibilityAccessFlag(this) ?: throw AssertionError("Unsupported visibility $this")
private fun storeSerializedIr(av: AnnotationVisitor, serializedIr: ByteArray) {
val serializedIrParts = BitEncoding.encodeBytes(serializedIr)
val partsVisitor = av.visitArray(JvmAnnotationNames.METADATA_SERIALIZED_IR_FIELD_NAME)
for (part in serializedIrParts) {
partsVisitor.visit(null, part)
}
partsVisitor.visitEnd()
}
@@ -37,6 +37,7 @@ public final class JvmAnnotationNames {
public static final String METADATA_PACKAGE_NAME_FIELD_NAME = "pn"; public static final String METADATA_PACKAGE_NAME_FIELD_NAME = "pn";
public static final String METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME = METADATA_EXTRA_STRING_FIELD_NAME; public static final String METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME = METADATA_EXTRA_STRING_FIELD_NAME;
public static final String METADATA_EXTRA_INT_FIELD_NAME = "xi"; public static final String METADATA_EXTRA_INT_FIELD_NAME = "xi";
public static final String METADATA_SERIALIZED_IR_FIELD_NAME = "si";
public static final int METADATA_MULTIFILE_PARTS_INHERIT_FLAG = 1 << 0; public static final int METADATA_MULTIFILE_PARTS_INHERIT_FLAG = 1 << 0;
public static final int METADATA_PRE_RELEASE_FLAG = 1 << 1; public static final int METADATA_PRE_RELEASE_FLAG = 1 << 1;