[klib] Deduplicate KLIB serialization logic in K/JS and K/N

Introduce the new `serializeModuleIntoKlib` function that all KLIB-based
backends can use to serialize a module to a KLIB.

^KT-64392 Fixed
This commit is contained in:
Sergej Jaskiewicz
2024-01-19 19:19:08 +01:00
committed by Space Team
parent c335cd0b1e
commit 93a1ceae75
8 changed files with 348 additions and 310 deletions
@@ -8,20 +8,20 @@ package org.jetbrains.kotlin.klib
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import junit.framework.TestCase
import org.jetbrains.kotlin.ir.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.backend.common.CommonKLibResolver
import org.jetbrains.kotlin.ir.util.isExpect
import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataIncrementalSerializer
import org.jetbrains.kotlin.backend.common.serialization.metadata.makeSerializedKlibMetadata
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
@@ -31,18 +31,20 @@ import org.jetbrains.kotlin.ir.AbstractIrGeneratorTestCase
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.backend.js.JsFactories
import org.jetbrains.kotlin.ir.backend.js.KotlinFileSerializedData
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.serializeModuleIntoKlib
import org.jetbrains.kotlin.ir.backend.js.serializeScope
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.library.impl.buildKotlinLibrary
import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.metadata.ProtoBuf
@@ -62,7 +64,6 @@ import org.jetbrains.kotlin.test.util.KtTestUtil
import org.jetbrains.kotlin.util.DummyLogger
import org.jetbrains.kotlin.utils.rethrow
import java.io.File
import java.util.*
/**
* Compares compiled and deserialized IR
@@ -147,81 +148,25 @@ abstract class AbstractKlibIrTextTestCase : CodegenTestCase() {
stdlib: KotlinLibrary,
containsErrorCode: Boolean,
): String {
val ktFiles = myFiles.psiFiles
val serializedIr = JsIrModuleSerializer(
KtDiagnosticReporterWithImplicitIrBasedContext(
DiagnosticReporterFactory.createPendingReporter(),
myEnvironment.configuration.languageVersionSettings,
),
irModuleFragment.irBuiltins,
CompatibilityMode.CURRENT,
false,
emptyList(),
myEnvironment.configuration.languageVersionSettings,
).serializedIrModule(irModuleFragment)
val moduleDescriptor = irModuleFragment.descriptor
val metadataSerializer = klibMetadataIncrementalSerializer(myEnvironment.configuration, myEnvironment.project, containsErrorCode)
val compiledKotlinFiles = mutableListOf<KotlinFileSerializedData>()
for ((ktFile, binaryFile) in ktFiles.zip(serializedIr.files)) {
assert(ktFile.virtualFilePath == binaryFile.path) {
"""The Kt and Ir files are put in different order
Kt: ${ktFile.virtualFilePath}
Ir: ${binaryFile.path}
""".trimMargin()
}
val packageFragment = metadataSerializer.serializeScope(ktFile, bindingContext, moduleDescriptor)
val compiledKotlinFile = KotlinFileSerializedData(packageFragment.toByteArray(), binaryFile)
compiledKotlinFiles += compiledKotlinFile
}
val header = metadataSerializer.serializeHeader(
moduleDescriptor,
compiledKotlinFiles.map { it.irData.fqName }.distinct().sorted(),
emptyList()
).toByteArray()
val serializedMetadata = makeSerializedKlibMetadata(
compiledKotlinFiles.groupBy { it.irData.fqName }
.map { (fqn, data) -> fqn to data.sortedBy { it.irData.path }.map { it.metadata } }.toMap(),
header
)
val fullSerializedIr = SerializedIrModule(compiledKotlinFiles.map { it.irData })
val properties = Properties().also { p ->
if (containsErrorCode) {
p.setProperty(KLIB_PROPERTY_CONTAINS_ERROR_CODE, "true")
}
}
val versions = KotlinLibraryVersioning(
abiVersion = KotlinAbiVersion.CURRENT,
libraryVersion = null,
compilerVersion = KotlinCompilerVersion.VERSION,
metadataVersion = KlibMetadataVersion.INSTANCE.toString(),
)
val klibDir = org.jetbrains.kotlin.konan.file.createTempDir("testKlib")
buildKotlinLibrary(
linkDependencies = listOf(stdlib),
ir = fullSerializedIr,
metadata = serializedMetadata,
dataFlowGraph = null,
manifestProperties = properties,
serializeModuleIntoKlib(
moduleName = MODULE_NAME,
configuration = myEnvironment.configuration,
diagnosticReporter = DiagnosticReporterFactory.createPendingReporter(),
files = myFiles.psiFiles.map(::KtPsiSourceFile),
klibPath = klibDir.canonicalPath,
dependencies = listOf(stdlib),
moduleFragment = irModuleFragment,
cleanFiles = emptyList(),
nopack = true,
perFile = false,
output = klibDir.canonicalPath,
versions = versions,
builtInsPlatform = BuiltInsPlatform.JS
containsErrorCode = containsErrorCode,
abiVersion = KotlinAbiVersion.CURRENT,
jsOutputName = null,
builtInsPlatform = BuiltInsPlatform.JS,
serializeSingleFile = { metadataSerializer.serializeScope(it, bindingContext, irModuleFragment.descriptor) }
)
return klibDir.canonicalPath
}