[KLIB] Introduce compatible mode for klibs.

Based on library ABI version linker could decide which signature mode
to be used to guarantee backward compatibility.
This commit is contained in:
Roman Artemev
2021-05-26 19:42:06 +03:00
committed by TeamCityServer
parent 3e99951a66
commit b5c28c1912
38 changed files with 343 additions and 256 deletions
@@ -21,12 +21,13 @@ import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.isPublicApi
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment
@@ -52,17 +53,17 @@ class JvmIrLinker(
moduleDescriptor.name.asString().startsWith("<dependencies of ")
// TODO: implement special Java deserializer
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer {
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: KotlinLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer {
if (klib != null) {
assert(moduleDescriptor.getCapability(KlibModuleOrigin.CAPABILITY) != null)
return JvmModuleDeserializer(moduleDescriptor, klib, strategy)
return JvmModuleDeserializer(moduleDescriptor, klib, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT, strategy)
}
return MetadataJVMModuleDeserializer(moduleDescriptor, emptyList())
}
private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy) :
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategy)
private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, libraryAbiVersion: KotlinAbiVersion, strategy: DeserializationStrategy) :
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategy, libraryAbiVersion)
private fun DeclarationDescriptor.isJavaDescriptor(): Boolean {
if (this is PackageFragmentDescriptor) {
@@ -122,7 +123,7 @@ class JvmIrLinker(
}
private inner class MetadataJVMModuleDeserializer(moduleDescriptor: ModuleDescriptor, dependencies: List<IrModuleDeserializer>) :
IrModuleDeserializer(moduleDescriptor) {
IrModuleDeserializer(moduleDescriptor, KotlinAbiVersion.CURRENT) {
// TODO: implement proper check whether `idSig` belongs to this module
override fun contains(idSig: IdSignature): Boolean = true
@@ -28,11 +28,7 @@ import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField
abstract class AbstractJvmManglerIr : IrBasedKotlinManglerImpl() {
companion object {
private val exportChecker = JvmIrExportChecker()
}
private class JvmIrExportChecker : IrExportCheckerVisitor() {
private class JvmIrExportChecker(compatibleMode: Boolean) : IrExportCheckerVisitor(compatibleMode) {
override fun IrDeclaration.isPlatformSpecificExported() = false
}
@@ -44,7 +40,7 @@ abstract class AbstractJvmManglerIr : IrBasedKotlinManglerImpl() {
irFunction.isFromJava()
}
override fun getExportChecker(): KotlinExportChecker<IrDeclaration> = exportChecker
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<IrDeclaration> = JvmIrExportChecker(compatibleMode)
override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> {
return JvmIrManglerComputer(StringBuilder(256), mode)
@@ -71,8 +67,7 @@ abstract class AbstractJvmDescriptorMangler(private val mainDetector: MainFuncti
override fun addReturnTypeSpecialCase(functionDescriptor: FunctionDescriptor): Boolean =
functionDescriptor is JavaMethodDescriptor
override fun copy(newMode: MangleMode): DescriptorMangleComputer =
JvmDescriptorManglerComputer(builder, mainDetector, newMode)
override fun copy(newMode: MangleMode): DescriptorMangleComputer = JvmDescriptorManglerComputer(builder, mainDetector, newMode)
private fun isMainFunction(descriptor: FunctionDescriptor): Boolean = mainDetector?.isMain(descriptor) ?: false
@@ -89,10 +84,14 @@ abstract class AbstractJvmDescriptorMangler(private val mainDetector: MainFuncti
return if (isJavaField) MangleConstant.JAVA_FIELD_SUFFIX else null
}
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Nothing?) {} // SKIP in case of synthetic properties
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Nothing?) {
// In general, having module descriptor as `containingDeclaration` for regular declaration is considered an error (in JS/Native)
// because there should be `PackageFragmentDescriptor` in between
// but on JVM there is `SyntheticJavaPropertyDescriptor` whose parent is a module. So let just skip it.
}
}
override fun getExportChecker(): KotlinExportChecker<DeclarationDescriptor> = exportChecker
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<DeclarationDescriptor> = exportChecker
override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<DeclarationDescriptor> {
return JvmDescriptorManglerComputer(StringBuilder(256), mainDetector, mode)