Move FirJvmClassCodegen inside fir:fir2ir:jvm-backend #KT-38156 Fixed

This removes dependency of IR JVM backend from FIR
This commit is contained in:
Mikhail Glukhikh
2020-04-24 18:55:35 +03:00
parent dbd4cecff6
commit 34ae35b2aa
14 changed files with 59 additions and 38 deletions
-3
View File
@@ -5,9 +5,6 @@ plugins {
dependencies {
compile(project(":kotlin-annotations-jvm"))
compile(project(":compiler:fir:fir-serialization"))
compile(project(":compiler:fir:fir2ir"))
compile(project(":compiler:fir:fir2ir:jvm-backend"))
compile(project(":compiler:backend"))
compile(project(":compiler:ir.tree"))
compile(project(":compiler:ir.psi2ir"))
@@ -53,7 +53,8 @@ class JvmBackendContext(
val phaseConfig: PhaseConfig,
// 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.
internal val classNameOverride: MutableMap<IrClass, JvmClassName>
val classNameOverride: MutableMap<IrClass, JvmClassName>,
internal val createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen?,
) : CommonBackendContext {
override val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
get() = TODO("not implemented")
@@ -92,10 +93,10 @@ class JvmBackendContext(
internal val classCodegens = mutableMapOf<IrClass, ClassCodegen>()
internal val localDelegatedProperties = mutableMapOf<IrClass, List<IrLocalDelegatedPropertySymbol>>()
val localDelegatedProperties = mutableMapOf<IrClass, List<IrLocalDelegatedPropertySymbol>>()
internal val multifileFacadesToAdd = mutableMapOf<JvmClassName, MutableList<IrClass>>()
internal val multifileFacadeForPart = mutableMapOf<IrClass, JvmClassName>()
val multifileFacadeForPart = mutableMapOf<IrClass, JvmClassName>()
internal val multifileFacadeClassForPart = mutableMapOf<IrClass, IrClass>()
internal val multifileFacadeMemberToPartMember = mutableMapOf<IrFunction, IrFunction>()
@@ -15,13 +15,12 @@ import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.ir.backend.jvm.serialization.EmptyLoggingContext
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrLinker
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmManglerDesc
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.types.defaultType
import org.jetbrains.kotlin.ir.util.*
@@ -86,10 +85,12 @@ object JvmBackendFacade {
sourceManager: PsiSourceManager,
phaseConfig: PhaseConfig,
irProviders: List<IrProvider>,
extensions: JvmGeneratorExtensions
extensions: JvmGeneratorExtensions,
createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen? = { _, _, _ -> null },
) {
val context = JvmBackendContext(
state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig, extensions.classNameOverride
state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment,
symbolTable, phaseConfig, extensions.classNameOverride, createCodegen
)
/* JvmBackendContext creates new unbound symbols, have to resolve them. */
ExternalDependenciesGenerator(symbolTable, irProviders, state.languageVersionSettings).generateUnboundSymbolsAsDependencies()
@@ -17,12 +17,15 @@
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.WrappedDeclarationDescriptor
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
@@ -40,7 +43,11 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory
}
fun generateModuleInFrontendIRMode(
state: GenerationState, irModuleFragment: IrModuleFragment, symbolTable: SymbolTable, sourceManager: PsiSourceManager
state: GenerationState,
irModuleFragment: IrModuleFragment,
symbolTable: SymbolTable,
sourceManager: PsiSourceManager,
createCodegen: (IrClass, JvmBackendContext, IrFunction?) -> ClassCodegen?,
) {
val extensions = JvmGeneratorExtensions()
val irProviders = generateTypicalIrProviderList(
@@ -55,7 +62,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory
}
JvmBackendFacade.doGenerateFilesInternal(
state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions
state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, createCodegen
)
}
@@ -12,11 +12,9 @@ import org.jetbrains.kotlin.backend.jvm.lower.buildAssertionsDisabledField
import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.WrappedClassDescriptor
@@ -28,7 +26,6 @@ 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.name.Name
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
@@ -44,9 +41,9 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.io.File
abstract class ClassCodegen protected constructor(
internal val irClass: IrClass,
val irClass: IrClass,
val context: JvmBackendContext,
private val parentFunction: IrFunction? = null
private val parentFunction: IrFunction?,
) : InnerClassConsumer {
protected val parentClassCodegen = (parentFunction?.parentAsClass ?: irClass.parent as? IrClass)?.let { getOrCreate(it, context) }
private val withinInline: Boolean = parentClassCodegen?.withinInline == true || parentFunction?.isInline == true
@@ -203,13 +200,13 @@ abstract class ClassCodegen protected constructor(
}
companion object {
fun getOrCreate(irClass: IrClass, context: JvmBackendContext, parentFunction: IrFunction? = null): ClassCodegen =
fun getOrCreate(
irClass: IrClass,
context: JvmBackendContext,
parentFunction: IrFunction? = null,
): ClassCodegen =
context.classCodegens.getOrPut(irClass) {
if (irClass.metadata is FirMetadataSource) {
FirBasedClassCodegen(irClass, context, parentFunction)
} else {
DescriptorBasedClassCodegen(irClass, context, parentFunction)
}
context.createCodegen(irClass, context, parentFunction) ?: DescriptorBasedClassCodegen(irClass, context, parentFunction)
}.also {
assert(parentFunction == null || it.parentFunction == parentFunction) {
"inconsistent parent function for ${irClass.render()}:\n" +
@@ -26,7 +26,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method
class DescriptorBasedClassCodegen internal constructor(
irClass: IrClass,
context: JvmBackendContext,
parentFunction: IrFunction? = null
parentFunction: IrFunction?,
) : ClassCodegen(irClass, context, parentFunction) {
private val serializerExtension = JvmSerializerExtension(visitor.serializationBindings, state, typeMapper)
@@ -1,161 +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.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmSerializerExtension
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
import org.jetbrains.kotlin.fir.serialization.FirElementSerializer
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.util.*
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.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
class FirBasedClassCodegen internal constructor(
irClass: IrClass,
context: JvmBackendContext,
parentFunction: IrFunction? = null
) : ClassCodegen(irClass, context, parentFunction) {
private val session = (irClass.metadata as FirMetadataSource).session
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.klass, serializerExtension, (parentClassCodegen as? FirBasedClassCodegen)?.serializer
)
is FirMetadataSource.File -> FirElementSerializer.createTopLevel(session, serializerExtension)
is FirMetadataSource.Function -> FirElementSerializer.createForLambda(session, serializerExtension)
else -> null
}
private fun FirFunction<*>.copyToFreeAnonymousFunction(): FirAnonymousFunction {
val function = this
return buildAnonymousFunction {
session = function.session
symbol = FirAnonymousFunctionSymbol()
returnTypeRef = function.returnTypeRef
receiverTypeRef = function.receiverTypeRef
isLambda = false
valueParameters.addAll(function.valueParameters)
typeParameters.addAll(function.typeParameters.filterIsInstance<FirTypeParameter>())
}
}
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.klass).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.file)
serializerExtension.serializeJvmPackage(packageProto, type)
val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId]
val kind = if (facadeClassName != null) KotlinClassHeader.Kind.MULTIFILE_CLASS_PART else KotlinClassHeader.Kind.FILE_FACADE
writeKotlinMetadata(visitor, state, kind, extraFlags) { av ->
AsmUtil.writeAnnotationData(av, packageProto.build(), serializer.stringTable as JvmStringTable)
if (facadeClassName != null) {
av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassName.internalName)
}
if (irClass in context.classNameOverride) {
av.visit(JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME, irClass.fqNameWhenAvailable!!.parent().asString())
}
}
}
is FirMetadataSource.Function -> {
val fakeAnonymousFunction = metadata.function.copyToFreeAnonymousFunction()
val functionProto = serializer!!.functionProto(fakeAnonymousFunction)?.build()
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.Variable -> {
// 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.variable, signature
)
}
is FirMetadataSource.Function -> {
visitor.serializationBindings.put(FirJvmSerializerExtension.METHOD_FOR_FIR_FUNCTION, metadata.function, signature)
}
null -> {
}
else -> {
error("Incorrect metadata source $metadata for:\n${method.dump()}")
}
}
}
override fun bindFieldMetadata(field: IrField, fieldType: Type, fieldName: String) {
// TODO
}
}
@@ -68,7 +68,7 @@ fun IrFrameMap.leave(irDeclaration: IrSymbolOwner): Int {
val IrClass.isJvmInterface get() = isAnnotationClass || isInterface
internal val IrDeclaration.fileParent: IrFile
val IrDeclaration.fileParent: IrFile
get() {
val myParent = parent
return when (myParent) {
@@ -76,7 +76,7 @@ internal val generateMultifileFacadesPhase = namedIrModulePhase(
}
)
internal class MultifileFacadeFileEntry(
class MultifileFacadeFileEntry(
private val className: JvmClassName,
val partFiles: List<IrFile>
) : SourceManager.FileEntry {