From dd913ef4508122d0bcb9dd9cfca8cd560b574e1d Mon Sep 17 00:00:00 2001 From: pyos Date: Tue, 15 Sep 2020 15:40:22 +0200 Subject: [PATCH] JVM_IR: move common metadata serialization code to ClassCodegen --- .../compiler/KotlinToJVMBytecodeCompiler.kt | 6 +- .../fir/backend/jvm/FirJvmClassCodegen.kt | 194 ------------------ .../fir/backend/jvm/FirMetadataSerializer.kt | 110 ++++++++++ .../kotlin/backend/jvm/JvmBackendContext.kt | 9 +- .../kotlin/backend/jvm/JvmBackendFacade.kt | 9 +- .../kotlin/backend/jvm/JvmIrCodegenFactory.kt | 7 +- .../backend/jvm/codegen/ClassCodegen.kt | 101 +++++++-- .../codegen/DescriptorBasedClassCodegen.kt | 144 ------------- .../codegen/DescriptorMetadataSerializer.kt | 75 +++++++ .../kotlin/codegen/GenerationUtils.kt | 6 +- 10 files changed, 287 insertions(+), 374 deletions(-) delete mode 100644 compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmClassCodegen.kt create mode 100644 compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt delete mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorBasedClassCodegen.kt create mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorMetadataSerializer.kt diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index 3b810d96d07..7aa13ea259c 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -57,7 +57,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade import org.jetbrains.kotlin.fir.analysis.diagnostics.* import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver -import org.jetbrains.kotlin.fir.backend.jvm.FirJvmClassCodegen +import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.session.FirSessionFactory @@ -399,8 +399,8 @@ object KotlinToJVMBytecodeCompiler { generationState.beforeCompile() codegenFactory.generateModuleInFrontendIRMode( generationState, moduleFragment, symbolTable, sourceManager - ) { irClass, context, parentFunction -> - FirJvmClassCodegen(irClass, context, parentFunction, session) + ) { context, irClass, type, serializationBindings, parent -> + FirMetadataSerializer(session, context, irClass, type, serializationBindings, parent) } CodegenFactory.doCheckCancelled(generationState) generationState.factory.done() diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmClassCodegen.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmClassCodegen.kt deleted file mode 100644 index 9b7ffc04330..00000000000 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmClassCodegen.kt +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.fir.backend.jvm - -import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen -import org.jetbrains.kotlin.backend.jvm.codegen.fileParent -import org.jetbrains.kotlin.backend.jvm.codegen.mapClass -import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry -import org.jetbrains.kotlin.codegen.AsmUtil -import org.jetbrains.kotlin.codegen.MultifileClassCodegenImpl -import org.jetbrains.kotlin.codegen.binding.CodegenBinding -import org.jetbrains.kotlin.codegen.writeKotlinMetadata -import org.jetbrains.kotlin.codegen.writeSyntheticClassMetadata -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.backend.FirMetadataSource -import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction -import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin -import org.jetbrains.kotlin.fir.declarations.FirFunction -import org.jetbrains.kotlin.fir.declarations.FirTypeParameter -import org.jetbrains.kotlin.fir.declarations.builder.* -import org.jetbrains.kotlin.fir.typeContext -import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType -import org.jetbrains.kotlin.fir.serialization.FirElementSerializer -import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol -import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI -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.* -import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.load.java.JvmAnnotationNames -import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader -import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable -import org.jetbrains.kotlin.types.AbstractTypeApproximator -import org.jetbrains.kotlin.types.TypeApproximatorConfiguration -import org.jetbrains.org.objectweb.asm.Type -import org.jetbrains.org.objectweb.asm.commons.Method - -class FirJvmClassCodegen( - irClass: IrClass, - context: JvmBackendContext, - parentFunction: IrFunction?, - session: FirSession, -) : ClassCodegen(irClass, context, parentFunction) { - private val serializerExtension = FirJvmSerializerExtension(session, visitor.serializationBindings, state, irClass, typeMapper) - private val serializer: FirElementSerializer? = - when (val metadata = irClass.metadata) { - is FirMetadataSource.Class -> FirElementSerializer.create( - metadata.fir, serializerExtension, (parentClassCodegen as? FirJvmClassCodegen)?.serializer - ) - is FirMetadataSource.File -> FirElementSerializer.createTopLevel(session, serializerExtension) - is FirMetadataSource.Function -> FirElementSerializer.createForLambda(session, serializerExtension) - else -> null - } - - private val approximator = object : AbstractTypeApproximator(session.typeContext) {} - - private fun FirTypeRef.approximated( - toSuper: Boolean, - conf: TypeApproximatorConfiguration = TypeApproximatorConfiguration.PublicDeclaration - ): FirTypeRef { - val approximatedType = if (toSuper) - approximator.approximateToSuperType(coneType, conf) - else - approximator.approximateToSubType(coneType, conf) - return withReplacedConeType(approximatedType as? ConeKotlinType) - } - - private fun FirFunction<*>.copyToFreeAnonymousFunction(): FirAnonymousFunction { - val function = this - return buildAnonymousFunction { - session = function.session - origin = FirDeclarationOrigin.Source - symbol = FirAnonymousFunctionSymbol() - returnTypeRef = function.returnTypeRef.approximated(toSuper = true) - receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false) - isLambda = (function as? FirAnonymousFunction)?.isLambda == true - valueParameters.addAll(function.valueParameters.map { - buildValueParameterCopy(it) { - returnTypeRef = it.returnTypeRef.approximated(toSuper = false) - } - }) - typeParameters.addAll(function.typeParameters.filterIsInstance()) - } - } - - @OptIn(ObsoleteDescriptorBasedAPI::class) - override fun generateKotlinMetadataAnnotation() { - - val localDelegatedProperties = (irClass.attributeOwnerId as? IrClass)?.let(context.localDelegatedProperties::get) - if (localDelegatedProperties != null && localDelegatedProperties.isNotEmpty()) { - state.bindingTrace.record( - CodegenBinding.DELEGATED_PROPERTIES_WITH_METADATA, type, localDelegatedProperties.map { it.descriptor } - ) - } - - // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. - var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG - if (state.isIrWithStableAbi) { - extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG - } - - when (val metadata = irClass.metadata) { - is FirMetadataSource.Class -> { - val classProto = serializer!!.classProto(metadata.fir).build() - writeKotlinMetadata(visitor, state, KotlinClassHeader.Kind.CLASS, extraFlags) { - AsmUtil.writeAnnotationData(it, classProto, serializer.stringTable as JvmStringTable) - } - - assert(irClass !in context.classNameOverride) { - "JvmPackageName is not supported for classes: ${irClass.render()}" - } - } - is FirMetadataSource.File -> { - val packageFqName = irClass.getPackageFragment()!!.fqName - val packageProto = serializer!!.packagePartProto(packageFqName, metadata.fir) - - 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.fir.copyToFreeAnonymousFunction() - val functionProto = serializer!!.functionProto(fakeAnonymousFunction)?.build() - writeKotlinMetadata(visitor, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, extraFlags) { - if (functionProto != null) { - AsmUtil.writeAnnotationData(it, functionProto, serializer.stringTable as JvmStringTable) - } - } - } - else -> { - val entry = irClass.fileParent.fileEntry - if (entry is MultifileFacadeFileEntry) { - val partInternalNames = entry.partFiles.mapNotNull { partFile -> - val fileClass = partFile.declarations.singleOrNull { it.isFileClass } as IrClass? - if (fileClass != null) typeMapper.mapClass(fileClass).internalName else null - } - MultifileClassCodegenImpl.writeMetadata( - visitor, state, extraFlags, partInternalNames, type, irClass.fqNameWhenAvailable!!.parent() - ) - } else { - writeSyntheticClassMetadata(visitor, state) - } - } - } - } - - override fun bindMethodMetadata(method: IrFunction, signature: Method) { - when (val metadata = method.metadata) { - is FirMetadataSource.Property -> { - // We can't check for JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS because for interface methods - // moved to DefaultImpls, origin is changed to DEFAULT_IMPLS - // TODO: fix origin somehow, because otherwise $annotations methods in interfaces also don't have ACC_SYNTHETIC - assert(method.name.asString().endsWith(JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX)) { method.dump() } - - state.globalSerializationBindings.put( - FirJvmSerializerExtension.SYNTHETIC_METHOD_FOR_FIR_VARIABLE, metadata.fir, signature - ) - } - is FirMetadataSource.Function -> { - visitor.serializationBindings.put(FirJvmSerializerExtension.METHOD_FOR_FIR_FUNCTION, metadata.fir, signature) - } - null -> { - } - else -> { - error("Incorrect metadata source $metadata for:\n${method.dump()}") - } - } - } - - override fun bindFieldMetadata(field: IrField, fieldType: Type, fieldName: String) { - val metadata = field.metadata - if (metadata is FirMetadataSource.Property) { - state.globalSerializationBindings.put(FirJvmSerializerExtension.FIELD_FOR_PROPERTY, metadata.fir, fieldType to fieldName) - } - } -} diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt new file mode 100644 index 00000000000..eafa249feaa --- /dev/null +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.backend.jvm + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.codegen.MetadataSerializer +import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.backend.FirMetadataSource +import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirFunction +import org.jetbrains.kotlin.fir.declarations.FirTypeParameter +import org.jetbrains.kotlin.fir.declarations.builder.* +import org.jetbrains.kotlin.fir.typeContext +import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType +import org.jetbrains.kotlin.fir.serialization.FirElementSerializer +import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.MetadataSource +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable +import org.jetbrains.kotlin.protobuf.MessageLite +import org.jetbrains.kotlin.types.AbstractTypeApproximator +import org.jetbrains.kotlin.types.TypeApproximatorConfiguration +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.Method + +class FirMetadataSerializer( + private val session: FirSession, + private val context: JvmBackendContext, + private val irClass: IrClass, + private val type: Type, + private val serializationBindings: JvmSerializationBindings, + parent: MetadataSerializer? +) : MetadataSerializer { + private val approximator = object : AbstractTypeApproximator(session.typeContext) {} + + private fun FirTypeRef.approximated(toSuper: Boolean): FirTypeRef { + val approximatedType = if (toSuper) + approximator.approximateToSuperType(coneType, TypeApproximatorConfiguration.PublicDeclaration) + else + approximator.approximateToSubType(coneType, TypeApproximatorConfiguration.PublicDeclaration) + return withReplacedConeType(approximatedType as? ConeKotlinType) + } + + private fun FirFunction<*>.copyToFreeAnonymousFunction(): FirAnonymousFunction { + val function = this + return buildAnonymousFunction { + session = function.session + origin = FirDeclarationOrigin.Source + symbol = FirAnonymousFunctionSymbol() + returnTypeRef = function.returnTypeRef.approximated(toSuper = true) + receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false) + isLambda = (function as? FirAnonymousFunction)?.isLambda == true + valueParameters.addAll(function.valueParameters.map { + buildValueParameterCopy(it) { + returnTypeRef = it.returnTypeRef.approximated(toSuper = false) + } + }) + typeParameters.addAll(function.typeParameters.filterIsInstance()) + } + } + + private val serializerExtension = + FirJvmSerializerExtension(session, serializationBindings, context.state, irClass, context.typeMapper) + + private val serializer: FirElementSerializer? = + when (val metadata = irClass.metadata) { + is FirMetadataSource.Class -> FirElementSerializer.create( + metadata.fir, serializerExtension, (parent as? FirMetadataSerializer)?.serializer + ) + is FirMetadataSource.File -> FirElementSerializer.createTopLevel(metadata.session, serializerExtension) + is FirMetadataSource.Function -> FirElementSerializer.createForLambda(metadata.session, serializerExtension) + else -> null + } + + override fun serialize(metadata: MetadataSource): Pair? { + val message = when (metadata) { + is FirMetadataSource.Class -> serializer!!.classProto(metadata.fir).build() + is FirMetadataSource.File -> + serializer!!.packagePartProto(irClass.getPackageFragment()!!.fqName, metadata.fir).apply { + serializerExtension.serializeJvmPackage(this, type) + }.build() + is FirMetadataSource.Function -> + serializer!!.functionProto(metadata.fir.copyToFreeAnonymousFunction())?.build() + else -> null + } ?: return null + return message to serializer!!.stringTable as JvmStringTable + } + + override fun bindMethodMetadata(metadata: MetadataSource.Property, signature: Method) { + val fir = (metadata as FirMetadataSource.Property).fir + context.state.globalSerializationBindings.put(FirJvmSerializerExtension.SYNTHETIC_METHOD_FOR_FIR_VARIABLE, fir, signature) + } + + override fun bindMethodMetadata(metadata: MetadataSource.Function, signature: Method) { + val fir = (metadata as FirMetadataSource.Function).fir + serializationBindings.put(FirJvmSerializerExtension.METHOD_FOR_FIR_FUNCTION, fir, signature) + } + + override fun bindFieldMetadata(metadata: MetadataSource.Property, signature: Pair) { + val fir = (metadata as FirMetadataSource.Property).fir + context.state.globalSerializationBindings.put(FirJvmSerializerExtension.FIELD_FOR_PROPERTY, fir, signature) + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 2544cbc7317..646b4ee03c4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -11,9 +11,7 @@ import org.jetbrains.kotlin.backend.common.Mapping import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig -import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen -import org.jetbrains.kotlin.backend.jvm.codegen.IrTypeMapper -import org.jetbrains.kotlin.backend.jvm.codegen.MethodSignatureMapper +import org.jetbrains.kotlin.backend.jvm.codegen.* import org.jetbrains.kotlin.backend.jvm.codegen.createFakeContinuation import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods @@ -22,6 +20,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.CollectionStubComputer import org.jetbrains.kotlin.backend.jvm.lower.JvmInnerClassesSupport import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements +import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor @@ -43,6 +42,8 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.org.objectweb.asm.Type +typealias MetadataSerializerFactory = (JvmBackendContext, IrClass, Type, JvmSerializationBindings, MetadataSerializer?) -> MetadataSerializer + class JvmBackendContext( val state: GenerationState, val psiSourceManager: PsiSourceManager, @@ -53,7 +54,7 @@ class JvmBackendContext( // If the JVM fqname of a class differs from what is implied by its parent, e.g. if it's a file class // annotated with @JvmPackageName, the correct name is recorded here. val classNameOverride: MutableMap, - internal val createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen?, + val serializerFactory: MetadataSerializerFactory ) : CommonBackendContext { override val transformedFunction: MutableMap get() = TODO("not implemented") diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt index 2d45895a014..cdfe4a59fd4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen +import org.jetbrains.kotlin.backend.jvm.codegen.DescriptorMetadataSerializer import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.codegen.state.GenerationState @@ -23,7 +24,6 @@ import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrLinker import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmManglerDesc import org.jetbrains.kotlin.ir.builders.TranslationPluginContext import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns @@ -110,7 +110,8 @@ object JvmBackendFacade { irModuleFragment.files.addAll(dependencies.flatMap { it.files }) doGenerateFilesInternal( - state, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, irProviders, extensions + state, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, + irProviders, extensions, ::DescriptorMetadataSerializer ) } @@ -122,11 +123,11 @@ object JvmBackendFacade { phaseConfig: PhaseConfig, irProviders: List, extensions: JvmGeneratorExtensions, - createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen? = { _, _, _ -> null }, + serializerFactory: MetadataSerializerFactory, ) { val context = JvmBackendContext( state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment, - symbolTable, phaseConfig, extensions.classNameOverride, createCodegen + symbolTable, phaseConfig, extensions.classNameOverride, serializerFactory ) /* JvmBackendContext creates new unbound symbols, have to resolve them. */ ExternalDependenciesGenerator(symbolTable, irProviders, state.languageVersionSettings).generateUnboundSymbolsAsDependencies() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index 8c62f44467b..5e536293cca 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -17,15 +17,12 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig -import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen import org.jetbrains.kotlin.codegen.CodegenFactory import org.jetbrains.kotlin.codegen.MultifileClassCodegen import org.jetbrains.kotlin.codegen.PackageCodegen import org.jetbrains.kotlin.codegen.PackageCodegenImpl import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.descriptors.IrFunctionFactory import org.jetbrains.kotlin.ir.util.SymbolTable @@ -45,7 +42,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory irModuleFragment: IrModuleFragment, symbolTable: SymbolTable, sourceManager: PsiSourceManager, - createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen?, + serializerFactory: MetadataSerializerFactory, ) { irModuleFragment.irBuiltins.functionFactory = IrFunctionFactory(irModuleFragment.irBuiltins, symbolTable) val extensions = JvmGeneratorExtensions() @@ -54,7 +51,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory ) JvmBackendFacade.doGenerateFilesInternal( - state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, createCodegen + state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, serializerFactory ) } 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 644e0253d37..e38b44da6c9 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 @@ -11,7 +11,7 @@ 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.builtins.StandardNames -import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings @@ -30,8 +30,13 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.IrSimpleType 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 +import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.protobuf.MessageLite import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.TRANSIENT_ANNOTATION_FQ_NAME @@ -46,16 +51,23 @@ import org.jetbrains.org.objectweb.asm.commons.Method import org.jetbrains.org.objectweb.asm.tree.MethodNode import java.io.File -abstract class ClassCodegen protected constructor( +interface MetadataSerializer { + fun serialize(metadata: MetadataSource): Pair? + fun bindMethodMetadata(metadata: MetadataSource.Property, signature: Method) + fun bindMethodMetadata(metadata: MetadataSource.Function, signature: Method) + fun bindFieldMetadata(metadata: MetadataSource.Property, signature: Pair) +} + +class ClassCodegen private constructor( val irClass: IrClass, val context: JvmBackendContext, private val parentFunction: IrFunction?, ) : InnerClassConsumer { - protected val parentClassCodegen = (parentFunction?.parentAsClass ?: irClass.parent as? IrClass)?.let { getOrCreate(it, context) } + private val parentClassCodegen = (parentFunction?.parentAsClass ?: irClass.parent as? IrClass)?.let { getOrCreate(it, context) } private val withinInline: Boolean = parentClassCodegen?.withinInline == true || parentFunction?.isInline == true - protected val state get() = context.state - protected val typeMapper get() = context.typeMapper + private val state get() = context.state + private val typeMapper get() = context.typeMapper val type: Type = typeMapper.mapClass(irClass) @@ -84,7 +96,7 @@ abstract class ClassCodegen protected constructor( } } - protected val visitor = state.factory.newVisitor(classOrigin, type, irClass.fileParent.loadSourceFilesInfo()).apply { + private val visitor = state.factory.newVisitor(classOrigin, type, irClass.fileParent.loadSourceFilesInfo()).apply { val signature = getSignature(irClass, type, irClass.getSuperClassInfo(typeMapper), typeMapper) // Ensure that the backend only produces class names that would be valid in the frontend for JVM. if (context.state.classBuilderMode.generateBodies && signature.hasInvalidName()) { @@ -216,7 +228,56 @@ abstract class ClassCodegen protected constructor( return null } - protected abstract fun generateKotlinMetadataAnnotation() + private val metadataSerializer: MetadataSerializer = + context.serializerFactory(context, irClass, type, visitor.serializationBindings, parentClassCodegen?.metadataSerializer) + + private fun generateKotlinMetadataAnnotation() { + // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. + var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG + if (state.isIrWithStableAbi) { + extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG + } + + val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId] + val metadata = irClass.metadata + val entry = irClass.fileParent.fileEntry + val kind = when { + facadeClassName != null -> KotlinClassHeader.Kind.MULTIFILE_CLASS_PART + metadata is MetadataSource.Class -> KotlinClassHeader.Kind.CLASS + metadata is MetadataSource.File -> KotlinClassHeader.Kind.FILE_FACADE + metadata is MetadataSource.Function -> KotlinClassHeader.Kind.SYNTHETIC_CLASS + entry is MultifileFacadeFileEntry -> KotlinClassHeader.Kind.MULTIFILE_CLASS + else -> KotlinClassHeader.Kind.SYNTHETIC_CLASS + } + writeKotlinMetadata(visitor, state, kind, extraFlags) { + if (metadata != null) { + metadataSerializer.serialize(metadata)?.let { (proto, stringTable) -> + AsmUtil.writeAnnotationData(it, proto, stringTable) + } + } + + if (entry is MultifileFacadeFileEntry) { + val arv = it.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME) + for (partFile in entry.partFiles) { + val fileClass = partFile.declarations.singleOrNull { it.isFileClass } as IrClass? + if (fileClass != null) arv.visit(null, typeMapper.mapClass(fileClass).internalName) + } + arv.visitEnd() + } + + if (facadeClassName != null) { + it.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassName.internalName) + } + + if (irClass in context.classNameOverride) { + val isFileClass = kind == KotlinClassHeader.Kind.MULTIFILE_CLASS || + kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART || + 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()) + } + } + } private fun IrFile.loadSourceFilesInfo(): List { val entry = fileEntry @@ -241,9 +302,7 @@ abstract class ClassCodegen protected constructor( it.origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER }, ): ClassCodegen = - context.classCodegens.getOrPut(irClass) { - context.createCodegen(irClass, context, parentFunction) ?: DescriptorBasedClassCodegen(irClass, context, parentFunction) - }.also { + context.classCodegens.getOrPut(irClass) { ClassCodegen(irClass, context, parentFunction) }.also { assert(parentFunction == null || it.parentFunction == parentFunction) { "inconsistent parent function for ${irClass.render()}:\n" + "New: ${parentFunction!!.render()}\n" + @@ -255,8 +314,6 @@ abstract class ClassCodegen protected constructor( name.splitToSequence('/').any { identifier -> identifier.any { it in JvmSimpleNameBacktickChecker.INVALID_CHARS } } } - protected abstract fun bindFieldMetadata(field: IrField, fieldType: Type, fieldName: String) - private fun generateField(field: IrField) { val fieldType = typeMapper.mapType(field) val fieldSignature = @@ -286,7 +343,9 @@ abstract class ClassCodegen protected constructor( }.genAnnotations(field, fieldType, field.type) } - bindFieldMetadata(field, fieldType, fieldName) + (field.metadata as? MetadataSource.Property)?.let { + metadataSerializer.bindFieldMetadata(it, fieldType to fieldName) + } } private val generatedInlineMethods = mutableMapOf() @@ -305,8 +364,6 @@ abstract class ClassCodegen protected constructor( return SMAPAndMethodNode(copy, smap) } - protected abstract fun bindMethodMetadata(method: IrFunction, signature: Method) - private fun generateMethod(method: IrFunction, classSMAP: SourceMapper, delegatedPropertyOptimizer: DelegatedPropertyOptimizer?) { if (method.isFakeOverride) { jvmSignatureClashDetector.trackFakeOverrideMethod(method) @@ -345,8 +402,18 @@ abstract class ClassCodegen protected constructor( } jvmSignatureClashDetector.trackMethod(method, RawSignature(node.name, node.desc, MemberKind.METHOD)) - val signature = Method(node.name, node.desc) - bindMethodMetadata(method, signature) + when (val metadata = method.metadata) { + is MetadataSource.Property -> { + // We can't check for JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS because for interface methods + // moved to DefaultImpls, origin is changed to DEFAULT_IMPLS + // TODO: fix origin somehow, because otherwise $annotations methods in interfaces also don't have ACC_SYNTHETIC + assert(method.name.asString().endsWith(JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX)) { method.dump() } + metadataSerializer.bindMethodMetadata(metadata, Method(node.name, node.desc)) + } + is MetadataSource.Function -> metadataSerializer.bindMethodMetadata(metadata, Method(node.name, node.desc)) + null -> Unit + else -> error("Incorrect metadata source $metadata for:\n${method.dump()}") + } } private fun generateInnerAndOuterClasses() { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorBasedClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorBasedClassCodegen.kt deleted file mode 100644 index 6fc9790c661..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorBasedClassCodegen.kt +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.backend.jvm.codegen - -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.codegen.serialization.JvmSerializerExtension -import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource -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.* -import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.load.java.JvmAnnotationNames -import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader -import org.jetbrains.kotlin.serialization.DescriptorSerializer -import org.jetbrains.org.objectweb.asm.Type -import org.jetbrains.org.objectweb.asm.commons.Method - -class DescriptorBasedClassCodegen internal constructor( - irClass: IrClass, - context: JvmBackendContext, - parentFunction: IrFunction?, -) : ClassCodegen(irClass, context, parentFunction) { - - private val serializerExtension = JvmSerializerExtension(visitor.serializationBindings, state, typeMapper) - private val serializer: DescriptorSerializer? = - when (val metadata = irClass.metadata) { - is DescriptorMetadataSource.Class -> DescriptorSerializer.create( - metadata.descriptor, serializerExtension, (parentClassCodegen as? DescriptorBasedClassCodegen)?.serializer - ) - is DescriptorMetadataSource.File -> DescriptorSerializer.createTopLevel(serializerExtension) - is DescriptorMetadataSource.Function -> DescriptorSerializer.createForLambda(serializerExtension) - else -> null - } - - override fun generateKotlinMetadataAnnotation() { - - val localDelegatedProperties = (irClass.attributeOwnerId as? IrClass)?.let(context.localDelegatedProperties::get) - if (localDelegatedProperties != null && localDelegatedProperties.isNotEmpty()) { - state.bindingTrace.record( - CodegenBinding.DELEGATED_PROPERTIES_WITH_METADATA, - type, - localDelegatedProperties.mapNotNull { (it.owner.metadata as? DescriptorMetadataSource.LocalDelegatedProperty)?.descriptor } - ) - } - - // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. - var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG - if (state.isIrWithStableAbi) { - extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG - } - - when (val metadata = irClass.metadata) { - is DescriptorMetadataSource.Class -> { - val classProto = serializer!!.classProto(metadata.descriptor).build() - writeKotlinMetadata(visitor, state, KotlinClassHeader.Kind.CLASS, extraFlags) { - AsmUtil.writeAnnotationData(it, serializer, classProto) - } - - assert(irClass !in context.classNameOverride) { - "JvmPackageName is not supported for classes: ${irClass.render()}" - } - } - is DescriptorMetadataSource.File -> { - val packageFqName = irClass.getPackageFragment()!!.fqName - val packageProto = serializer!!.packagePartProto(packageFqName, metadata.descriptors) - - 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, serializer, packageProto.build()) - - 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 DescriptorMetadataSource.Function -> { - val fakeDescriptor = createFreeFakeLambdaDescriptor(metadata.descriptor, state.typeApproximator) - val functionProto = serializer!!.functionProto(fakeDescriptor)?.build() - writeKotlinMetadata(visitor, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, extraFlags) { - if (functionProto != null) { - AsmUtil.writeAnnotationData(it, serializer, functionProto) - } - } - } - else -> { - val entry = irClass.fileParent.fileEntry - if (entry is MultifileFacadeFileEntry) { - val partInternalNames = entry.partFiles.mapNotNull { partFile -> - val fileClass = partFile.declarations.singleOrNull { it.isFileClass } as IrClass? - if (fileClass != null) typeMapper.mapClass(fileClass).internalName else null - } - MultifileClassCodegenImpl.writeMetadata( - visitor, state, extraFlags, partInternalNames, type, irClass.fqNameWhenAvailable!!.parent() - ) - } else { - writeSyntheticClassMetadata(visitor, state) - } - } - } - } - - override fun bindMethodMetadata(method: IrFunction, signature: Method) { - when (val metadata = method.metadata) { - is DescriptorMetadataSource.Property -> { - // We can't check for JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS because for interface methods - // moved to DefaultImpls, origin is changed to DEFAULT_IMPLS - // TODO: fix origin somehow, because otherwise $annotations methods in interfaces also don't have ACC_SYNTHETIC - assert(method.name.asString().endsWith(JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX)) { method.dump() } - - state.globalSerializationBindings.put( - JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY, metadata.descriptor, signature - ) - } - is DescriptorMetadataSource.Function -> { - visitor.serializationBindings.put(JvmSerializationBindings.METHOD_FOR_FUNCTION, metadata.descriptor, signature) - } - null -> { - } - else -> error("Incorrect metadata source $metadata for:\n${method.dump()}") - } - } - - override fun bindFieldMetadata(field: IrField, fieldType: Type, fieldName: String) { - val descriptor = (field.metadata as? DescriptorMetadataSource.Property)?.descriptor - if (descriptor != null) { - state.globalSerializationBindings.put(JvmSerializationBindings.FIELD_FOR_PROPERTY, descriptor, fieldType to fieldName) - } - } -} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorMetadataSerializer.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorMetadataSerializer.kt new file mode 100644 index 00000000000..b2bd195a4f0 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorMetadataSerializer.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.codegen + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.* +import org.jetbrains.kotlin.codegen.binding.CodegenBinding +import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings +import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable +import org.jetbrains.kotlin.protobuf.MessageLite +import org.jetbrains.kotlin.serialization.DescriptorSerializer +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.Method + +class DescriptorMetadataSerializer( + private val context: JvmBackendContext, + private val irClass: IrClass, + private val type: Type, + private val serializationBindings: JvmSerializationBindings, + parent: MetadataSerializer? +) : MetadataSerializer { + private val serializerExtension = JvmSerializerExtension(serializationBindings, context.state, context.typeMapper) + private val serializer: DescriptorSerializer? = + when (val metadata = irClass.metadata) { + is DescriptorMetadataSource.Class -> DescriptorSerializer.create( + metadata.descriptor, serializerExtension, (parent as? DescriptorMetadataSerializer)?.serializer + ) + is DescriptorMetadataSource.File -> DescriptorSerializer.createTopLevel(serializerExtension) + is DescriptorMetadataSource.Function -> DescriptorSerializer.createForLambda(serializerExtension) + else -> null + } + + override fun serialize(metadata: MetadataSource): Pair? { + val localDelegatedProperties = (irClass.attributeOwnerId as? IrClass)?.let(context.localDelegatedProperties::get) + if (localDelegatedProperties != null && localDelegatedProperties.isNotEmpty()) { + context.state.bindingTrace.record( + CodegenBinding.DELEGATED_PROPERTIES_WITH_METADATA, + type, + localDelegatedProperties.mapNotNull { (it.owner.metadata as? DescriptorMetadataSource.LocalDelegatedProperty)?.descriptor } + ) + } + val message = when (metadata) { + is DescriptorMetadataSource.Class -> serializer!!.classProto(metadata.descriptor).build() + is DescriptorMetadataSource.File -> + serializer!!.packagePartProto(irClass.getPackageFragment()!!.fqName, metadata.descriptors).apply { + serializerExtension.serializeJvmPackage(this, type) + }.build() + is DescriptorMetadataSource.Function -> + serializer!!.functionProto(createFreeFakeLambdaDescriptor(metadata.descriptor, context.state.typeApproximator))?.build() + else -> null + } ?: return null + return message to serializer!!.stringTable as JvmStringTable + } + + override fun bindMethodMetadata(metadata: MetadataSource.Property, signature: Method) { + val descriptor = (metadata as DescriptorMetadataSource.Property).descriptor + context.state.globalSerializationBindings.put(JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, signature) + } + + override fun bindMethodMetadata(metadata: MetadataSource.Function, signature: Method) { + val descriptor = (metadata as DescriptorMetadataSource.Function).descriptor + serializationBindings.put(JvmSerializationBindings.METHOD_FOR_FUNCTION, descriptor, signature) + } + + override fun bindFieldMetadata(metadata: MetadataSource.Property, signature: Pair) { + val descriptor = (metadata as DescriptorMetadataSource.Property).descriptor + context.state.globalSerializationBindings.put(JvmSerializationBindings.FIELD_FOR_PROPERTY, descriptor, signature) + } +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt index c2ec5fcd93a..c0b3056b12c 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt @@ -40,7 +40,7 @@ import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver -import org.jetbrains.kotlin.fir.backend.jvm.FirJvmClassCodegen +import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer import org.jetbrains.kotlin.fir.createSession import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries import org.jetbrains.kotlin.load.kotlin.PackagePartProvider @@ -140,8 +140,8 @@ object GenerationUtils { generationState.beforeCompile() codegenFactory.generateModuleInFrontendIRMode( generationState, moduleFragment, symbolTable, sourceManager - ) { irClass, context, irFunction -> - FirJvmClassCodegen(irClass, context, irFunction, session) + ) { context, irClass, type, serializationBindings, parent -> + FirMetadataSerializer(session, context, irClass, type, serializationBindings, parent) } generationState.factory.done()