[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:
committed by
TeamCityServer
parent
3e99951a66
commit
b5c28c1912
+6
-3
@@ -5,7 +5,10 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrOverridableMember
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -41,7 +44,7 @@ class FakeOverrideChecker(
|
||||
.filterNot { it.visibility == DescriptorVisibilities.PRIVATE || it.visibility == DescriptorVisibilities.INVISIBLE_FAKE }
|
||||
|
||||
val descriptorSignatures = descriptorFakeOverrides
|
||||
.map { with(descriptorMangler) { it.signatureString }}
|
||||
.map { with(descriptorMangler) { it.signatureString() } }
|
||||
.sorted()
|
||||
|
||||
val irFakeOverrides = clazz.declarations
|
||||
@@ -53,7 +56,7 @@ class FakeOverrideChecker(
|
||||
}
|
||||
|
||||
val irSignatures = irFakeOverrides
|
||||
.map { with(irMangler) { it.signatureString }}
|
||||
.map { with(irMangler) { it.signatureString() } }
|
||||
.sorted()
|
||||
|
||||
// We can't have equality here because dependency libraries could have
|
||||
|
||||
+32
-21
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.overrides
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
|
||||
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
|
||||
import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable
|
||||
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
|
||||
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.ir.types.getClass
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.fileOrNull
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
|
||||
class FakeOverrideGlobalDeclarationTable(
|
||||
@@ -77,13 +79,15 @@ class FakeOverrideBuilder(
|
||||
// TODO: The declaration table is needed for the signaturer.
|
||||
private val fakeOverrideDeclarationTable = FakeOverrideDeclarationTable(mangler)
|
||||
|
||||
private val fakeOverrideClassQueue = mutableListOf<IrClass>()
|
||||
fun enqueueClass(clazz: IrClass, signature: IdSignature) {
|
||||
// private class CompatibilityMode(val oldSignatures: Boolean)
|
||||
|
||||
private val fakeOverrideCandidates = mutableMapOf<IrClass, CompatibilityMode>()
|
||||
fun enqueueClass(clazz: IrClass, signature: IdSignature, compatibilityMode: CompatibilityMode) {
|
||||
fakeOverrideDeclarationTable.assumeDeclarationSignature(clazz, signature)
|
||||
fakeOverrideClassQueue.add(clazz)
|
||||
fakeOverrideCandidates[clazz] = compatibilityMode
|
||||
}
|
||||
|
||||
private fun buildFakeOverrideChainsForClass(clazz: IrClass) {
|
||||
private fun buildFakeOverrideChainsForClass(clazz: IrClass, compatibilityMode: CompatibilityMode) {
|
||||
if (haveFakeOverrides.contains(clazz)) return
|
||||
if (!platformSpecificClassFilter.needToConstructFakeOverrides(clazz)) return
|
||||
|
||||
@@ -93,20 +97,25 @@ class FakeOverrideBuilder(
|
||||
it.getClass() ?: error("Unexpected super type: $it")
|
||||
}
|
||||
|
||||
superClasses.forEach {
|
||||
buildFakeOverrideChainsForClass(it)
|
||||
haveFakeOverrides.add(it)
|
||||
superClasses.forEach { superClass ->
|
||||
val mode = fakeOverrideCandidates[superClass] ?: compatibilityMode
|
||||
buildFakeOverrideChainsForClass(superClass, mode)
|
||||
haveFakeOverrides.add(superClass)
|
||||
}
|
||||
|
||||
irOverridingUtil.buildFakeOverridesForClass(clazz)
|
||||
fakeOverrideDeclarationTable.run {
|
||||
inFile(clazz.fileOrNull) {
|
||||
irOverridingUtil.buildFakeOverridesForClass(clazz, compatibilityMode.oldSignatures)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction) {
|
||||
val signature = composeSignature(declaration)
|
||||
override fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction, compatibilityMode: Boolean) {
|
||||
val signature = composeSignature(declaration, compatibilityMode)
|
||||
declareFunctionFakeOverride(declaration, signature)
|
||||
}
|
||||
|
||||
override fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty) {
|
||||
override fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty, compatibilityMode: Boolean) {
|
||||
// To compute a signature for a property with type parameters,
|
||||
// we must have its accessor's correspondingProperty pointing to the property's symbol.
|
||||
// See IrMangleComputer.mangleTypeParameterReference() for details.
|
||||
@@ -123,21 +132,21 @@ class FakeOverrideBuilder(
|
||||
it.correspondingPropertySymbol = tempSymbol
|
||||
}
|
||||
|
||||
val signature = composeSignature(declaration)
|
||||
val signature = composeSignature(declaration, compatibilityMode)
|
||||
declarePropertyFakeOverride(declaration, signature)
|
||||
|
||||
declaration.getter?.let {
|
||||
it.correspondingPropertySymbol = declaration.symbol
|
||||
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override getter: $it"))
|
||||
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override getter: $it"), compatibilityMode)
|
||||
}
|
||||
declaration.setter?.let {
|
||||
it.correspondingPropertySymbol = declaration.symbol
|
||||
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override setter: $it"))
|
||||
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override setter: $it"), compatibilityMode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun composeSignature(declaration: IrDeclaration) =
|
||||
fakeOverrideDeclarationTable.signaturer.composeSignatureForDeclaration(declaration)
|
||||
private fun composeSignature(declaration: IrDeclaration, compatibleMode: Boolean) =
|
||||
fakeOverrideDeclarationTable.signaturer.composeSignatureForDeclaration(declaration, compatibleMode)
|
||||
|
||||
private fun declareFunctionFakeOverride(declaration: IrFakeOverrideFunction, signature: IdSignature) {
|
||||
val parent = declaration.parentAsClass
|
||||
@@ -159,16 +168,18 @@ class FakeOverrideBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
private fun provideFakeOverrides(klass: IrClass) {
|
||||
buildFakeOverrideChainsForClass(klass)
|
||||
private fun provideFakeOverrides(klass: IrClass, compatibleMode: CompatibilityMode) {
|
||||
buildFakeOverrideChainsForClass(klass, compatibleMode)
|
||||
irOverridingUtil.clear()
|
||||
haveFakeOverrides.add(klass)
|
||||
}
|
||||
|
||||
fun provideFakeOverrides() {
|
||||
while (fakeOverrideClassQueue.isNotEmpty()) {
|
||||
val klass = fakeOverrideClassQueue.removeLast()
|
||||
provideFakeOverrides(klass)
|
||||
val entries = fakeOverrideCandidates.entries
|
||||
while (entries.isNotEmpty()) {
|
||||
val candidate = entries.last()
|
||||
entries.remove(candidate)
|
||||
provideFakeOverrides(candidate.key, candidate.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.library.IrLibrary
|
||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||
|
||||
@@ -25,9 +26,10 @@ abstract class BasicIrModuleDeserializer(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
override val klib: IrLibrary,
|
||||
override val strategy: DeserializationStrategy,
|
||||
private val containsErrorCode: Boolean = false,
|
||||
libraryAbiVersion: KotlinAbiVersion,
|
||||
private val containsErrorCode: Boolean = false
|
||||
) :
|
||||
IrModuleDeserializer(moduleDescriptor) {
|
||||
IrModuleDeserializer(moduleDescriptor, libraryAbiVersion) {
|
||||
|
||||
private val fileToDeserializerMap = mutableMapOf<IrFile, IrFileDeserializer>()
|
||||
|
||||
|
||||
+31
-16
@@ -6,14 +6,19 @@
|
||||
package org.jetbrains.kotlin.backend.common.serialization
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.backend.common.serialization.signature.PublicIdSignatureComputer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
|
||||
|
||||
interface IdSignatureClashTracker {
|
||||
@@ -43,13 +48,13 @@ abstract class GlobalDeclarationTable(
|
||||
}
|
||||
}
|
||||
|
||||
open fun computeSignatureByDeclaration(declaration: IrDeclaration): IdSignature {
|
||||
open fun computeSignatureByDeclaration(declaration: IrDeclaration, compatibleMode: Boolean): IdSignature {
|
||||
return table.getOrPut(declaration) {
|
||||
publicIdSignatureComputer.composePublicIdSignature(declaration).also { clashTracker.commit(declaration, it) }
|
||||
publicIdSignatureComputer.composePublicIdSignature(declaration, compatibleMode).also { clashTracker.commit(declaration, it) }
|
||||
}
|
||||
}
|
||||
|
||||
fun isExportedDeclaration(declaration: IrDeclaration): Boolean = with(mangler) { declaration.isExported() }
|
||||
fun isExportedDeclaration(declaration: IrDeclaration, compatibleMode: Boolean): Boolean = with(mangler) { declaration.isExported(compatibleMode) }
|
||||
}
|
||||
|
||||
open class DeclarationTable(globalTable: GlobalDeclarationTable) {
|
||||
@@ -62,24 +67,34 @@ open class DeclarationTable(globalTable: GlobalDeclarationTable) {
|
||||
signaturer.inFile(file?.symbol, block)
|
||||
}
|
||||
|
||||
fun isExportedDeclaration(declaration: IrDeclaration) = globalDeclarationTable.isExportedDeclaration(declaration)
|
||||
|
||||
private fun IrDeclaration.isLocalDeclaration(compatibleMode: Boolean): Boolean {
|
||||
return !isExportedDeclaration(this, compatibleMode)
|
||||
}
|
||||
|
||||
fun isExportedDeclaration(declaration: IrDeclaration, compatibleMode: Boolean) =
|
||||
globalDeclarationTable.isExportedDeclaration(declaration, compatibleMode)
|
||||
|
||||
protected open fun tryComputeBackendSpecificSignature(declaration: IrDeclaration): IdSignature? = null
|
||||
|
||||
private fun computeSignatureByDeclaration(declaration: IrDeclaration): IdSignature {
|
||||
tryComputeBackendSpecificSignature(declaration)?.let { return it }
|
||||
return if (declaration.isLocalDeclaration()) {
|
||||
table.getOrPut(declaration) { signaturer.composeFileLocalIdSignature(declaration) }
|
||||
} else globalDeclarationTable.computeSignatureByDeclaration(declaration)
|
||||
private fun allocateIndexedSignature(declaration: IrDeclaration, compatibleMode: Boolean): IdSignature {
|
||||
return table.getOrPut(declaration) { signaturer.composeFileLocalIdSignature(declaration, compatibleMode) }
|
||||
}
|
||||
|
||||
fun privateDeclarationSignature(declaration: IrDeclaration, builder: () -> IdSignature): IdSignature {
|
||||
assert(declaration.isLocalDeclaration())
|
||||
private fun computeSignatureByDeclaration(declaration: IrDeclaration, compatibleMode: Boolean): IdSignature {
|
||||
tryComputeBackendSpecificSignature(declaration)?.let { return it }
|
||||
return if (declaration.isLocalDeclaration(compatibleMode)) {
|
||||
allocateIndexedSignature(declaration, compatibleMode)
|
||||
} else globalDeclarationTable.computeSignatureByDeclaration(declaration, compatibleMode)
|
||||
}
|
||||
|
||||
fun privateDeclarationSignature(declaration: IrDeclaration, compatibleMode: Boolean, builder: () -> IdSignature): IdSignature {
|
||||
assert(declaration.isLocalDeclaration(compatibleMode))
|
||||
return table.getOrPut(declaration) { builder() }
|
||||
}
|
||||
|
||||
fun signatureByDeclaration(declaration: IrDeclaration): IdSignature {
|
||||
return computeSignatureByDeclaration(declaration)
|
||||
fun signatureByDeclaration(declaration: IrDeclaration, compatibleMode: Boolean): IdSignature {
|
||||
return computeSignatureByDeclaration(declaration, compatibleMode)
|
||||
}
|
||||
|
||||
fun assumeDeclarationSignature(declaration: IrDeclaration, signature: IdSignature) {
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ class DescriptorByIdSignatureFinder(
|
||||
// We don't compute id for typealiases and classes.
|
||||
candidate is ClassDescriptor || candidate is TypeAliasDescriptor
|
||||
} else {
|
||||
val candidateHash = with(mangler) { candidate.signatureMangle }
|
||||
val candidateHash = with(mangler) { candidate.signatureMangle() }
|
||||
candidateHash == id
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.library.IrLibrary
|
||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||
import org.jetbrains.kotlin.library.SerializedIrFile
|
||||
import org.jetbrains.kotlin.library.impl.*
|
||||
|
||||
@@ -79,7 +80,7 @@ class CurrentModuleWithICDeserializer(
|
||||
private val irBuiltIns: IrBuiltIns,
|
||||
icData: List<SerializedIrFile>,
|
||||
icReaderFactory: (IrLibrary) -> IrModuleDeserializer) :
|
||||
IrModuleDeserializer(delegate.moduleDescriptor) {
|
||||
IrModuleDeserializer(delegate.moduleDescriptor, KotlinAbiVersion.CURRENT) {
|
||||
|
||||
private val dirtyDeclarations = mutableMapOf<IdSignature, IrSymbol>()
|
||||
private val icKlib = ICKotlinLibrary(icData)
|
||||
|
||||
+5
-1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.InlineClassRepresentation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterPublicSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.*
|
||||
@@ -32,6 +34,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import kotlin.collections.set
|
||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrAnonymousInit as ProtoAnonymousInit
|
||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrClass as ProtoClass
|
||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructor as ProtoConstructor
|
||||
@@ -73,6 +76,7 @@ class IrDeclarationDeserializer(
|
||||
private val skipMutableState: Boolean = false,
|
||||
additionalStatementOriginIndex: Map<String, IrStatementOrigin> = emptyMap(),
|
||||
allowErrorStatementOrigins: Boolean = false,
|
||||
private val compatibilityMode: CompatibilityMode
|
||||
) {
|
||||
|
||||
val bodyDeserializer = IrBodyDeserializer(builtIns, allowErrorNodes, irFactory, fileReader, this, statementOriginIndex + additionalStatementOriginIndex, allowErrorStatementOrigins)
|
||||
@@ -334,7 +338,7 @@ class IrDeclarationDeserializer(
|
||||
else -> computeMissingInlineClassRepresentationForCompatibility(this)
|
||||
}
|
||||
|
||||
fakeOverrideBuilder.enqueueClass(this, signature)
|
||||
fakeOverrideBuilder.enqueueClass(this, signature, compatibilityMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -71,9 +71,7 @@ class FileDeserializationState(
|
||||
|
||||
val symbolDeserializer =
|
||||
IrSymbolDeserializer(
|
||||
linker.symbolTable,
|
||||
fileReader,
|
||||
file.symbol,
|
||||
linker.symbolTable, fileReader, file.symbol,
|
||||
fileProto.actualList,
|
||||
::addIdSignature,
|
||||
linker::handleExpectActualMapping,
|
||||
@@ -102,6 +100,7 @@ class FileDeserializationState(
|
||||
symbolDeserializer,
|
||||
linker.fakeOverrideBuilder.platformSpecificClassFilter,
|
||||
linker.fakeOverrideBuilder,
|
||||
compatibilityMode = moduleDeserializer.compatibilityMode
|
||||
)
|
||||
|
||||
val fileDeserializer = IrFileDeserializer(file, fileReader, fileProto, symbolDeserializer, declarationDeserializer)
|
||||
|
||||
+5
-4
@@ -120,6 +120,7 @@ open class IrFileSerializer(
|
||||
val messageLogger: IrMessageLogger,
|
||||
private val declarationTable: DeclarationTable,
|
||||
private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
|
||||
private val compatibilityMode: CompatibilityMode,
|
||||
private val bodiesOnlyForInlines: Boolean = false,
|
||||
private val skipExpects: Boolean = false,
|
||||
// required for JS IC caches
|
||||
@@ -312,7 +313,7 @@ open class IrFileSerializer(
|
||||
}
|
||||
|
||||
private fun protoIdSignature(declaration: IrDeclaration): Int {
|
||||
val idSig = declarationTable.signatureByDeclaration(declaration)
|
||||
val idSig = declarationTable.signatureByDeclaration(declaration, compatibilityMode.oldSignatures)
|
||||
return protoIdSignature(idSig)
|
||||
}
|
||||
|
||||
@@ -1470,7 +1471,7 @@ open class IrFileSerializer(
|
||||
|
||||
for (declaration in declarations) {
|
||||
val byteArray = serializeDeclaration(declaration).toByteArray()
|
||||
val idSig = declarationTable.signatureByDeclaration(declaration)
|
||||
val idSig = declarationTable.signatureByDeclaration(declaration, compatibleMode = false)
|
||||
|
||||
// TODO: keep order similar
|
||||
// ^ TODO what does that mean?
|
||||
@@ -1521,8 +1522,8 @@ open class IrFileSerializer(
|
||||
}
|
||||
|
||||
val byteArray = serializeDeclaration(it).toByteArray()
|
||||
val idSig = declarationTable.signatureByDeclaration(it)
|
||||
require(idSig === idSig.topLevelSignature()) { "IdSig: $idSig\ntopLevel: ${idSig.topLevelSignature()}" }
|
||||
val idSig = declarationTable.signatureByDeclaration(it, compatibilityMode.oldSignatures)
|
||||
require(idSig == idSig.topLevelSignature()) { "IdSig: $idSig\ntopLevel: ${idSig.topLevelSignature()}" }
|
||||
require(!idSig.isPackageSignature()) { "IsSig: $idSig\nDeclaration: ${it.render()}" }
|
||||
|
||||
// TODO: keep order similar
|
||||
|
||||
+35
-6
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.library.IrLibrary
|
||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||
|
||||
internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind {
|
||||
return when (this) {
|
||||
@@ -28,11 +29,35 @@ internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class IrModuleDeserializer(val moduleDescriptor: ModuleDescriptor) {
|
||||
class CompatibilityMode(val abiVersion: KotlinAbiVersion) {
|
||||
|
||||
init {
|
||||
assert(abiVersion.isCompatible())
|
||||
}
|
||||
|
||||
val oldSignatures: Boolean
|
||||
get() {
|
||||
if (abiVersion.minor == LAST_PRIVATE_SIG_ABI_VERSION.minor) {
|
||||
return abiVersion.patch <= LAST_PRIVATE_SIG_ABI_VERSION.patch
|
||||
}
|
||||
return abiVersion.minor < LAST_PRIVATE_SIG_ABI_VERSION.minor
|
||||
}
|
||||
|
||||
companion object {
|
||||
val LAST_PRIVATE_SIG_ABI_VERSION = KotlinAbiVersion(1, 5, 0)
|
||||
|
||||
val WITH_PRIVATE_SIG = CompatibilityMode(LAST_PRIVATE_SIG_ABI_VERSION)
|
||||
val WITH_COMMON_SIG = CompatibilityMode(KotlinAbiVersion.CURRENT)
|
||||
|
||||
val CURRENT = WITH_COMMON_SIG
|
||||
}
|
||||
}
|
||||
|
||||
abstract class IrModuleDeserializer(val moduleDescriptor: ModuleDescriptor, val libraryAbiVersion: KotlinAbiVersion) {
|
||||
abstract operator fun contains(idSig: IdSignature): Boolean
|
||||
abstract fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol
|
||||
|
||||
open fun referenceSimpleFunctionByLocalSignature(file: IrFile, idSignature: IdSignature) : IrSimpleFunctionSymbol =
|
||||
open fun referenceSimpleFunctionByLocalSignature(file: IrFile, idSignature: IdSignature): IrSimpleFunctionSymbol =
|
||||
error("Unsupported operation")
|
||||
|
||||
open fun referencePropertyByLocalSignature(file: IrFile, idSignature: IdSignature): IrPropertySymbol =
|
||||
@@ -53,7 +78,9 @@ abstract class IrModuleDeserializer(val moduleDescriptor: ModuleDescriptor) {
|
||||
|
||||
open fun init(delegate: IrModuleDeserializer) {}
|
||||
|
||||
open fun addModuleReachableTopLevel(idSig: IdSignature) { error("Unsupported Operation (sig: $idSig") }
|
||||
open fun addModuleReachableTopLevel(idSig: IdSignature) {
|
||||
error("Unsupported Operation (sig: $idSig")
|
||||
}
|
||||
|
||||
open fun deserializeReachableDeclarations() { error("Unsupported Operation") }
|
||||
|
||||
@@ -64,14 +91,16 @@ abstract class IrModuleDeserializer(val moduleDescriptor: ModuleDescriptor) {
|
||||
open val strategy: DeserializationStrategy = DeserializationStrategy.ONLY_DECLARATION_HEADERS
|
||||
|
||||
open val isCurrent = false
|
||||
|
||||
val compatibilityMode: CompatibilityMode get() = CompatibilityMode(libraryAbiVersion)
|
||||
}
|
||||
|
||||
// Used to resolve built in symbols like `kotlin.ir.internal.*` or `kotlin.FunctionN`
|
||||
class IrModuleDeserializerWithBuiltIns(
|
||||
builtIns: IrBuiltIns,
|
||||
private val functionFactory: IrAbstractFunctionFactory,
|
||||
private val delegate: IrModuleDeserializer
|
||||
) : IrModuleDeserializer(delegate.moduleDescriptor) {
|
||||
private val delegate: IrModuleDeserializer,
|
||||
) : IrModuleDeserializer(delegate.moduleDescriptor, delegate.libraryAbiVersion) {
|
||||
|
||||
init {
|
||||
// TODO: figure out how it should work for K/N
|
||||
@@ -205,7 +234,7 @@ class IrModuleDeserializerWithBuiltIns(
|
||||
open class CurrentModuleDeserializer(
|
||||
override val moduleFragment: IrModuleFragment,
|
||||
override val moduleDependencies: Collection<IrModuleDeserializer>
|
||||
) : IrModuleDeserializer(moduleFragment.descriptor) {
|
||||
) : IrModuleDeserializer(moduleFragment.descriptor, KotlinAbiVersion.CURRENT) {
|
||||
override fun contains(idSig: IdSignature): Boolean = false // TODO:
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||
import org.jetbrains.kotlin.library.SerializedIrFile
|
||||
import org.jetbrains.kotlin.library.SerializedIrModule
|
||||
|
||||
abstract class IrModuleSerializer<F : IrFileSerializer>(protected val messageLogger: IrMessageLogger) {
|
||||
abstract class IrModuleSerializer<F : IrFileSerializer>(protected val messageLogger: IrMessageLogger, protected val compatibilityMode: CompatibilityMode) {
|
||||
abstract fun createSerializerForFile(file: IrFile): F
|
||||
|
||||
/**
|
||||
|
||||
+1
-6
@@ -22,11 +22,6 @@ 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.ir.util.file
|
||||
import org.jetbrains.kotlin.library.IrLibrary
|
||||
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.ir.util.file
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
@@ -90,7 +85,7 @@ abstract class KotlinIrLinker(
|
||||
|
||||
protected abstract fun createModuleDeserializer(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
klib: IrLibrary?,
|
||||
klib: KotlinLibrary?,
|
||||
strategy: DeserializationStrategy,
|
||||
): IrModuleDeserializer
|
||||
|
||||
|
||||
+1
-1
@@ -11,6 +11,6 @@ import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
abstract class AbstractKotlinMangler<D : Any> : KotlinMangler<D> {
|
||||
override val String.hashMangle get() = cityHash64()
|
||||
|
||||
abstract fun getExportChecker(): KotlinExportChecker<D>
|
||||
abstract fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<D>
|
||||
abstract fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<D>
|
||||
}
|
||||
+21
-34
@@ -9,11 +9,11 @@ import org.jetbrains.kotlin.backend.common.serialization.mangle.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
abstract class DescriptorBasedKotlinManglerImpl : AbstractKotlinMangler<DeclarationDescriptor>(), KotlinMangler.DescriptorMangler {
|
||||
private fun withMode(mode: MangleMode, descriptor: DeclarationDescriptor): String =
|
||||
@@ -21,23 +21,15 @@ abstract class DescriptorBasedKotlinManglerImpl : AbstractKotlinMangler<Declarat
|
||||
|
||||
override fun ClassDescriptor.mangleEnumEntryString(): String = withMode(MangleMode.FQNAME, this)
|
||||
|
||||
override fun ClassDescriptor.isExportEnumEntry(): Boolean =
|
||||
getExportChecker().check(this, SpecialDeclarationType.ENUM_ENTRY)
|
||||
override fun PropertyDescriptor.mangleFieldString(): String = mangleString()
|
||||
|
||||
override fun PropertyDescriptor.isExportField(): Boolean = false
|
||||
override fun DeclarationDescriptor.mangleString(): String = withMode(MangleMode.FULL, this)
|
||||
|
||||
override fun PropertyDescriptor.mangleFieldString(): String = error("Fields supposed to be non-exporting")
|
||||
override fun DeclarationDescriptor.signatureString(): String = withMode(MangleMode.SIGNATURE, this)
|
||||
|
||||
override val DeclarationDescriptor.mangleString: String
|
||||
get() = withMode(MangleMode.FULL, this)
|
||||
override fun DeclarationDescriptor.fqnString(): String = withMode(MangleMode.FQNAME, this)
|
||||
|
||||
override val DeclarationDescriptor.signatureString: String
|
||||
get() = withMode(MangleMode.SIGNATURE, this)
|
||||
|
||||
override val DeclarationDescriptor.fqnString: String
|
||||
get() = withMode(MangleMode.FQNAME, this)
|
||||
|
||||
override fun DeclarationDescriptor.isExported(): Boolean = getExportChecker().check(this, SpecialDeclarationType.REGULAR)
|
||||
override fun DeclarationDescriptor.isExported(compatibleMode: Boolean): Boolean = getExportChecker(compatibleMode).check(this, SpecialDeclarationType.REGULAR)
|
||||
}
|
||||
|
||||
class Ir2DescriptorManglerAdapter(private val delegate: DescriptorBasedKotlinManglerImpl) : AbstractKotlinMangler<IrDeclaration>(),
|
||||
@@ -45,31 +37,26 @@ class Ir2DescriptorManglerAdapter(private val delegate: DescriptorBasedKotlinMan
|
||||
override val manglerName: String
|
||||
get() = delegate.manglerName
|
||||
|
||||
override fun IrDeclaration.isExported(): Boolean {
|
||||
override fun IrDeclaration.isExported(compatibleMode: Boolean): Boolean {
|
||||
return delegate.run { descriptor.isExported(compatibleMode) }
|
||||
}
|
||||
|
||||
override fun IrDeclaration.mangleString(): String {
|
||||
return when (this) {
|
||||
is IrAnonymousInitializer -> false
|
||||
is IrEnumEntry -> delegate.run { descriptor.isExportEnumEntry() }
|
||||
is IrField -> delegate.run { descriptor.isExportField() }
|
||||
else -> delegate.run { descriptor.isExported() }
|
||||
is IrEnumEntry -> delegate.run { descriptor.mangleEnumEntryString() }
|
||||
is IrField -> delegate.run { descriptor.mangleFieldString() }
|
||||
else -> delegate.run { descriptor.mangleString() }
|
||||
}
|
||||
}
|
||||
|
||||
override val IrDeclaration.mangleString: String
|
||||
get() {
|
||||
return when (this) {
|
||||
is IrEnumEntry -> delegate.run { descriptor.mangleEnumEntryString() }
|
||||
is IrField -> delegate.run { descriptor.mangleFieldString() }
|
||||
else -> delegate.run { descriptor.mangleString }
|
||||
}
|
||||
}
|
||||
override fun IrDeclaration.signatureString(): String = delegate.run { descriptor.signatureString() }
|
||||
|
||||
override val IrDeclaration.signatureString: String
|
||||
get() = delegate.run { descriptor.signatureString }
|
||||
override fun IrDeclaration.fqnString(): String = delegate.run { descriptor.fqnString() }
|
||||
|
||||
override val IrDeclaration.fqnString: String
|
||||
get() = delegate.run { descriptor.fqnString }
|
||||
override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> =
|
||||
error("Should not have been reached")
|
||||
|
||||
override fun getExportChecker() = error("Should not have been reached")
|
||||
|
||||
override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> = error("Should not have been reached")
|
||||
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<IrDeclaration> {
|
||||
error("Should not be called")
|
||||
}
|
||||
}
|
||||
+6
-7
@@ -12,14 +12,13 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
|
||||
abstract class IrBasedKotlinManglerImpl : AbstractKotlinMangler<IrDeclaration>(), KotlinMangler.IrMangler {
|
||||
override val IrDeclaration.mangleString: String
|
||||
get() = getMangleComputer(MangleMode.FULL).computeMangle(this)
|
||||
|
||||
override val IrDeclaration.signatureString: String
|
||||
get() = getMangleComputer(MangleMode.SIGNATURE).computeMangle(this)
|
||||
override fun IrDeclaration.mangleString(): String = getMangleComputer(MangleMode.FULL).computeMangle(this)
|
||||
|
||||
override val IrDeclaration.fqnString: String
|
||||
get() = getMangleComputer(MangleMode.FQNAME).computeMangle(this)
|
||||
override fun IrDeclaration.signatureString(): String = getMangleComputer(MangleMode.SIGNATURE).computeMangle(this)
|
||||
|
||||
override fun IrDeclaration.isExported(): Boolean = getExportChecker().check(this, SpecialDeclarationType.REGULAR)
|
||||
override fun IrDeclaration.fqnString(): String = getMangleComputer(MangleMode.FQNAME).computeMangle(this)
|
||||
|
||||
override fun IrDeclaration.isExported(compatibleMode: Boolean): Boolean =
|
||||
getExportChecker(compatibleMode).check(this, SpecialDeclarationType.REGULAR)
|
||||
}
|
||||
+19
-3
@@ -23,15 +23,23 @@ import org.jetbrains.kotlin.name.SpecialNames
|
||||
abstract class IrExportCheckerVisitor(private val compatibleMode: Boolean) : KotlinExportChecker<IrDeclaration> {
|
||||
|
||||
private val compatibleChecker = CompatibleChecker()
|
||||
private val newChecker = NewChecker()
|
||||
private val checker = Checker()
|
||||
|
||||
/**
|
||||
* @return true if [declaration] is exportable from klib point of view.
|
||||
* Depending on [compatibleMode] option the same declaration could have FileLocal or Common signature.
|
||||
*/
|
||||
override fun check(declaration: IrDeclaration, type: SpecialDeclarationType): Boolean {
|
||||
return declaration.accept(if (compatibleMode) compatibleChecker else newChecker, null)
|
||||
return declaration.accept(if (compatibleMode) compatibleChecker else checker, null)
|
||||
}
|
||||
|
||||
abstract override fun IrDeclaration.isPlatformSpecificExported(): Boolean
|
||||
|
||||
private class NewChecker : IrElementVisitor<Boolean, Nothing?> {
|
||||
/**
|
||||
* Corresponding to export policy of klib ABI >= 1.6.0.
|
||||
* In that case any non-local declaration (including type parameter and field) is exportable and could be navigated between modules
|
||||
*/
|
||||
private class Checker : IrElementVisitor<Boolean, Nothing?> {
|
||||
override fun visitElement(element: IrElement, data: Nothing?): Boolean {
|
||||
error("Should bot reach here ${element.render()}")
|
||||
}
|
||||
@@ -68,6 +76,14 @@ abstract class IrExportCheckerVisitor(private val compatibleMode: Boolean) : Kot
|
||||
override fun visitErrorDeclaration(declaration: IrErrorDeclaration, data: Nothing?): Boolean = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Was using for klib ABI version <= 1.5.0. In that case declaration which has itself or in their hierarchy private or local parent
|
||||
* is considered non-exportable.
|
||||
*
|
||||
* Also type parameters and fields are not exportable.
|
||||
*
|
||||
* Is used to link libraries with ABI level <= 1.5.0
|
||||
*/
|
||||
private inner class CompatibleChecker : IrElementVisitor<Boolean, Nothing?> {
|
||||
private fun IrDeclaration.isExported(annotations: List<IrConstructorCall>, visibility: DescriptorVisibility?): Boolean {
|
||||
val speciallyExported = annotations.hasAnnotation(publishedApiAnnotation) || isPlatformSpecificExported()
|
||||
|
||||
Reference in New Issue
Block a user