[FIR] Support FirMetadataSource.File in FIR2IR & serializer (KT-38156)

This commit is contained in:
Mikhail Glukhikh
2020-04-16 15:35:58 +03:00
parent 95a17eadb2
commit f98c73cb30
21 changed files with 57 additions and 22 deletions
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.metadata.serialization.Interner
import org.jetbrains.kotlin.metadata.serialization.MutableTypeTable
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.RequireKotlinConstants
import org.jetbrains.kotlin.resolve.constants.ConstantValue
@@ -57,6 +58,31 @@ class FirElementSerializer private constructor(
) {
private val contractSerializer = FirContractSerializer()
fun packagePartProto(packageFqName: FqName, file: FirFile): ProtoBuf.Package.Builder {
val builder = ProtoBuf.Package.newBuilder()
for (declaration in file.declarations) {
when (declaration) {
is FirProperty -> propertyProto(declaration)?.let { builder.addProperty(it) }
is FirSimpleFunction -> functionProto(declaration)?.let { builder.addFunction(it) }
}
}
val typeTableProto = typeTable.serialize()
if (typeTableProto != null) {
builder.typeTable = typeTableProto
}
val versionRequirementTableProto = versionRequirementTable?.serialize()
if (versionRequirementTableProto != null) {
builder.versionRequirementTable = versionRequirementTableProto
}
extension.serializePackage(packageFqName, builder)
return builder
}
fun classProto(irClass: IrClass): ProtoBuf.Class.Builder {
val klass = (irClass.metadata as FirMetadataSource.Class).klass
val builder = ProtoBuf.Class.newBuilder()
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.ir.builders.constFalse
import org.jetbrains.kotlin.ir.builders.constTrue
import org.jetbrains.kotlin.ir.builders.elseBranch
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.IrType
@@ -81,6 +82,8 @@ class Fir2IrVisitor(
annotations = file.annotations.mapNotNull {
it.accept(this@Fir2IrVisitor, data) as? IrConstructorCall
}
(this as IrFileImpl).metadata = FirMetadataSource.File(file, components.session, declarations.map { it.descriptor })
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.fir.FirSession
@@ -16,6 +17,10 @@ interface FirMetadataSource : MetadataSource {
val session: FirSession
class File(
val file: FirFile, override val session: FirSession, descriptors: List<DeclarationDescriptor>
) : MetadataSource.File(descriptors), FirMetadataSource
class Class(
val klass: FirClass<*>, descriptor: WrappedClassDescriptor
) : MetadataSource.Class(descriptor), FirMetadataSource {
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmSerializerExtension
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
@@ -21,10 +20,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.isFileClass
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
@@ -46,6 +42,7 @@ class FirBasedClassCodegen internal constructor(
is FirMetadataSource.Class -> FirElementSerializer.create(
metadata.klass, serializerExtension, (parentClassCodegen as? FirBasedClassCodegen)?.serializer
)
is FirMetadataSource.File -> FirElementSerializer.createTopLevel(session, serializerExtension)
is FirMetadataSource.Function -> FirElementSerializer.createForLambda(session, serializerExtension)
else -> null
}
@@ -89,6 +86,26 @@ class FirBasedClassCodegen internal constructor(
"JvmPackageName is not supported for classes: ${irClass.render()}"
}
}
is FirMetadataSource.File -> {
val packageFqName = irClass.getPackageFragment()!!.fqName
val packageProto = serializer!!.packagePartProto(packageFqName, metadata.file)
serializerExtension.serializeJvmPackage(packageProto, type)
val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId]
val kind = if (facadeClassName != null) KotlinClassHeader.Kind.MULTIFILE_CLASS_PART else KotlinClassHeader.Kind.FILE_FACADE
writeKotlinMetadata(visitor, state, kind, extraFlags) { av ->
AsmUtil.writeAnnotationData(av, packageProto.build(), serializer.stringTable as JvmStringTable)
if (facadeClassName != null) {
av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassName.internalName)
}
if (irClass in context.classNameOverride) {
av.visit(JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME, irClass.fqNameWhenAvailable!!.parent().asString())
}
}
}
is FirMetadataSource.Function -> {
val fakeAnonymousFunction = metadata.function.copyToFreeAnonymousFunction()
val functionProto = serializer!!.functionProto(fakeAnonymousFunction)?.build()
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
interface MetadataSource {
open class Class(val descriptor: ClassDescriptor) : MetadataSource
class File(val descriptors: List<DeclarationDescriptor>) : MetadataSource
open class File(val descriptors: List<DeclarationDescriptor>) : MetadataSource
open class Function(val descriptor: FunctionDescriptor) : MetadataSource
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_REFLECT
// KJS_WITH_FULL_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,5 +1,4 @@
// !LANGUAGE: +MultiPlatformProjects
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS
// IGNORE_BACKEND: JS_IR
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// MODULE: lib
// FILE: f1.kt