JVM_IR: partially implement FIR local delegated property reflection

Type parameter references are broken, just like for lambdas. Also, the
code is super ugly.
This commit is contained in:
pyos
2020-09-15 17:55:21 +02:00
committed by Mikhail Glukhikh
parent 6f622920e7
commit aa58ed9234
11 changed files with 74 additions and 43 deletions
@@ -399,8 +399,8 @@ object KotlinToJVMBytecodeCompiler {
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager
) { context, irClass, type, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, type, serializationBindings, parent)
) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, parent)
}
CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done()
@@ -5,17 +5,13 @@
package org.jetbrains.kotlin.fir.backend.jvm
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.serialization.FirElementAwareStringTable
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
class FirJvmElementAwareStringTable(
private val typeMapper: KotlinTypeMapperBase,
nameResolver: JvmNameResolver? = null
) : JvmStringTable(nameResolver), FirElementAwareStringTable {
override fun getLocalClassIdReplacement(classLikeDeclaration: FirClassLikeDeclaration<*>): ClassId {
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.backend.jvm
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
@@ -22,7 +21,6 @@ import org.jetbrains.kotlin.fir.serialization.FirElementSerializer
import org.jetbrains.kotlin.fir.serialization.FirSerializerExtension
import org.jetbrains.kotlin.fir.serialization.nonSourceAnnotations
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil
import org.jetbrains.kotlin.load.kotlin.NON_EXISTENT_CLASS_NAME
@@ -40,15 +38,15 @@ import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
class FirJvmSerializerExtension @JvmOverloads constructor(
class FirJvmSerializerExtension(
override val session: FirSession,
private val bindings: JvmSerializationBindings,
state: GenerationState,
private val irClass: IrClass,
private val typeMapper: KotlinTypeMapperBase = state.typeMapper
private val localDelegatedProperties: List<FirProperty>
) : FirSerializerExtension() {
private val globalBindings = state.globalSerializationBindings
override val stringTable = FirJvmElementAwareStringTable(typeMapper)
override val stringTable = FirJvmElementAwareStringTable()
private val useTypeTable = state.useTypeTableInSerializer
private val moduleName = state.moduleName
private val classBuilderMode = state.classBuilderMode
@@ -75,7 +73,6 @@ class FirJvmSerializerExtension @JvmOverloads constructor(
return classBuilderMode != ClassBuilderMode.ABI || nestedClass.visibility != Visibilities.Private
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
override fun serializeClass(
klass: FirClass<*>,
proto: ProtoBuf.Class.Builder,
@@ -86,11 +83,7 @@ class FirJvmSerializerExtension @JvmOverloads constructor(
if (moduleName != JvmProtoBufUtil.DEFAULT_MODULE_NAME) {
proto.setExtension(JvmProtoBuf.classModuleName, stringTable.getStringIndex(moduleName))
}
//TODO: support local delegated properties in new defaults scheme
val containerAsmType =
if (klass is FirRegularClass && klass.classKind == ClassKind.INTERFACE) typeMapper.mapDefaultImpls(irClass.descriptor)
else typeMapper.mapClass(irClass.descriptor)
writeLocalProperties(proto, containerAsmType, JvmProtoBuf.classLocalVariable)
writeLocalProperties(proto, JvmProtoBuf.classLocalVariable)
writeVersionRequirementForJvmDefaultIfNeeded(klass, proto, versionRequirementTable)
if (jvmDefaultMode.forAllMethodsWithBody && klass is FirRegularClass && klass.classKind == ClassKind.INTERFACE) {
@@ -148,24 +141,19 @@ class FirJvmSerializerExtension @JvmOverloads constructor(
}
}
fun serializeJvmPackage(proto: ProtoBuf.Package.Builder, partAsmType: Type) {
writeLocalProperties(proto, partAsmType, JvmProtoBuf.packageLocalVariable)
fun serializeJvmPackage(proto: ProtoBuf.Package.Builder) {
writeLocalProperties(proto, JvmProtoBuf.packageLocalVariable)
}
@Suppress("UNUSED_PARAMETER")
private fun <MessageType : GeneratedMessageLite.ExtendableMessage<MessageType>, BuilderType : GeneratedMessageLite.ExtendableBuilder<MessageType, BuilderType>> writeLocalProperties(
proto: BuilderType,
classAsmType: Type,
extension: GeneratedMessageLite.GeneratedExtension<MessageType, List<ProtoBuf.Property>>
) {
// TODO
// val localVariables = CodegenBinding.getLocalDelegatedProperties(codegenBinding, classAsmType) ?: return
//
// for (localVariable in localVariables) {
// val propertyDescriptor = createFreeFakeLocalPropertyDescriptor(localVariable)
// val serializer = FirElementSerializer.createForLambda(this)
// proto.addExtension(extension, serializer.propertyProto(propertyDescriptor)?.build() ?: continue)
// }
for (localVariable in localDelegatedProperties) {
val serializer = FirElementSerializer.createForLambda(session, this)
proto.addExtension(extension, serializer.propertyProto(localVariable)?.build() ?: continue)
}
}
override fun serializeFlexibleType(
@@ -10,15 +10,15 @@ 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.*
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.serialization.FirElementSerializer
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.MetadataSource
@@ -35,7 +35,6 @@ 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 {
@@ -67,12 +66,64 @@ class FirMetadataSerializer(
returnTypeRef = it.returnTypeRef.approximated(toSuper = false)
}
})
typeParameters.addAll(function.typeParameters.filterIsInstance<FirTypeParameter>())
// TODO need containers' type parameters too
function.typeParameters.filterIsInstanceTo(typeParameters)
}
}
private fun FirPropertyAccessor.copyToFreeAccessor(): FirPropertyAccessor {
val accessor = this
return buildPropertyAccessor {
session = accessor.session
origin = FirDeclarationOrigin.Source
returnTypeRef = accessor.returnTypeRef.approximated(toSuper = true)
symbol = FirPropertyAccessorSymbol()
isGetter = accessor.isGetter
status = accessor.status
accessor.valueParameters.mapTo(valueParameters) {
buildValueParameterCopy(it) {
returnTypeRef = it.returnTypeRef.approximated(toSuper = false)
}
}
annotations += accessor.annotations
// TODO need containers' type parameters too
typeParameters += accessor.typeParameters
}
}
private fun FirProperty.copyToFreeProperty(): FirProperty {
val property = this
return buildProperty {
session = property.session
origin = FirDeclarationOrigin.Source
symbol = FirPropertySymbol(property.symbol.callableId)
returnTypeRef = property.returnTypeRef.approximated(toSuper = true)
receiverTypeRef = property.receiverTypeRef?.approximated(toSuper = false)
name = property.name
initializer = property.initializer
delegate = property.delegate
delegateFieldSymbol = property.delegateFieldSymbol?.let {
FirDelegateFieldSymbol(it.callableId)
}
getter = property.getter?.copyToFreeAccessor()
setter = property.setter?.copyToFreeAccessor()
isVar = property.isVar
isLocal = property.isLocal
status = property.status
annotations += property.annotations
// TODO need containers' type parameters too
typeParameters += property.typeParameters
}.apply {
delegateFieldSymbol?.fir = this
}
}
private val localDelegatedProperties = context.localDelegatedProperties[irClass.attributeOwnerId]?.map {
(it.owner.metadata as FirMetadataSource.Property).fir.copyToFreeProperty()
} ?: emptyList()
private val serializerExtension =
FirJvmSerializerExtension(session, serializationBindings, context.state, irClass, context.typeMapper)
FirJvmSerializerExtension(session, serializationBindings, context.state, irClass, localDelegatedProperties)
private val serializer: FirElementSerializer? =
when (val metadata = irClass.metadata) {
@@ -89,7 +140,7 @@ class FirMetadataSerializer(
is FirMetadataSource.Class -> serializer!!.classProto(metadata.fir).build()
is FirMetadataSource.File ->
serializer!!.packagePartProto(irClass.getPackageFragment()!!.fqName, metadata.fir).apply {
serializerExtension.serializeJvmPackage(this, type)
serializerExtension.serializeJvmPackage(this)
}.build()
is FirMetadataSource.Function ->
serializer!!.functionProto(metadata.fir.copyToFreeAnonymousFunction())?.build()
@@ -895,6 +895,7 @@ class Fir2IrDeclarationStorage(
}
}.apply {
parent = irParent
metadata = FirMetadataSource.Property(property)
enterScope(this)
delegate = declareIrVariable(
startOffset, endOffset, IrDeclarationOrigin.PROPERTY_DELEGATE,
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
// FILE: 1.kt
@@ -140,8 +140,8 @@ object GenerationUtils {
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager
) { context, irClass, type, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, type, serializationBindings, parent)
) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, parent)
}
generationState.factory.done()