JVM_IR: move common metadata serialization code to ClassCodegen
This commit is contained in:
+3
-3
@@ -57,7 +57,7 @@ import org.jetbrains.kotlin.fir.FirSession
|
|||||||
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
|
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
|
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.checkers.registerExtendedCommonCheckers
|
||||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||||
import org.jetbrains.kotlin.fir.session.FirSessionFactory
|
import org.jetbrains.kotlin.fir.session.FirSessionFactory
|
||||||
@@ -399,8 +399,8 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
generationState.beforeCompile()
|
generationState.beforeCompile()
|
||||||
codegenFactory.generateModuleInFrontendIRMode(
|
codegenFactory.generateModuleInFrontendIRMode(
|
||||||
generationState, moduleFragment, symbolTable, sourceManager
|
generationState, moduleFragment, symbolTable, sourceManager
|
||||||
) { irClass, context, parentFunction ->
|
) { context, irClass, type, serializationBindings, parent ->
|
||||||
FirJvmClassCodegen(irClass, context, parentFunction, session)
|
FirMetadataSerializer(session, context, irClass, type, serializationBindings, parent)
|
||||||
}
|
}
|
||||||
CodegenFactory.doCheckCancelled(generationState)
|
CodegenFactory.doCheckCancelled(generationState)
|
||||||
generationState.factory.done()
|
generationState.factory.done()
|
||||||
|
|||||||
-194
@@ -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<FirTypeParameter>())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+110
@@ -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<FirTypeParameter>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<MessageLite, JvmStringTable>? {
|
||||||
|
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<Type, String>) {
|
||||||
|
val fir = (metadata as FirMetadataSource.Property).fir
|
||||||
|
context.state.globalSerializationBindings.put(FirJvmSerializerExtension.FIELD_FOR_PROPERTY, fir, signature)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.ir.Ir
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen
|
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.IrTypeMapper
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.MethodSignatureMapper
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.createFakeContinuation
|
import org.jetbrains.kotlin.backend.jvm.codegen.createFakeContinuation
|
||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
|
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
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.JvmInnerClassesSupport
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements
|
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.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
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.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
|
typealias MetadataSerializerFactory = (JvmBackendContext, IrClass, Type, JvmSerializationBindings, MetadataSerializer?) -> MetadataSerializer
|
||||||
|
|
||||||
class JvmBackendContext(
|
class JvmBackendContext(
|
||||||
val state: GenerationState,
|
val state: GenerationState,
|
||||||
val psiSourceManager: PsiSourceManager,
|
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
|
// 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.
|
// annotated with @JvmPackageName, the correct name is recorded here.
|
||||||
val classNameOverride: MutableMap<IrClass, JvmClassName>,
|
val classNameOverride: MutableMap<IrClass, JvmClassName>,
|
||||||
internal val createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen?,
|
val serializerFactory: MetadataSerializerFactory
|
||||||
) : CommonBackendContext {
|
) : CommonBackendContext {
|
||||||
override val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
|
override val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
|
||||||
get() = TODO("not implemented")
|
get() = TODO("not implemented")
|
||||||
|
|||||||
@@ -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.ir.BuiltinSymbolsBase
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen
|
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.lower.MultifileFacadeFileEntry
|
||||||
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
|
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
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.backend.jvm.serialization.JvmManglerDesc
|
||||||
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
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.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
@@ -110,7 +110,8 @@ object JvmBackendFacade {
|
|||||||
irModuleFragment.files.addAll(dependencies.flatMap { it.files })
|
irModuleFragment.files.addAll(dependencies.flatMap { it.files })
|
||||||
|
|
||||||
doGenerateFilesInternal(
|
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,
|
phaseConfig: PhaseConfig,
|
||||||
irProviders: List<IrProvider>,
|
irProviders: List<IrProvider>,
|
||||||
extensions: JvmGeneratorExtensions,
|
extensions: JvmGeneratorExtensions,
|
||||||
createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen? = { _, _, _ -> null },
|
serializerFactory: MetadataSerializerFactory,
|
||||||
) {
|
) {
|
||||||
val context = JvmBackendContext(
|
val context = JvmBackendContext(
|
||||||
state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment,
|
state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment,
|
||||||
symbolTable, phaseConfig, extensions.classNameOverride, createCodegen
|
symbolTable, phaseConfig, extensions.classNameOverride, serializerFactory
|
||||||
)
|
)
|
||||||
/* JvmBackendContext creates new unbound symbols, have to resolve them. */
|
/* JvmBackendContext creates new unbound symbols, have to resolve them. */
|
||||||
ExternalDependenciesGenerator(symbolTable, irProviders, state.languageVersionSettings).generateUnboundSymbolsAsDependencies()
|
ExternalDependenciesGenerator(symbolTable, irProviders, state.languageVersionSettings).generateUnboundSymbolsAsDependencies()
|
||||||
|
|||||||
@@ -17,15 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm
|
package org.jetbrains.kotlin.backend.jvm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
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.CodegenFactory
|
||||||
import org.jetbrains.kotlin.codegen.MultifileClassCodegen
|
import org.jetbrains.kotlin.codegen.MultifileClassCodegen
|
||||||
import org.jetbrains.kotlin.codegen.PackageCodegen
|
import org.jetbrains.kotlin.codegen.PackageCodegen
|
||||||
import org.jetbrains.kotlin.codegen.PackageCodegenImpl
|
import org.jetbrains.kotlin.codegen.PackageCodegenImpl
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
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.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrFunctionFactory
|
import org.jetbrains.kotlin.ir.descriptors.IrFunctionFactory
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
@@ -45,7 +42,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory
|
|||||||
irModuleFragment: IrModuleFragment,
|
irModuleFragment: IrModuleFragment,
|
||||||
symbolTable: SymbolTable,
|
symbolTable: SymbolTable,
|
||||||
sourceManager: PsiSourceManager,
|
sourceManager: PsiSourceManager,
|
||||||
createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen?,
|
serializerFactory: MetadataSerializerFactory,
|
||||||
) {
|
) {
|
||||||
irModuleFragment.irBuiltins.functionFactory = IrFunctionFactory(irModuleFragment.irBuiltins, symbolTable)
|
irModuleFragment.irBuiltins.functionFactory = IrFunctionFactory(irModuleFragment.irBuiltins, symbolTable)
|
||||||
val extensions = JvmGeneratorExtensions()
|
val extensions = JvmGeneratorExtensions()
|
||||||
@@ -54,7 +51,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory
|
|||||||
)
|
)
|
||||||
|
|
||||||
JvmBackendFacade.doGenerateFilesInternal(
|
JvmBackendFacade.doGenerateFilesInternal(
|
||||||
state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, createCodegen
|
state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, serializerFactory
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+84
-17
@@ -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.buildAssertionsDisabledField
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField
|
import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
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.codegen.inline.*
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
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.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
|
||||||
import org.jetbrains.kotlin.resolve.jvm.annotations.TRANSIENT_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 org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class ClassCodegen protected constructor(
|
interface MetadataSerializer {
|
||||||
|
fun serialize(metadata: MetadataSource): Pair<MessageLite, JvmStringTable>?
|
||||||
|
fun bindMethodMetadata(metadata: MetadataSource.Property, signature: Method)
|
||||||
|
fun bindMethodMetadata(metadata: MetadataSource.Function, signature: Method)
|
||||||
|
fun bindFieldMetadata(metadata: MetadataSource.Property, signature: Pair<Type, String>)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassCodegen private constructor(
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
val context: JvmBackendContext,
|
val context: JvmBackendContext,
|
||||||
private val parentFunction: IrFunction?,
|
private val parentFunction: IrFunction?,
|
||||||
) : InnerClassConsumer {
|
) : 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
|
private val withinInline: Boolean = parentClassCodegen?.withinInline == true || parentFunction?.isInline == true
|
||||||
|
|
||||||
protected val state get() = context.state
|
private val state get() = context.state
|
||||||
protected val typeMapper get() = context.typeMapper
|
private val typeMapper get() = context.typeMapper
|
||||||
|
|
||||||
val type: Type = typeMapper.mapClass(irClass)
|
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)
|
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.
|
// Ensure that the backend only produces class names that would be valid in the frontend for JVM.
|
||||||
if (context.state.classBuilderMode.generateBodies && signature.hasInvalidName()) {
|
if (context.state.classBuilderMode.generateBodies && signature.hasInvalidName()) {
|
||||||
@@ -216,7 +228,56 @@ abstract class ClassCodegen protected constructor(
|
|||||||
return null
|
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<File> {
|
private fun IrFile.loadSourceFilesInfo(): List<File> {
|
||||||
val entry = fileEntry
|
val entry = fileEntry
|
||||||
@@ -241,9 +302,7 @@ abstract class ClassCodegen protected constructor(
|
|||||||
it.origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER
|
it.origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER
|
||||||
},
|
},
|
||||||
): ClassCodegen =
|
): ClassCodegen =
|
||||||
context.classCodegens.getOrPut(irClass) {
|
context.classCodegens.getOrPut(irClass) { ClassCodegen(irClass, context, parentFunction) }.also {
|
||||||
context.createCodegen(irClass, context, parentFunction) ?: DescriptorBasedClassCodegen(irClass, context, parentFunction)
|
|
||||||
}.also {
|
|
||||||
assert(parentFunction == null || it.parentFunction == parentFunction) {
|
assert(parentFunction == null || it.parentFunction == parentFunction) {
|
||||||
"inconsistent parent function for ${irClass.render()}:\n" +
|
"inconsistent parent function for ${irClass.render()}:\n" +
|
||||||
"New: ${parentFunction!!.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 } }
|
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) {
|
private fun generateField(field: IrField) {
|
||||||
val fieldType = typeMapper.mapType(field)
|
val fieldType = typeMapper.mapType(field)
|
||||||
val fieldSignature =
|
val fieldSignature =
|
||||||
@@ -286,7 +343,9 @@ abstract class ClassCodegen protected constructor(
|
|||||||
}.genAnnotations(field, fieldType, field.type)
|
}.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<IrFunction, SMAPAndMethodNode>()
|
private val generatedInlineMethods = mutableMapOf<IrFunction, SMAPAndMethodNode>()
|
||||||
@@ -305,8 +364,6 @@ abstract class ClassCodegen protected constructor(
|
|||||||
return SMAPAndMethodNode(copy, smap)
|
return SMAPAndMethodNode(copy, smap)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun bindMethodMetadata(method: IrFunction, signature: Method)
|
|
||||||
|
|
||||||
private fun generateMethod(method: IrFunction, classSMAP: SourceMapper, delegatedPropertyOptimizer: DelegatedPropertyOptimizer?) {
|
private fun generateMethod(method: IrFunction, classSMAP: SourceMapper, delegatedPropertyOptimizer: DelegatedPropertyOptimizer?) {
|
||||||
if (method.isFakeOverride) {
|
if (method.isFakeOverride) {
|
||||||
jvmSignatureClashDetector.trackFakeOverrideMethod(method)
|
jvmSignatureClashDetector.trackFakeOverrideMethod(method)
|
||||||
@@ -345,8 +402,18 @@ abstract class ClassCodegen protected constructor(
|
|||||||
}
|
}
|
||||||
jvmSignatureClashDetector.trackMethod(method, RawSignature(node.name, node.desc, MemberKind.METHOD))
|
jvmSignatureClashDetector.trackMethod(method, RawSignature(node.name, node.desc, MemberKind.METHOD))
|
||||||
|
|
||||||
val signature = Method(node.name, node.desc)
|
when (val metadata = method.metadata) {
|
||||||
bindMethodMetadata(method, signature)
|
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() {
|
private fun generateInnerAndOuterClasses() {
|
||||||
|
|||||||
-144
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+75
@@ -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<MessageLite, JvmStringTable>? {
|
||||||
|
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<Type, String>) {
|
||||||
|
val descriptor = (metadata as DescriptorMetadataSource.Property).descriptor
|
||||||
|
context.state.globalSerializationBindings.put(JvmSerializationBindings.FIELD_FOR_PROPERTY, descriptor, signature)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.container.get
|
|||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
|
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
|
||||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
|
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.fir.createSession
|
||||||
import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries
|
import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||||
@@ -140,8 +140,8 @@ object GenerationUtils {
|
|||||||
generationState.beforeCompile()
|
generationState.beforeCompile()
|
||||||
codegenFactory.generateModuleInFrontendIRMode(
|
codegenFactory.generateModuleInFrontendIRMode(
|
||||||
generationState, moduleFragment, symbolTable, sourceManager
|
generationState, moduleFragment, symbolTable, sourceManager
|
||||||
) { irClass, context, irFunction ->
|
) { context, irClass, type, serializationBindings, parent ->
|
||||||
FirJvmClassCodegen(irClass, context, irFunction, session)
|
FirMetadataSerializer(session, context, irClass, type, serializationBindings, parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
generationState.factory.done()
|
generationState.factory.done()
|
||||||
|
|||||||
Reference in New Issue
Block a user