[FIR] Handle expect declarations in JVM backend

1. Do not generate bytecode for expect declarations

2. Serialize @OptionalExpectation annotations into .kotlin_module file

^KT-62931: Fixed
This commit is contained in:
vladislav.grechko
2024-02-08 18:01:11 +01:00
committed by Space Team
parent b74501ee93
commit d753a22fc6
24 changed files with 352 additions and 113 deletions
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.backend.jvm.ir.getKtFile
import org.jetbrains.kotlin.backend.jvm.serialization.DisabledIdSignatureDescriptor
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
import org.jetbrains.kotlin.codegen.CodegenFactory
import org.jetbrains.kotlin.codegen.addCompiledPartsAndSort
import org.jetbrains.kotlin.codegen.loadCompiledModule
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
@@ -43,6 +45,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.library.metadata.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.library.metadata.KlibModuleOrigin
import org.jetbrains.kotlin.metadata.jvm.JvmModuleProtoBuf
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
@@ -53,6 +56,7 @@ import org.jetbrains.kotlin.psi2ir.generators.fragments.EvaluatorFragmentInfo
import org.jetbrains.kotlin.psi2ir.generators.fragments.FragmentContext
import org.jetbrains.kotlin.psi2ir.preprocessing.SourceDeclarationsPreprocessor
import org.jetbrains.kotlin.resolve.CleanableBindingContext
import org.jetbrains.kotlin.serialization.StringTableImpl
import org.jetbrains.kotlin.utils.IDEAPlatforms
import org.jetbrains.kotlin.utils.IDEAPluginsCompatibilityAPI
@@ -370,6 +374,50 @@ open class JvmIrCodegenFactory(
// TODO: split classes into groups connected by inline calls; call this after every group
// and clear `JvmBackendContext.classCodegens`
state.afterIndependentPart()
generateModuleMetadata(input)
}
private fun generateModuleMetadata(result: CodegenFactory.CodegenInput) {
val backendContext = (result as JvmIrCodegenInput).context
val builder = JvmModuleProtoBuf.Module.newBuilder()
val stringTable = StringTableImpl()
backendContext.state.loadCompiledModule()?.moduleData?.run {
// In incremental compilation scenario, we might already have some serialized optionalAnnotations from the previous run
// In this case, we first initialize string table with the serialized one
// See jps/jps-plugin/testData/incremental/multiModule/multiplatform/custom/modifyOptionalAnnotationUsage for example
val nameResolver = nameResolver
repeat(nameResolver.strings.stringCount) { stringIndex ->
stringTable.addString(nameResolver.strings.getString(stringIndex))
}
repeat(nameResolver.qualifiedNames.qualifiedNameCount) { nameIndex ->
val qualifiedName = nameResolver.qualifiedNames.getQualifiedName(nameIndex)
stringTable.addQualifiedName(qualifiedName)
}
// Then add the annotations themselves, unless they are in dirty sources, i.e. contained in backendContext.optionalAnnotations
for (proto in optionalAnnotations) {
val name = nameResolver.getQualifiedClassName(proto.fqName)
if (backendContext.optionalAnnotations.none { metadata -> metadata.name?.asString() == name }) {
builder.addOptionalAnnotationClass(proto)
}
}
}
for (part in backendContext.state.factory.packagePartRegistry.parts.values.addCompiledPartsAndSort(backendContext.state)) {
part.addTo(builder)
}
for (metadata in backendContext.optionalAnnotations) {
val serializer = backendContext.backendExtension.createModuleMetadataSerializer(backendContext)
builder.addOptionalAnnotationClass(serializer.serializeOptionalAnnotationClass(metadata, stringTable))
}
val (stringTableProto, qualifiedNameTableProto) = stringTable.buildProto()
builder.setStringTable(stringTableProto)
builder.setQualifiedNameTable(qualifiedNameTableProto)
backendContext.state.factory.setModuleMapping(builder.build())
}
fun generateModuleInFrontendIRMode(