[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
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.backend.common.IrValidator
import org.jetbrains.kotlin.backend.common.IrValidatorConfig
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
import org.jetbrains.kotlin.backend.konan.MemoryModel
import org.jetbrains.kotlin.backend.konan.llvm.*
@@ -155,7 +156,7 @@ internal val serializerPhase = konanUnitPhase(
serializedIr = irModule?.let { ir ->
KonanIrModuleSerializer(
messageLogger, ir.irBuiltins, expectDescriptorToSymbol, skipExpects = !expectActualLinker
messageLogger, ir.irBuiltins, expectDescriptorToSymbol, skipExpects = !expectActualLinker, compatibilityMode = CompatibilityMode.CURRENT
).serializedIrModule(ir)
}
@@ -34,9 +34,9 @@ import org.jetbrains.kotlin.name.Name
object KonanBinaryInterface {
private val mangler = object : AbstractKonanIrMangler(true) {}
private val exportChecker = mangler.getExportChecker()
private val exportChecker = mangler.getExportChecker(compatibleMode = true)
val IrFunction.functionName: String get() = mangler.run { signatureString }
val IrFunction.functionName: String get() = mangler.run { signatureString() }
val IrFunction.symbolName: String get() = funSymbolNameImpl()
val IrField.symbolName: String get() =
@@ -65,7 +65,7 @@ object KonanBinaryInterface {
return name // no wrapping currently required
}
return withPrefix(MangleConstant.FUN_PREFIX, mangler.run { mangleString })
return withPrefix(MangleConstant.FUN_PREFIX, mangler.run { mangleString() })
}
private fun IrField.fieldSymbolNameImpl(): String {
@@ -1,5 +1,6 @@
package org.jetbrains.kotlin.backend.konan.serialization
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer
import org.jetbrains.kotlin.backend.konan.RuntimeNames
@@ -16,8 +17,9 @@ class KonanIrFileSerializer(
declarationTable: DeclarationTable,
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
skipExpects: Boolean,
bodiesOnlyForInlines: Boolean = false
): IrFileSerializer(messageLogger, declarationTable, expectDescriptorToSymbol, skipExpects = skipExpects, bodiesOnlyForInlines = bodiesOnlyForInlines) {
bodiesOnlyForInlines: Boolean = false,
compatibilityMode: CompatibilityMode
): IrFileSerializer(messageLogger, declarationTable, expectDescriptorToSymbol, compatibilityMode, bodiesOnlyForInlines, skipExpects) {
override fun backendSpecificExplicitRoot(node: IrAnnotationContainer): Boolean {
val fqn = when (node) {
@@ -1,6 +1,7 @@
package org.jetbrains.kotlin.backend.konan.serialization
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.IrModuleSerializer
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -13,8 +14,9 @@ class KonanIrModuleSerializer(
messageLogger: IrMessageLogger,
irBuiltIns: IrBuiltIns,
private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
val skipExpects: Boolean
) : IrModuleSerializer<KonanIrFileSerializer>(messageLogger) {
val skipExpects: Boolean,
compatibilityMode: CompatibilityMode
) : IrModuleSerializer<KonanIrFileSerializer>(messageLogger, compatibilityMode) {
private val globalDeclarationTable = KonanGlobalDeclarationTable(irBuiltIns)
@@ -28,5 +30,5 @@ class KonanIrModuleSerializer(
file.fileEntry.name != IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName
override fun createSerializerForFile(file: IrFile): KonanIrFileSerializer =
KonanIrFileSerializer(messageLogger, KonanDeclarationTable(globalDeclarationTable), expectDescriptorToSymbol, skipExpects = skipExpects)
KonanIrFileSerializer(messageLogger, KonanDeclarationTable(globalDeclarationTable), expectDescriptorToSymbol, skipExpects = skipExpects, compatibilityMode = compatibilityMode)
}
@@ -41,7 +41,7 @@ import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -93,16 +93,16 @@ internal class KonanIrLinker(
private val forwardDeclarationDeserializer = forwardModuleDescriptor?.let { KonanForwardDeclarationModuleDeserializer(it) }
override val fakeOverrideBuilder = FakeOverrideBuilder(this, symbolTable, KonanManglerIr, builtIns, KonanFakeOverrideClassFilter)
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer {
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: KotlinLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer {
if (moduleDescriptor === forwardModuleDescriptor) {
return forwardDeclarationDeserializer ?: error("forward declaration deserializer expected")
}
if (klib is KotlinLibrary && klib.isInteropLibrary()) {
if (klib != null && klib.isInteropLibrary()) {
// See https://youtrack.jetbrains.com/issue/KT-43517.
// Disabling this flag forces linker to generate IR.
val isCached = false //cachedLibraries.isLibraryCached(klib)
return KonanInteropModuleDeserializer(moduleDescriptor, isCached)
return KonanInteropModuleDeserializer(moduleDescriptor, klib, isCached)
}
return KonanModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy)
@@ -110,16 +110,17 @@ internal class KonanIrLinker(
private inner class KonanModuleDeserializer(
moduleDescriptor: ModuleDescriptor,
klib: IrLibrary,
klib: KotlinLibrary,
strategy: DeserializationStrategy
): BasicIrModuleDeserializer(this@KonanIrLinker, moduleDescriptor, klib, strategy){
): BasicIrModuleDeserializer(this@KonanIrLinker, moduleDescriptor, klib, strategy, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT) {
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList())
}
private inner class KonanInteropModuleDeserializer(
moduleDescriptor: ModuleDescriptor,
klib: KotlinLibrary,
private val isLibraryCached: Boolean
) : IrModuleDeserializer(moduleDescriptor) {
) : IrModuleDeserializer(moduleDescriptor, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT) {
init {
assert(moduleDescriptor.kotlinLibrary.isInteropLibrary())
}
@@ -170,7 +171,7 @@ internal class KonanIrLinker(
override val moduleDependencies: Collection<IrModuleDeserializer> = listOfNotNull(forwardDeclarationDeserializer)
}
private inner class KonanForwardDeclarationModuleDeserializer(moduleDescriptor: ModuleDescriptor) : IrModuleDeserializer(moduleDescriptor) {
private inner class KonanForwardDeclarationModuleDeserializer(moduleDescriptor: ModuleDescriptor) : IrModuleDeserializer(moduleDescriptor, KotlinAbiVersion.CURRENT) {
init {
assert(moduleDescriptor.isForwardDeclarationModule)
}
@@ -1,5 +1,6 @@
package org.jetbrains.kotlin.backend.konan.serialization
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorBasedKotlinManglerImpl
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorExportCheckerVisitor
@@ -12,40 +13,42 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.types.KotlinType
abstract class AbstractKonanIrMangler(private val withReturnType: Boolean) : IrBasedKotlinManglerImpl() {
override fun getExportChecker(): IrExportCheckerVisitor = KonanIrExportChecker()
override fun getExportChecker(compatibleMode: Boolean): IrExportCheckerVisitor = KonanIrExportChecker(compatibleMode)
override fun getMangleComputer(mode: MangleMode): IrMangleComputer =
KonanIrManglerComputer(StringBuilder(256), mode, withReturnType)
override fun getMangleComputer(mode: MangleMode): IrMangleComputer = KonanIrManglerComputer(StringBuilder(256), mode, withReturnType)
private class KonanIrExportChecker : IrExportCheckerVisitor() {
override fun IrDeclaration.isPlatformSpecificExported(): Boolean {
if (this is IrSimpleFunction) if (isFakeOverride) return false
override fun IrDeclaration.isPlatformSpecificExport(): Boolean {
if (this is IrSimpleFunction) if (isFakeOverride) return false
// TODO: revise
if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) {
// Treat any `@SymbolName` declaration as exported.
return true
}
if (annotations.hasAnnotation(KonanFqNames.gcUnsafeCall)) {
// TODO: revise
if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) {
// Treat any `@SymbolName` declaration as exported.
return true
}
if (annotations.hasAnnotation(KonanFqNames.gcUnsafeCall)) {
// Treat any `@GCUnsafeCall` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) {
// Treat any `@ExportForCppRuntime` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) {
// Treat `@CName` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) {
return true
}
return false
// Treat any `@ExportForCppRuntime` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) {
// Treat `@CName` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) {
return true
}
return false
}
private inner class KonanIrExportChecker(compatibleMode: Boolean) : IrExportCheckerVisitor(compatibleMode) {
override fun IrDeclaration.isPlatformSpecificExported(): Boolean = isPlatformSpecificExport()
}
private class KonanIrManglerComputer(builder: StringBuilder, mode: MangleMode, private val withReturnType: Boolean) : IrMangleComputer(builder, mode) {
@@ -88,39 +91,40 @@ abstract class AbstractKonanIrMangler(private val withReturnType: Boolean) : IrB
object KonanManglerIr : AbstractKonanIrMangler(false)
abstract class AbstractKonanDescriptorMangler : DescriptorBasedKotlinManglerImpl() {
override fun getExportChecker(): DescriptorExportCheckerVisitor = KonanDescriptorExportChecker()
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<DeclarationDescriptor> = KonanDescriptorExportChecker()
override fun getMangleComputer(mode: MangleMode): DescriptorMangleComputer =
KonanDescriptorMangleComputer(StringBuilder(256), mode)
override fun getMangleComputer(mode: MangleMode): DescriptorMangleComputer = KonanDescriptorMangleComputer(StringBuilder(256), mode)
private class KonanDescriptorExportChecker : DescriptorExportCheckerVisitor() {
override fun DeclarationDescriptor.isPlatformSpecificExported(): Boolean {
if (this is SimpleFunctionDescriptor) {
if (kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return false
}
// TODO: revise
if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) {
// Treat any `@SymbolName` declaration as exported.
return true
}
if (annotations.hasAnnotation(KonanFqNames.gcUnsafeCall)) {
// Treat any `@GCUnsafeCall` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) {
// Treat any `@ExportForCppRuntime` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) {
// Treat `@CName` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) {
return true
}
private inner class KonanDescriptorExportChecker : DescriptorExportCheckerVisitor() {
override fun DeclarationDescriptor.isPlatformSpecificExported(): Boolean = isPlatformSpecificExport()
}
return false
override fun DeclarationDescriptor.isPlatformSpecificExport(): Boolean {
if (this is SimpleFunctionDescriptor) {
if (kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return false
}
// TODO: revise
if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) {
// Treat any `@SymbolName` declaration as exported.
return true
}
if (annotations.hasAnnotation(KonanFqNames.gcUnsafeCall)) {
// Treat any `@GCUnsafeCall` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) {
// Treat any `@ExportForCppRuntime` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) {
// Treat `@CName` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) {
return true
}
return false
}
private class KonanDescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) : DescriptorMangleComputer(builder, mode) {