[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
@@ -14,18 +14,15 @@ import org.jetbrains.kotlin.fir.signaturer.FirMangler
@NoMutableState @NoMutableState
class FirJvmKotlinMangler(private val session: FirSession) : AbstractKotlinMangler<FirDeclaration>(), FirMangler { class FirJvmKotlinMangler(private val session: FirSession) : AbstractKotlinMangler<FirDeclaration>(), FirMangler {
override val FirDeclaration.mangleString: String override fun FirDeclaration.mangleString(): String = getMangleComputer(MangleMode.FULL).computeMangle(this)
get() = getMangleComputer(MangleMode.FULL).computeMangle(this)
override val FirDeclaration.signatureString: String override fun FirDeclaration.signatureString(): String = getMangleComputer(MangleMode.SIGNATURE).computeMangle(this)
get() = getMangleComputer(MangleMode.SIGNATURE).computeMangle(this)
override val FirDeclaration.fqnString: String override fun FirDeclaration.fqnString(): String = getMangleComputer(MangleMode.FQNAME).computeMangle(this)
get() = getMangleComputer(MangleMode.FQNAME).computeMangle(this)
override fun FirDeclaration.isExported(): Boolean = true override fun FirDeclaration.isExported(compatibleMode: Boolean): Boolean = true
override fun getExportChecker(): KotlinExportChecker<FirDeclaration> { override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<FirDeclaration> {
return object : KotlinExportChecker<FirDeclaration> { return object : KotlinExportChecker<FirDeclaration> {
override fun check(declaration: FirDeclaration, type: SpecialDeclarationType): Boolean = true override fun check(declaration: FirDeclaration, type: SpecialDeclarationType): Boolean = true
@@ -40,17 +40,17 @@ class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatu
} }
override fun visitConstructor(constructor: FirConstructor, data: Any?) { override fun visitConstructor(constructor: FirConstructor, data: Any?) {
hashId = mangler.run { constructor.signatureMangle } hashId = mangler.run { constructor.signatureMangle() }
setExpected(constructor.isExpect) setExpected(constructor.isExpect)
} }
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?) { override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?) {
hashId = mangler.run { simpleFunction.signatureMangle } hashId = mangler.run { simpleFunction.signatureMangle() }
setExpected(simpleFunction.isExpect) setExpected(simpleFunction.isExpect)
} }
override fun visitProperty(property: FirProperty, data: Any?) { override fun visitProperty(property: FirProperty, data: Any?) {
hashId = mangler.run { property.signatureMangle } hashId = mangler.run { property.signatureMangle() }
setExpected(property.isExpect) setExpected(property.isExpect)
} }
@@ -457,11 +457,11 @@ val IrFunction.allParametersCount: Int
// TODO: merge it with FakeOverrideBuilder. // TODO: merge it with FakeOverrideBuilder.
private class FakeOverrideBuilderForLowerings : FakeOverrideBuilderStrategy() { private class FakeOverrideBuilderForLowerings : FakeOverrideBuilderStrategy() {
override fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction) { override fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction, compatibilityMode: Boolean) {
declaration.acquireSymbol(IrSimpleFunctionSymbolImpl()) declaration.acquireSymbol(IrSimpleFunctionSymbolImpl())
} }
override fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty) { override fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty, compatibilityMode: Boolean) {
val propertySymbol = IrPropertySymbolImpl() val propertySymbol = IrPropertySymbolImpl()
declaration.getter?.let { it.correspondingPropertySymbol = propertySymbol } declaration.getter?.let { it.correspondingPropertySymbol = propertySymbol }
declaration.setter?.let { it.correspondingPropertySymbol = propertySymbol } declaration.setter?.let { it.correspondingPropertySymbol = propertySymbol }
@@ -470,18 +470,18 @@ private class FakeOverrideBuilderForLowerings : FakeOverrideBuilderStrategy() {
declaration.getter?.let { declaration.getter?.let {
it.correspondingPropertySymbol = declaration.symbol 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 { declaration.setter?.let {
it.correspondingPropertySymbol = declaration.symbol 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)
} }
} }
} }
fun IrClass.addFakeOverrides(irBuiltIns: IrBuiltIns, implementedMembers: List<IrOverridableMember> = emptyList()) { fun IrClass.addFakeOverrides(irBuiltIns: IrBuiltIns, implementedMembers: List<IrOverridableMember> = emptyList()) {
IrOverridingUtil(irBuiltIns, FakeOverrideBuilderForLowerings()) IrOverridingUtil(irBuiltIns, FakeOverrideBuilderForLowerings())
.buildFakeOverridesForClassUsingOverriddenSymbols(this, implementedMembers) .buildFakeOverridesForClassUsingOverriddenSymbols(this, implementedMembers, compatibilityMode = false)
.forEach { addChild(it) } .forEach { addChild(it) }
} }
@@ -34,7 +34,7 @@ import kotlin.math.abs
private fun <T> mapToKey(declaration: T): String { private fun <T> mapToKey(declaration: T): String {
return with(JsManglerIr) { return with(JsManglerIr) {
if (declaration is IrDeclaration) { if (declaration is IrDeclaration) {
declaration.hashedMangle.toString() declaration.hashedMangle().toString()
} else if (declaration is String) { } else if (declaration is String) {
declaration.hashMangle.toString() declaration.hashMangle.toString()
} else { } else {
@@ -27,16 +27,16 @@ abstract class FakeOverrideBuilderStrategy {
open fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember = open fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember =
buildFakeOverrideMember(superType, member, clazz) buildFakeOverrideMember(superType, member, clazz)
fun linkFakeOverride(fakeOverride: IrOverridableMember) { fun linkFakeOverride(fakeOverride: IrOverridableMember, compatibilityMode: Boolean) {
when (fakeOverride) { when (fakeOverride) {
is IrFakeOverrideFunction -> linkFunctionFakeOverride(fakeOverride) is IrFakeOverrideFunction -> linkFunctionFakeOverride(fakeOverride, compatibilityMode)
is IrFakeOverrideProperty -> linkPropertyFakeOverride(fakeOverride) is IrFakeOverrideProperty -> linkPropertyFakeOverride(fakeOverride, compatibilityMode)
else -> error("Unexpected fake override: $fakeOverride") else -> error("Unexpected fake override: $fakeOverride")
} }
} }
protected abstract fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction) protected abstract fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction, compatibilityMode: Boolean)
protected abstract fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty) protected abstract fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty, compatibilityMode: Boolean)
} }
private fun IrOverridableMember.isPrivateToThisModule(thisClass: IrClass, memberClass: IrClass): Boolean { private fun IrOverridableMember.isPrivateToThisModule(thisClass: IrClass, memberClass: IrClass): Boolean {
@@ -133,7 +133,7 @@ class IrOverridingUtil(
} }
} }
fun buildFakeOverridesForClass(clazz: IrClass) { fun buildFakeOverridesForClass(clazz: IrClass, oldSignatures: Boolean) {
val superTypes = clazz.superTypes val superTypes = clazz.superTypes
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -158,14 +158,15 @@ class IrOverridingUtil(
generateOverridesInFunctionGroup( generateOverridesInFunctionGroup(
group.value, group.value,
fromCurrent.filter { it.name == group.key }, fromCurrent.filter { it.name == group.key },
clazz clazz, oldSignatures
) )
} }
} }
fun buildFakeOverridesForClassUsingOverriddenSymbols( fun buildFakeOverridesForClassUsingOverriddenSymbols(
clazz: IrClass, clazz: IrClass,
implementedMembers: List<IrOverridableMember> = emptyList() implementedMembers: List<IrOverridableMember> = emptyList(),
compatibilityMode: Boolean
): List<IrOverridableMember> { ): List<IrOverridableMember> {
val overriddenMembers = (clazz.declarations.filterIsInstance<IrOverridableMember>() + implementedMembers) val overriddenMembers = (clazz.declarations.filterIsInstance<IrOverridableMember>() + implementedMembers)
.flatMap { member -> member.overriddenSymbols.map { it.owner } } .flatMap { member -> member.overriddenSymbols.map { it.owner } }
@@ -189,7 +190,7 @@ class IrOverridingUtil(
val unoverriddenSuperMembersGroupedByName = unoverriddenSuperMembers.groupBy { it.name } val unoverriddenSuperMembersGroupedByName = unoverriddenSuperMembers.groupBy { it.name }
val fakeOverrides = mutableListOf<IrOverridableMember>() val fakeOverrides = mutableListOf<IrOverridableMember>()
for (group in unoverriddenSuperMembersGroupedByName.values) { for (group in unoverriddenSuperMembersGroupedByName.values) {
createAndBindFakeOverrides(clazz, group, fakeOverrides) createAndBindFakeOverrides(clazz, group, fakeOverrides, compatibilityMode)
} }
return fakeOverrides return fakeOverrides
} }
@@ -207,7 +208,8 @@ class IrOverridingUtil(
private fun generateOverridesInFunctionGroup( private fun generateOverridesInFunctionGroup(
membersFromSupertypes: List<IrOverridableMember>, membersFromSupertypes: List<IrOverridableMember>,
membersFromCurrent: List<IrOverridableMember>, membersFromCurrent: List<IrOverridableMember>,
current: IrClass current: IrClass,
compatibilityMode: Boolean
) { ) {
val notOverridden = membersFromSupertypes.toMutableSet() val notOverridden = membersFromSupertypes.toMutableSet()
@@ -217,7 +219,7 @@ class IrOverridingUtil(
} }
val addedFakeOverrides = mutableListOf<IrOverridableMember>() val addedFakeOverrides = mutableListOf<IrOverridableMember>()
createAndBindFakeOverrides(current, notOverridden, addedFakeOverrides) createAndBindFakeOverrides(current, notOverridden, addedFakeOverrides, compatibilityMode)
current.declarations.addAll(addedFakeOverrides) current.declarations.addAll(addedFakeOverrides)
} }
@@ -259,7 +261,8 @@ class IrOverridingUtil(
private fun createAndBindFakeOverrides( private fun createAndBindFakeOverrides(
current: IrClass, current: IrClass,
notOverridden: Collection<IrOverridableMember>, notOverridden: Collection<IrOverridableMember>,
addedFakeOverrides: MutableList<IrOverridableMember> addedFakeOverrides: MutableList<IrOverridableMember>,
compatibilityMode: Boolean
) { ) {
val fromSuper = notOverridden.toMutableSet() val fromSuper = notOverridden.toMutableSet()
while (fromSuper.isNotEmpty()) { while (fromSuper.isNotEmpty()) {
@@ -268,7 +271,7 @@ class IrOverridingUtil(
notOverriddenFromSuper, notOverriddenFromSuper,
fromSuper fromSuper
) )
createAndBindFakeOverride(overridables, current, addedFakeOverrides) createAndBindFakeOverride(overridables, current, addedFakeOverrides, compatibilityMode)
} }
} }
@@ -381,7 +384,8 @@ class IrOverridingUtil(
private fun createAndBindFakeOverride( private fun createAndBindFakeOverride(
overridables: Collection<IrOverridableMember>, overridables: Collection<IrOverridableMember>,
current: IrClass, current: IrClass,
addedFakeOverrides: MutableList<IrOverridableMember> addedFakeOverrides: MutableList<IrOverridableMember>,
compatibilityMode: Boolean
) { ) {
val effectiveOverridden = filterVisibleFakeOverrides(overridables) val effectiveOverridden = filterVisibleFakeOverrides(overridables)
@@ -416,7 +420,7 @@ class IrOverridingUtil(
) { "Overridden symbols should be set for " + CallableMemberDescriptor.Kind.FAKE_OVERRIDE } ) { "Overridden symbols should be set for " + CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
addedFakeOverrides.add(fakeOverride) addedFakeOverrides.add(fakeOverride)
fakeOverrideBuilder.linkFakeOverride(fakeOverride) fakeOverrideBuilder.linkFakeOverride(fakeOverride, compatibilityMode)
} }
private fun isVisibilityMoreSpecific( private fun isVisibilityMoreSpecific(
@@ -14,14 +14,16 @@ interface KotlinMangler<D : Any> {
val String.hashMangle: Long val String.hashMangle: Long
fun D.isExported(): Boolean fun D.isExported(compatibleMode: Boolean): Boolean
val D.mangleString: String fun D.mangleString(): String
val D.signatureString: String fun D.signatureString(): String
val D.fqnString: String fun D.fqnString(): String
val D.hashedMangle: Long get() = mangleString.hashMangle fun D.hashedMangle(): Long = mangleString().hashMangle
val D.signatureMangle: Long get() = signatureString.hashMangle fun D.signatureMangle(): Long = signatureString().hashMangle
val D.fqnMangle: Long get() = fqnString.hashMangle fun D.fqnMangle(): Long = fqnString().hashMangle
fun D.isPlatformSpecificExport(): Boolean = false
val manglerName: String val manglerName: String
@@ -5,7 +5,10 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.ir.IrElement 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.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -41,7 +44,7 @@ class FakeOverrideChecker(
.filterNot { it.visibility == DescriptorVisibilities.PRIVATE || it.visibility == DescriptorVisibilities.INVISIBLE_FAKE } .filterNot { it.visibility == DescriptorVisibilities.PRIVATE || it.visibility == DescriptorVisibilities.INVISIBLE_FAKE }
val descriptorSignatures = descriptorFakeOverrides val descriptorSignatures = descriptorFakeOverrides
.map { with(descriptorMangler) { it.signatureString }} .map { with(descriptorMangler) { it.signatureString() } }
.sorted() .sorted()
val irFakeOverrides = clazz.declarations val irFakeOverrides = clazz.declarations
@@ -53,7 +56,7 @@ class FakeOverrideChecker(
} }
val irSignatures = irFakeOverrides val irSignatures = irFakeOverrides
.map { with(irMangler) { it.signatureString }} .map { with(irMangler) { it.signatureString() } }
.sorted() .sorted()
// We can't have equality here because dependency libraries could have // We can't have equality here because dependency libraries could have
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.backend.common.overrides 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.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer 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.IdSignature
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.fileOrNull
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
class FakeOverrideGlobalDeclarationTable( class FakeOverrideGlobalDeclarationTable(
@@ -77,13 +79,15 @@ class FakeOverrideBuilder(
// TODO: The declaration table is needed for the signaturer. // TODO: The declaration table is needed for the signaturer.
private val fakeOverrideDeclarationTable = FakeOverrideDeclarationTable(mangler) private val fakeOverrideDeclarationTable = FakeOverrideDeclarationTable(mangler)
private val fakeOverrideClassQueue = mutableListOf<IrClass>() // private class CompatibilityMode(val oldSignatures: Boolean)
fun enqueueClass(clazz: IrClass, signature: IdSignature) {
private val fakeOverrideCandidates = mutableMapOf<IrClass, CompatibilityMode>()
fun enqueueClass(clazz: IrClass, signature: IdSignature, compatibilityMode: CompatibilityMode) {
fakeOverrideDeclarationTable.assumeDeclarationSignature(clazz, signature) 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 (haveFakeOverrides.contains(clazz)) return
if (!platformSpecificClassFilter.needToConstructFakeOverrides(clazz)) return if (!platformSpecificClassFilter.needToConstructFakeOverrides(clazz)) return
@@ -93,20 +97,25 @@ class FakeOverrideBuilder(
it.getClass() ?: error("Unexpected super type: $it") it.getClass() ?: error("Unexpected super type: $it")
} }
superClasses.forEach { superClasses.forEach { superClass ->
buildFakeOverrideChainsForClass(it) val mode = fakeOverrideCandidates[superClass] ?: compatibilityMode
haveFakeOverrides.add(it) buildFakeOverrideChainsForClass(superClass, mode)
haveFakeOverrides.add(superClass)
} }
irOverridingUtil.buildFakeOverridesForClass(clazz) fakeOverrideDeclarationTable.run {
inFile(clazz.fileOrNull) {
irOverridingUtil.buildFakeOverridesForClass(clazz, compatibilityMode.oldSignatures)
}
}
} }
override fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction) { override fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction, compatibilityMode: Boolean) {
val signature = composeSignature(declaration) val signature = composeSignature(declaration, compatibilityMode)
declareFunctionFakeOverride(declaration, signature) 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, // To compute a signature for a property with type parameters,
// we must have its accessor's correspondingProperty pointing to the property's symbol. // we must have its accessor's correspondingProperty pointing to the property's symbol.
// See IrMangleComputer.mangleTypeParameterReference() for details. // See IrMangleComputer.mangleTypeParameterReference() for details.
@@ -123,21 +132,21 @@ class FakeOverrideBuilder(
it.correspondingPropertySymbol = tempSymbol it.correspondingPropertySymbol = tempSymbol
} }
val signature = composeSignature(declaration) val signature = composeSignature(declaration, compatibilityMode)
declarePropertyFakeOverride(declaration, signature) declarePropertyFakeOverride(declaration, signature)
declaration.getter?.let { declaration.getter?.let {
it.correspondingPropertySymbol = declaration.symbol 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 { declaration.setter?.let {
it.correspondingPropertySymbol = declaration.symbol 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) = private fun composeSignature(declaration: IrDeclaration, compatibleMode: Boolean) =
fakeOverrideDeclarationTable.signaturer.composeSignatureForDeclaration(declaration) fakeOverrideDeclarationTable.signaturer.composeSignatureForDeclaration(declaration, compatibleMode)
private fun declareFunctionFakeOverride(declaration: IrFakeOverrideFunction, signature: IdSignature) { private fun declareFunctionFakeOverride(declaration: IrFakeOverrideFunction, signature: IdSignature) {
val parent = declaration.parentAsClass val parent = declaration.parentAsClass
@@ -159,16 +168,18 @@ class FakeOverrideBuilder(
} }
} }
private fun provideFakeOverrides(klass: IrClass) { private fun provideFakeOverrides(klass: IrClass, compatibleMode: CompatibilityMode) {
buildFakeOverrideChainsForClass(klass) buildFakeOverrideChainsForClass(klass, compatibleMode)
irOverridingUtil.clear() irOverridingUtil.clear()
haveFakeOverrides.add(klass) haveFakeOverrides.add(klass)
} }
fun provideFakeOverrides() { fun provideFakeOverrides() {
while (fakeOverrideClassQueue.isNotEmpty()) { val entries = fakeOverrideCandidates.entries
val klass = fakeOverrideClassQueue.removeLast() while (entries.isNotEmpty()) {
provideFakeOverrides(klass) val candidate = entries.last()
entries.remove(candidate)
provideFakeOverrides(candidate.key, candidate.value)
} }
} }
} }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.protobuf.CodedInputStream
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
@@ -25,9 +26,10 @@ abstract class BasicIrModuleDeserializer(
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
override val klib: IrLibrary, override val klib: IrLibrary,
override val strategy: DeserializationStrategy, 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>() private val fileToDeserializerMap = mutableMapOf<IrFile, IrFileDeserializer>()
@@ -6,14 +6,19 @@
package org.jetbrains.kotlin.backend.common.serialization package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer 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.backend.common.serialization.signature.PublicIdSignatureComputer
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
interface IdSignatureClashTracker { 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) { 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) { open class DeclarationTable(globalTable: GlobalDeclarationTable) {
@@ -62,24 +67,34 @@ open class DeclarationTable(globalTable: GlobalDeclarationTable) {
signaturer.inFile(file?.symbol, block) 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 protected open fun tryComputeBackendSpecificSignature(declaration: IrDeclaration): IdSignature? = null
private fun computeSignatureByDeclaration(declaration: IrDeclaration): IdSignature { private fun allocateIndexedSignature(declaration: IrDeclaration, compatibleMode: Boolean): IdSignature {
tryComputeBackendSpecificSignature(declaration)?.let { return it } return table.getOrPut(declaration) { signaturer.composeFileLocalIdSignature(declaration, compatibleMode) }
return if (declaration.isLocalDeclaration()) {
table.getOrPut(declaration) { signaturer.composeFileLocalIdSignature(declaration) }
} else globalDeclarationTable.computeSignatureByDeclaration(declaration)
} }
fun privateDeclarationSignature(declaration: IrDeclaration, builder: () -> IdSignature): IdSignature { private fun computeSignatureByDeclaration(declaration: IrDeclaration, compatibleMode: Boolean): IdSignature {
assert(declaration.isLocalDeclaration()) 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() } return table.getOrPut(declaration) { builder() }
} }
fun signatureByDeclaration(declaration: IrDeclaration): IdSignature { fun signatureByDeclaration(declaration: IrDeclaration, compatibleMode: Boolean): IdSignature {
return computeSignatureByDeclaration(declaration) return computeSignatureByDeclaration(declaration, compatibleMode)
} }
fun assumeDeclarationSignature(declaration: IrDeclaration, signature: IdSignature) { fun assumeDeclarationSignature(declaration: IrDeclaration, signature: IdSignature) {
@@ -140,7 +140,7 @@ class DescriptorByIdSignatureFinder(
// We don't compute id for typealiases and classes. // We don't compute id for typealiases and classes.
candidate is ClassDescriptor || candidate is TypeAliasDescriptor candidate is ClassDescriptor || candidate is TypeAliasDescriptor
} else { } else {
val candidateHash = with(mangler) { candidate.signatureMangle } val candidateHash = with(mangler) { candidate.signatureMangle() }
candidateHash == id candidateHash == id
} }
} }
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.library.SerializedIrFile import org.jetbrains.kotlin.library.SerializedIrFile
import org.jetbrains.kotlin.library.impl.* import org.jetbrains.kotlin.library.impl.*
@@ -79,7 +80,7 @@ class CurrentModuleWithICDeserializer(
private val irBuiltIns: IrBuiltIns, private val irBuiltIns: IrBuiltIns,
icData: List<SerializedIrFile>, icData: List<SerializedIrFile>,
icReaderFactory: (IrLibrary) -> IrModuleDeserializer) : icReaderFactory: (IrLibrary) -> IrModuleDeserializer) :
IrModuleDeserializer(delegate.moduleDescriptor) { IrModuleDeserializer(delegate.moduleDescriptor, KotlinAbiVersion.CURRENT) {
private val dirtyDeclarations = mutableMapOf<IdSignature, IrSymbol>() private val dirtyDeclarations = mutableMapOf<IdSignature, IrSymbol>()
private val icKlib = ICKotlinLibrary(icData) private val icKlib = ICKotlinLibrary(icData)
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.InlineClassRepresentation
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl 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.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrBody 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.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase 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.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.* 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.CodedInputStream
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
import org.jetbrains.kotlin.types.Variance 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.IrAnonymousInit as ProtoAnonymousInit
import org.jetbrains.kotlin.backend.common.serialization.proto.IrClass as ProtoClass import org.jetbrains.kotlin.backend.common.serialization.proto.IrClass as ProtoClass
import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructor as ProtoConstructor import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructor as ProtoConstructor
@@ -73,6 +76,7 @@ class IrDeclarationDeserializer(
private val skipMutableState: Boolean = false, private val skipMutableState: Boolean = false,
additionalStatementOriginIndex: Map<String, IrStatementOrigin> = emptyMap(), additionalStatementOriginIndex: Map<String, IrStatementOrigin> = emptyMap(),
allowErrorStatementOrigins: Boolean = false, allowErrorStatementOrigins: Boolean = false,
private val compatibilityMode: CompatibilityMode
) { ) {
val bodyDeserializer = IrBodyDeserializer(builtIns, allowErrorNodes, irFactory, fileReader, this, statementOriginIndex + additionalStatementOriginIndex, allowErrorStatementOrigins) val bodyDeserializer = IrBodyDeserializer(builtIns, allowErrorNodes, irFactory, fileReader, this, statementOriginIndex + additionalStatementOriginIndex, allowErrorStatementOrigins)
@@ -334,7 +338,7 @@ class IrDeclarationDeserializer(
else -> computeMissingInlineClassRepresentationForCompatibility(this) else -> computeMissingInlineClassRepresentationForCompatibility(this)
} }
fakeOverrideBuilder.enqueueClass(this, signature) fakeOverrideBuilder.enqueueClass(this, signature, compatibilityMode)
} }
} }
} }
@@ -71,9 +71,7 @@ class FileDeserializationState(
val symbolDeserializer = val symbolDeserializer =
IrSymbolDeserializer( IrSymbolDeserializer(
linker.symbolTable, linker.symbolTable, fileReader, file.symbol,
fileReader,
file.symbol,
fileProto.actualList, fileProto.actualList,
::addIdSignature, ::addIdSignature,
linker::handleExpectActualMapping, linker::handleExpectActualMapping,
@@ -102,6 +100,7 @@ class FileDeserializationState(
symbolDeserializer, symbolDeserializer,
linker.fakeOverrideBuilder.platformSpecificClassFilter, linker.fakeOverrideBuilder.platformSpecificClassFilter,
linker.fakeOverrideBuilder, linker.fakeOverrideBuilder,
compatibilityMode = moduleDeserializer.compatibilityMode
) )
val fileDeserializer = IrFileDeserializer(file, fileReader, fileProto, symbolDeserializer, declarationDeserializer) val fileDeserializer = IrFileDeserializer(file, fileReader, fileProto, symbolDeserializer, declarationDeserializer)
@@ -120,6 +120,7 @@ open class IrFileSerializer(
val messageLogger: IrMessageLogger, val messageLogger: IrMessageLogger,
private val declarationTable: DeclarationTable, private val declarationTable: DeclarationTable,
private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
private val compatibilityMode: CompatibilityMode,
private val bodiesOnlyForInlines: Boolean = false, private val bodiesOnlyForInlines: Boolean = false,
private val skipExpects: Boolean = false, private val skipExpects: Boolean = false,
// required for JS IC caches // required for JS IC caches
@@ -312,7 +313,7 @@ open class IrFileSerializer(
} }
private fun protoIdSignature(declaration: IrDeclaration): Int { private fun protoIdSignature(declaration: IrDeclaration): Int {
val idSig = declarationTable.signatureByDeclaration(declaration) val idSig = declarationTable.signatureByDeclaration(declaration, compatibilityMode.oldSignatures)
return protoIdSignature(idSig) return protoIdSignature(idSig)
} }
@@ -1470,7 +1471,7 @@ open class IrFileSerializer(
for (declaration in declarations) { for (declaration in declarations) {
val byteArray = serializeDeclaration(declaration).toByteArray() val byteArray = serializeDeclaration(declaration).toByteArray()
val idSig = declarationTable.signatureByDeclaration(declaration) val idSig = declarationTable.signatureByDeclaration(declaration, compatibleMode = false)
// TODO: keep order similar // TODO: keep order similar
// ^ TODO what does that mean? // ^ TODO what does that mean?
@@ -1521,8 +1522,8 @@ open class IrFileSerializer(
} }
val byteArray = serializeDeclaration(it).toByteArray() val byteArray = serializeDeclaration(it).toByteArray()
val idSig = declarationTable.signatureByDeclaration(it) val idSig = declarationTable.signatureByDeclaration(it, compatibilityMode.oldSignatures)
require(idSig === idSig.topLevelSignature()) { "IdSig: $idSig\ntopLevel: ${idSig.topLevelSignature()}" } require(idSig == idSig.topLevelSignature()) { "IdSig: $idSig\ntopLevel: ${idSig.topLevelSignature()}" }
require(!idSig.isPackageSignature()) { "IsSig: $idSig\nDeclaration: ${it.render()}" } require(!idSig.isPackageSignature()) { "IsSig: $idSig\nDeclaration: ${it.render()}" }
// TODO: keep order similar // TODO: keep order similar
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinAbiVersion
internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind { internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind {
return when (this) { 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 operator fun contains(idSig: IdSignature): Boolean
abstract fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol 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") error("Unsupported operation")
open fun referencePropertyByLocalSignature(file: IrFile, idSignature: IdSignature): IrPropertySymbol = 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 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") } 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 strategy: DeserializationStrategy = DeserializationStrategy.ONLY_DECLARATION_HEADERS
open val isCurrent = false open val isCurrent = false
val compatibilityMode: CompatibilityMode get() = CompatibilityMode(libraryAbiVersion)
} }
// Used to resolve built in symbols like `kotlin.ir.internal.*` or `kotlin.FunctionN` // Used to resolve built in symbols like `kotlin.ir.internal.*` or `kotlin.FunctionN`
class IrModuleDeserializerWithBuiltIns( class IrModuleDeserializerWithBuiltIns(
builtIns: IrBuiltIns, builtIns: IrBuiltIns,
private val functionFactory: IrAbstractFunctionFactory, private val functionFactory: IrAbstractFunctionFactory,
private val delegate: IrModuleDeserializer private val delegate: IrModuleDeserializer,
) : IrModuleDeserializer(delegate.moduleDescriptor) { ) : IrModuleDeserializer(delegate.moduleDescriptor, delegate.libraryAbiVersion) {
init { init {
// TODO: figure out how it should work for K/N // TODO: figure out how it should work for K/N
@@ -205,7 +234,7 @@ class IrModuleDeserializerWithBuiltIns(
open class CurrentModuleDeserializer( open class CurrentModuleDeserializer(
override val moduleFragment: IrModuleFragment, override val moduleFragment: IrModuleFragment,
override val moduleDependencies: Collection<IrModuleDeserializer> override val moduleDependencies: Collection<IrModuleDeserializer>
) : IrModuleDeserializer(moduleFragment.descriptor) { ) : IrModuleDeserializer(moduleFragment.descriptor, KotlinAbiVersion.CURRENT) {
override fun contains(idSig: IdSignature): Boolean = false // TODO: override fun contains(idSig: IdSignature): Boolean = false // TODO:
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.library.SerializedIrFile import org.jetbrains.kotlin.library.SerializedIrFile
import org.jetbrains.kotlin.library.SerializedIrModule 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 abstract fun createSerializerForFile(file: IrFile): F
/** /**
@@ -22,11 +22,6 @@ import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.file 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.library.KotlinLibrary
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
@@ -90,7 +85,7 @@ abstract class KotlinIrLinker(
protected abstract fun createModuleDeserializer( protected abstract fun createModuleDeserializer(
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
klib: IrLibrary?, klib: KotlinLibrary?,
strategy: DeserializationStrategy, strategy: DeserializationStrategy,
): IrModuleDeserializer ): IrModuleDeserializer
@@ -11,6 +11,6 @@ import org.jetbrains.kotlin.ir.util.KotlinMangler
abstract class AbstractKotlinMangler<D : Any> : KotlinMangler<D> { abstract class AbstractKotlinMangler<D : Any> : KotlinMangler<D> {
override val String.hashMangle get() = cityHash64() 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> abstract fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<D>
} }
@@ -9,11 +9,11 @@ import org.jetbrains.kotlin.backend.common.serialization.mangle.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor 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.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.types.KotlinType
abstract class DescriptorBasedKotlinManglerImpl : AbstractKotlinMangler<DeclarationDescriptor>(), KotlinMangler.DescriptorMangler { abstract class DescriptorBasedKotlinManglerImpl : AbstractKotlinMangler<DeclarationDescriptor>(), KotlinMangler.DescriptorMangler {
private fun withMode(mode: MangleMode, descriptor: DeclarationDescriptor): String = 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.mangleEnumEntryString(): String = withMode(MangleMode.FQNAME, this)
override fun ClassDescriptor.isExportEnumEntry(): Boolean = override fun PropertyDescriptor.mangleFieldString(): String = mangleString()
getExportChecker().check(this, SpecialDeclarationType.ENUM_ENTRY)
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 override fun DeclarationDescriptor.fqnString(): String = withMode(MangleMode.FQNAME, this)
get() = withMode(MangleMode.FULL, this)
override val DeclarationDescriptor.signatureString: String override fun DeclarationDescriptor.isExported(compatibleMode: Boolean): Boolean = getExportChecker(compatibleMode).check(this, SpecialDeclarationType.REGULAR)
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)
} }
class Ir2DescriptorManglerAdapter(private val delegate: DescriptorBasedKotlinManglerImpl) : AbstractKotlinMangler<IrDeclaration>(), class Ir2DescriptorManglerAdapter(private val delegate: DescriptorBasedKotlinManglerImpl) : AbstractKotlinMangler<IrDeclaration>(),
@@ -45,31 +37,26 @@ class Ir2DescriptorManglerAdapter(private val delegate: DescriptorBasedKotlinMan
override val manglerName: String override val manglerName: String
get() = delegate.manglerName 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) { return when (this) {
is IrAnonymousInitializer -> false is IrEnumEntry -> delegate.run { descriptor.mangleEnumEntryString() }
is IrEnumEntry -> delegate.run { descriptor.isExportEnumEntry() } is IrField -> delegate.run { descriptor.mangleFieldString() }
is IrField -> delegate.run { descriptor.isExportField() } else -> delegate.run { descriptor.mangleString() }
else -> delegate.run { descriptor.isExported() }
} }
} }
override val IrDeclaration.mangleString: String override fun IrDeclaration.signatureString(): String = delegate.run { descriptor.signatureString() }
get() {
return when (this) {
is IrEnumEntry -> delegate.run { descriptor.mangleEnumEntryString() }
is IrField -> delegate.run { descriptor.mangleFieldString() }
else -> delegate.run { descriptor.mangleString }
}
}
override val IrDeclaration.signatureString: String override fun IrDeclaration.fqnString(): String = delegate.run { descriptor.fqnString() }
get() = delegate.run { descriptor.signatureString }
override val IrDeclaration.fqnString: String override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> =
get() = delegate.run { descriptor.fqnString } error("Should not have been reached")
override fun getExportChecker() = error("Should not have been reached") override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<IrDeclaration> {
error("Should not be called")
override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> = error("Should not have been reached") }
} }
@@ -12,14 +12,13 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
abstract class IrBasedKotlinManglerImpl : AbstractKotlinMangler<IrDeclaration>(), KotlinMangler.IrMangler { abstract class IrBasedKotlinManglerImpl : AbstractKotlinMangler<IrDeclaration>(), KotlinMangler.IrMangler {
override val IrDeclaration.mangleString: String
get() = getMangleComputer(MangleMode.FULL).computeMangle(this)
override val IrDeclaration.signatureString: String override fun IrDeclaration.mangleString(): String = getMangleComputer(MangleMode.FULL).computeMangle(this)
get() = getMangleComputer(MangleMode.SIGNATURE).computeMangle(this)
override val IrDeclaration.fqnString: String override fun IrDeclaration.signatureString(): String = getMangleComputer(MangleMode.SIGNATURE).computeMangle(this)
get() = getMangleComputer(MangleMode.FQNAME).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)
} }
@@ -23,15 +23,23 @@ import org.jetbrains.kotlin.name.SpecialNames
abstract class IrExportCheckerVisitor(private val compatibleMode: Boolean) : KotlinExportChecker<IrDeclaration> { abstract class IrExportCheckerVisitor(private val compatibleMode: Boolean) : KotlinExportChecker<IrDeclaration> {
private val compatibleChecker = CompatibleChecker() 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 { 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 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 { override fun visitElement(element: IrElement, data: Nothing?): Boolean {
error("Should bot reach here ${element.render()}") 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 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 inner class CompatibleChecker : IrElementVisitor<Boolean, Nothing?> {
private fun IrDeclaration.isExported(annotations: List<IrConstructorCall>, visibility: DescriptorVisibility?): Boolean { private fun IrDeclaration.isExported(annotations: List<IrConstructorCall>, visibility: DescriptorVisibility?): Boolean {
val speciallyExported = annotations.hasAnnotation(publishedApiAnnotation) || isPlatformSpecificExported() val speciallyExported = annotations.hasAnnotation(publishedApiAnnotation) || isPlatformSpecificExported()
@@ -105,7 +105,8 @@ fun generateKLib(
irFactory: IrFactory, irFactory: IrFactory,
outputKlibPath: String, outputKlibPath: String,
nopack: Boolean, nopack: Boolean,
jsOutputName: String?, abiVersion: KotlinAbiVersion = KotlinAbiVersion.CURRENT,
jsOutputName: String?
) { ) {
val incrementalDataProvider = configuration.get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER) val incrementalDataProvider = configuration.get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER)
val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT
@@ -196,6 +197,7 @@ fun generateKLib(
nopack, nopack,
perFile = false, perFile = false,
hasErrors, hasErrors,
abiVersion,
jsOutputName jsOutputName
) )
} }
@@ -495,15 +497,19 @@ fun serializeModuleIntoKlib(
nopack: Boolean, nopack: Boolean,
perFile: Boolean, perFile: Boolean,
containsErrorCode: Boolean = false, containsErrorCode: Boolean = false,
abiVersion: KotlinAbiVersion,
jsOutputName: String?, jsOutputName: String?,
) { ) {
assert(files.size == moduleFragment.files.size) assert(files.size == moduleFragment.files.size)
val compatibilityMode = CompatibilityMode(abiVersion)
val serializedIr = val serializedIr =
JsIrModuleSerializer( JsIrModuleSerializer(
messageLogger, messageLogger,
moduleFragment.irBuiltins, moduleFragment.irBuiltins,
expectDescriptorToSymbol = expectDescriptorToSymbol, expectDescriptorToSymbol,
compatibilityMode,
skipExpects = !configuration.expectActualLinker skipExpects = !configuration.expectActualLinker
).serializedIrModule(moduleFragment) ).serializedIrModule(moduleFragment)
@@ -559,7 +565,7 @@ fun serializeModuleIntoKlib(
val fullSerializedIr = SerializedIrModule(compiledKotlinFiles.map { it.irData }) val fullSerializedIr = SerializedIrModule(compiledKotlinFiles.map { it.irData })
val versions = KotlinLibraryVersioning( val versions = KotlinLibraryVersioning(
abiVersion = KotlinAbiVersion.CURRENT, abiVersion = compatibilityMode.abiVersion,
libraryVersion = null, libraryVersion = null,
compilerVersion = KotlinCompilerVersion.VERSION, compilerVersion = KotlinCompilerVersion.VERSION,
metadataVersion = KlibMetadataVersion.INSTANCE.toString(), metadataVersion = KlibMetadataVersion.INSTANCE.toString(),
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.serialization.IdSignatureClashTracker
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
import org.jetbrains.kotlin.backend.common.serialization.signature.PublicIdSignatureComputer import org.jetbrains.kotlin.backend.common.serialization.signature.PublicIdSignatureComputer
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -19,6 +20,7 @@ class JsIrFileSerializer(
messageLogger: IrMessageLogger, messageLogger: IrMessageLogger,
declarationTable: DeclarationTable, declarationTable: DeclarationTable,
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
compatibilityMode: CompatibilityMode,
skipExpects: Boolean, skipExpects: Boolean,
bodiesOnlyForInlines: Boolean = false, bodiesOnlyForInlines: Boolean = false,
icMode: Boolean = false, icMode: Boolean = false,
@@ -26,6 +28,7 @@ class JsIrFileSerializer(
messageLogger, messageLogger,
declarationTable, declarationTable,
expectDescriptorToSymbol, expectDescriptorToSymbol,
compatibilityMode,
bodiesOnlyForInlines = bodiesOnlyForInlines, bodiesOnlyForInlines = bodiesOnlyForInlines,
skipExpects = skipExpects, skipExpects = skipExpects,
skipMutableState = icMode, skipMutableState = icMode,
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.containsErrorCode import org.jetbrains.kotlin.library.containsErrorCode
@@ -37,17 +38,19 @@ class JsIrLinker(
private val IrLibrary.libContainsErrorCode: Boolean private val IrLibrary.libContainsErrorCode: Boolean
get() = this is KotlinLibrary && this.containsErrorCode get() = this is KotlinLibrary && this.containsErrorCode
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer = override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: KotlinLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer = klib?.let { lib ->
JsModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy, klib.libContainsErrorCode) JsModuleDeserializer(moduleDescriptor, lib, strategy, lib.versions.abiVersion ?: KotlinAbiVersion.CURRENT, lib.libContainsErrorCode)
} ?: error("Expecting kotlin library")
private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy, allowErrorCode: Boolean) :
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategy, allowErrorCode) private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy, libraryAbiVersion: KotlinAbiVersion, allowErrorCode: Boolean) :
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategy, libraryAbiVersion, allowErrorCode)
override fun createCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection<IrModuleDeserializer>): IrModuleDeserializer { override fun createCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection<IrModuleDeserializer>): IrModuleDeserializer {
val currentModuleDeserializer = super.createCurrentModuleDeserializer(moduleFragment, dependencies) val currentModuleDeserializer = super.createCurrentModuleDeserializer(moduleFragment, dependencies)
icData?.let { icData?.let {
return CurrentModuleWithICDeserializer(currentModuleDeserializer, symbolTable, builtIns, it.icData) { lib -> return CurrentModuleWithICDeserializer(currentModuleDeserializer, symbolTable, builtIns, it.icData) { lib ->
JsModuleDeserializer(currentModuleDeserializer.moduleDescriptor, lib, currentModuleDeserializer.strategy, it.containsErrorCode) JsModuleDeserializer(currentModuleDeserializer.moduleDescriptor, lib, currentModuleDeserializer.strategy, KotlinAbiVersion.CURRENT, it.containsErrorCode)
} }
} }
return currentModuleDeserializer return currentModuleDeserializer
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.IrModuleSerializer import org.jetbrains.kotlin.backend.common.serialization.IrModuleSerializer
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
@@ -19,11 +20,12 @@ class JsIrModuleSerializer(
messageLogger: IrMessageLogger, messageLogger: IrMessageLogger,
irBuiltIns: IrBuiltIns, irBuiltIns: IrBuiltIns,
private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
compatibilityMode: CompatibilityMode,
val skipExpects: Boolean val skipExpects: Boolean
) : IrModuleSerializer<JsIrFileSerializer>(messageLogger) { ) : IrModuleSerializer<JsIrFileSerializer>(messageLogger, compatibilityMode) {
private val globalDeclarationTable = JsGlobalDeclarationTable(irBuiltIns) private val globalDeclarationTable = JsGlobalDeclarationTable(irBuiltIns)
override fun createSerializerForFile(file: IrFile): JsIrFileSerializer = override fun createSerializerForFile(file: IrFile): JsIrFileSerializer =
JsIrFileSerializer(messageLogger, DeclarationTable(globalDeclarationTable), expectDescriptorToSymbol, skipExpects = skipExpects) JsIrFileSerializer(messageLogger, DeclarationTable(globalDeclarationTable), expectDescriptorToSymbol, skipExpects = skipExpects, compatibilityMode = compatibilityMode)
} }
@@ -19,11 +19,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclaration
abstract class AbstractJsManglerIr : IrBasedKotlinManglerImpl() { abstract class AbstractJsManglerIr : IrBasedKotlinManglerImpl() {
companion object { private class JsIrExportChecker(compatibleMode: Boolean) : IrExportCheckerVisitor(compatibleMode) {
private val exportChecker = JsIrExportChecker()
}
private class JsIrExportChecker : IrExportCheckerVisitor() {
override fun IrDeclaration.isPlatformSpecificExported() = false override fun IrDeclaration.isPlatformSpecificExported() = false
} }
@@ -31,7 +27,7 @@ abstract class AbstractJsManglerIr : IrBasedKotlinManglerImpl() {
override fun copy(newMode: MangleMode): IrMangleComputer = JsIrManglerComputer(builder, newMode) override fun copy(newMode: MangleMode): IrMangleComputer = JsIrManglerComputer(builder, newMode)
} }
override fun getExportChecker(): KotlinExportChecker<IrDeclaration> = exportChecker override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<IrDeclaration> = JsIrExportChecker(compatibleMode)
override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> { override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> {
return JsIrManglerComputer(StringBuilder(256), mode) return JsIrManglerComputer(StringBuilder(256), mode)
@@ -54,7 +50,7 @@ abstract class AbstractJsDescriptorMangler : DescriptorBasedKotlinManglerImpl()
override fun copy(newMode: MangleMode): DescriptorMangleComputer = JsDescriptorManglerComputer(builder, newMode) override fun copy(newMode: MangleMode): DescriptorMangleComputer = JsDescriptorManglerComputer(builder, newMode)
} }
override fun getExportChecker(): KotlinExportChecker<DeclarationDescriptor> = exportChecker override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<DeclarationDescriptor> = exportChecker
override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<DeclarationDescriptor> { override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<DeclarationDescriptor> {
return JsDescriptorManglerComputer(StringBuilder(256), mode) return JsDescriptorManglerComputer(StringBuilder(256), mode)
@@ -21,12 +21,13 @@ import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol 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.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.IrLibrary 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.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment
@@ -52,17 +53,17 @@ class JvmIrLinker(
moduleDescriptor.name.asString().startsWith("<dependencies of ") moduleDescriptor.name.asString().startsWith("<dependencies of ")
// TODO: implement special Java deserializer // 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) { if (klib != null) {
assert(moduleDescriptor.getCapability(KlibModuleOrigin.CAPABILITY) != 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()) return MetadataJVMModuleDeserializer(moduleDescriptor, emptyList())
} }
private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy) : private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, libraryAbiVersion: KotlinAbiVersion, strategy: DeserializationStrategy) :
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategy) BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategy, libraryAbiVersion)
private fun DeclarationDescriptor.isJavaDescriptor(): Boolean { private fun DeclarationDescriptor.isJavaDescriptor(): Boolean {
if (this is PackageFragmentDescriptor) { if (this is PackageFragmentDescriptor) {
@@ -122,7 +123,7 @@ class JvmIrLinker(
} }
private inner class MetadataJVMModuleDeserializer(moduleDescriptor: ModuleDescriptor, dependencies: List<IrModuleDeserializer>) : 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 // TODO: implement proper check whether `idSig` belongs to this module
override fun contains(idSig: IdSignature): Boolean = true override fun contains(idSig: IdSignature): Boolean = true
@@ -28,11 +28,7 @@ import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField
abstract class AbstractJvmManglerIr : IrBasedKotlinManglerImpl() { abstract class AbstractJvmManglerIr : IrBasedKotlinManglerImpl() {
companion object { private class JvmIrExportChecker(compatibleMode: Boolean) : IrExportCheckerVisitor(compatibleMode) {
private val exportChecker = JvmIrExportChecker()
}
private class JvmIrExportChecker : IrExportCheckerVisitor() {
override fun IrDeclaration.isPlatformSpecificExported() = false override fun IrDeclaration.isPlatformSpecificExported() = false
} }
@@ -44,7 +40,7 @@ abstract class AbstractJvmManglerIr : IrBasedKotlinManglerImpl() {
irFunction.isFromJava() irFunction.isFromJava()
} }
override fun getExportChecker(): KotlinExportChecker<IrDeclaration> = exportChecker override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<IrDeclaration> = JvmIrExportChecker(compatibleMode)
override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> { override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<IrDeclaration> {
return JvmIrManglerComputer(StringBuilder(256), mode) return JvmIrManglerComputer(StringBuilder(256), mode)
@@ -71,8 +67,7 @@ abstract class AbstractJvmDescriptorMangler(private val mainDetector: MainFuncti
override fun addReturnTypeSpecialCase(functionDescriptor: FunctionDescriptor): Boolean = override fun addReturnTypeSpecialCase(functionDescriptor: FunctionDescriptor): Boolean =
functionDescriptor is JavaMethodDescriptor functionDescriptor is JavaMethodDescriptor
override fun copy(newMode: MangleMode): DescriptorMangleComputer = override fun copy(newMode: MangleMode): DescriptorMangleComputer = JvmDescriptorManglerComputer(builder, mainDetector, newMode)
JvmDescriptorManglerComputer(builder, mainDetector, newMode)
private fun isMainFunction(descriptor: FunctionDescriptor): Boolean = mainDetector?.isMain(descriptor) ?: false 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 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> { override fun getMangleComputer(mode: MangleMode): KotlinMangleComputer<DeclarationDescriptor> {
return JvmDescriptorManglerComputer(StringBuilder(256), mainDetector, mode) return JvmDescriptorManglerComputer(StringBuilder(256), mainDetector, mode)
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import junit.framework.TestCase import junit.framework.TestCase
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataIncrementalSerializer import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataIncrementalSerializer
@@ -134,7 +135,7 @@ abstract class AbstractKlibTextTestCase : CodegenTestCase() {
protected fun serializeModule(irModuleFragment: IrModuleFragment, bindingContext: BindingContext, stdlib: KotlinLibrary, containsErrorCode: Boolean, expectActualSymbols: MutableMap<DeclarationDescriptor, IrSymbol>, skipExpect: Boolean): String { protected fun serializeModule(irModuleFragment: IrModuleFragment, bindingContext: BindingContext, stdlib: KotlinLibrary, containsErrorCode: Boolean, expectActualSymbols: MutableMap<DeclarationDescriptor, IrSymbol>, skipExpect: Boolean): String {
val ktFiles = myFiles.psiFiles val ktFiles = myFiles.psiFiles
val serializedIr = val serializedIr =
JsIrModuleSerializer(IrMessageLogger.None, irModuleFragment.irBuiltins, expectActualSymbols, skipExpect).serializedIrModule( JsIrModuleSerializer(IrMessageLogger.None, irModuleFragment.irBuiltins, expectActualSymbols, CompatibilityMode.CURRENT, skipExpect).serializedIrModule(
irModuleFragment irModuleFragment
) )
@@ -14,6 +14,7 @@ import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
@@ -492,6 +493,7 @@ class GenerateIrRuntime {
emptyList(), emptyList(),
true, true,
perFile, perFile,
abiVersion = KotlinAbiVersion.CURRENT,
jsOutputName = null jsOutputName = null
) )
@@ -506,7 +508,7 @@ class GenerateIrRuntime {
private fun doSerializeIrModule(module: IrModuleFragment): SerializedIrModule { private fun doSerializeIrModule(module: IrModuleFragment): SerializedIrModule {
val serializedIr = JsIrModuleSerializer(IrMessageLogger.None, module.irBuiltins, mutableMapOf(), true).serializedIrModule(module) val serializedIr = JsIrModuleSerializer(IrMessageLogger.None, module.irBuiltins, mutableMapOf(), CompatibilityMode.CURRENT, true).serializedIrModule(module)
return serializedIr return serializedIr
} }
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.backend.common.IrValidator
import org.jetbrains.kotlin.backend.common.IrValidatorConfig import org.jetbrains.kotlin.backend.common.IrValidatorConfig
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.* 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.common.serialization.metadata.KlibMetadataMonolithicSerializer
import org.jetbrains.kotlin.backend.konan.MemoryModel import org.jetbrains.kotlin.backend.konan.MemoryModel
import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.llvm.*
@@ -155,7 +156,7 @@ internal val serializerPhase = konanUnitPhase(
serializedIr = irModule?.let { ir -> serializedIr = irModule?.let { ir ->
KonanIrModuleSerializer( KonanIrModuleSerializer(
messageLogger, ir.irBuiltins, expectDescriptorToSymbol, skipExpects = !expectActualLinker messageLogger, ir.irBuiltins, expectDescriptorToSymbol, skipExpects = !expectActualLinker, compatibilityMode = CompatibilityMode.CURRENT
).serializedIrModule(ir) ).serializedIrModule(ir)
} }
@@ -34,9 +34,9 @@ import org.jetbrains.kotlin.name.Name
object KonanBinaryInterface { object KonanBinaryInterface {
private val mangler = object : AbstractKonanIrMangler(true) {} 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 IrFunction.symbolName: String get() = funSymbolNameImpl()
val IrField.symbolName: String get() = val IrField.symbolName: String get() =
@@ -65,7 +65,7 @@ object KonanBinaryInterface {
return name // no wrapping currently required 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 { private fun IrField.fieldSymbolNameImpl(): String {
@@ -1,5 +1,6 @@
package org.jetbrains.kotlin.backend.konan.serialization 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.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer
import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.backend.konan.RuntimeNames
@@ -16,8 +17,9 @@ class KonanIrFileSerializer(
declarationTable: DeclarationTable, declarationTable: DeclarationTable,
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
skipExpects: Boolean, skipExpects: Boolean,
bodiesOnlyForInlines: Boolean = false bodiesOnlyForInlines: Boolean = false,
): IrFileSerializer(messageLogger, declarationTable, expectDescriptorToSymbol, skipExpects = skipExpects, bodiesOnlyForInlines = bodiesOnlyForInlines) { compatibilityMode: CompatibilityMode
): IrFileSerializer(messageLogger, declarationTable, expectDescriptorToSymbol, compatibilityMode, bodiesOnlyForInlines, skipExpects) {
override fun backendSpecificExplicitRoot(node: IrAnnotationContainer): Boolean { override fun backendSpecificExplicitRoot(node: IrAnnotationContainer): Boolean {
val fqn = when (node) { val fqn = when (node) {
@@ -1,6 +1,7 @@
package org.jetbrains.kotlin.backend.konan.serialization 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.common.serialization.signature.IdSignatureSerializer
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -13,8 +14,9 @@ class KonanIrModuleSerializer(
messageLogger: IrMessageLogger, messageLogger: IrMessageLogger,
irBuiltIns: IrBuiltIns, irBuiltIns: IrBuiltIns,
private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
val skipExpects: Boolean val skipExpects: Boolean,
) : IrModuleSerializer<KonanIrFileSerializer>(messageLogger) { compatibilityMode: CompatibilityMode
) : IrModuleSerializer<KonanIrFileSerializer>(messageLogger, compatibilityMode) {
private val globalDeclarationTable = KonanGlobalDeclarationTable(irBuiltIns) private val globalDeclarationTable = KonanGlobalDeclarationTable(irBuiltIns)
@@ -28,5 +30,5 @@ class KonanIrModuleSerializer(
file.fileEntry.name != IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName file.fileEntry.name != IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName
override fun createSerializerForFile(file: IrFile): KonanIrFileSerializer = 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.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor 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.library.KotlinLibrary
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -93,16 +93,16 @@ internal class KonanIrLinker(
private val forwardDeclarationDeserializer = forwardModuleDescriptor?.let { KonanForwardDeclarationModuleDeserializer(it) } private val forwardDeclarationDeserializer = forwardModuleDescriptor?.let { KonanForwardDeclarationModuleDeserializer(it) }
override val fakeOverrideBuilder = FakeOverrideBuilder(this, symbolTable, KonanManglerIr, builtIns, KonanFakeOverrideClassFilter) 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) { if (moduleDescriptor === forwardModuleDescriptor) {
return forwardDeclarationDeserializer ?: error("forward declaration deserializer expected") 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. // See https://youtrack.jetbrains.com/issue/KT-43517.
// Disabling this flag forces linker to generate IR. // Disabling this flag forces linker to generate IR.
val isCached = false //cachedLibraries.isLibraryCached(klib) val isCached = false //cachedLibraries.isLibraryCached(klib)
return KonanInteropModuleDeserializer(moduleDescriptor, isCached) return KonanInteropModuleDeserializer(moduleDescriptor, klib, isCached)
} }
return KonanModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy) return KonanModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy)
@@ -110,16 +110,17 @@ internal class KonanIrLinker(
private inner class KonanModuleDeserializer( private inner class KonanModuleDeserializer(
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
klib: IrLibrary, klib: KotlinLibrary,
strategy: DeserializationStrategy 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()) override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList())
} }
private inner class KonanInteropModuleDeserializer( private inner class KonanInteropModuleDeserializer(
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
klib: KotlinLibrary,
private val isLibraryCached: Boolean private val isLibraryCached: Boolean
) : IrModuleDeserializer(moduleDescriptor) { ) : IrModuleDeserializer(moduleDescriptor, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT) {
init { init {
assert(moduleDescriptor.kotlinLibrary.isInteropLibrary()) assert(moduleDescriptor.kotlinLibrary.isInteropLibrary())
} }
@@ -170,7 +171,7 @@ internal class KonanIrLinker(
override val moduleDependencies: Collection<IrModuleDeserializer> = listOfNotNull(forwardDeclarationDeserializer) 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 { init {
assert(moduleDescriptor.isForwardDeclarationModule) assert(moduleDescriptor.isForwardDeclarationModule)
} }
@@ -1,5 +1,6 @@
package org.jetbrains.kotlin.backend.konan.serialization 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.MangleMode
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorBasedKotlinManglerImpl import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorBasedKotlinManglerImpl
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorExportCheckerVisitor 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.declarations.*
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.types.KotlinType
abstract class AbstractKonanIrMangler(private val withReturnType: Boolean) : IrBasedKotlinManglerImpl() { 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 = override fun getMangleComputer(mode: MangleMode): IrMangleComputer = KonanIrManglerComputer(StringBuilder(256), mode, withReturnType)
KonanIrManglerComputer(StringBuilder(256), mode, withReturnType)
private class KonanIrExportChecker : IrExportCheckerVisitor() { override fun IrDeclaration.isPlatformSpecificExport(): Boolean {
override fun IrDeclaration.isPlatformSpecificExported(): Boolean { if (this is IrSimpleFunction) if (isFakeOverride) return false
if (this is IrSimpleFunction) if (isFakeOverride) return false
// TODO: revise // TODO: revise
if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) { if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) {
// Treat any `@SymbolName` declaration as exported. // Treat any `@SymbolName` declaration as exported.
return true return true
} }
if (annotations.hasAnnotation(KonanFqNames.gcUnsafeCall)) { if (annotations.hasAnnotation(KonanFqNames.gcUnsafeCall)) {
// Treat any `@GCUnsafeCall` declaration as exported. // Treat any `@GCUnsafeCall` declaration as exported.
return true return true
} }
if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) { if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) {
// Treat any `@ExportForCppRuntime` declaration as exported. // Treat any `@ExportForCppRuntime` declaration as exported.
return true return true
}
if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) {
// Treat `@CName` declaration as exported.
return true
}
if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) {
return true
}
return false
} }
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) { 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) object KonanManglerIr : AbstractKonanIrMangler(false)
abstract class AbstractKonanDescriptorMangler : DescriptorBasedKotlinManglerImpl() { abstract class AbstractKonanDescriptorMangler : DescriptorBasedKotlinManglerImpl() {
override fun getExportChecker(): DescriptorExportCheckerVisitor = KonanDescriptorExportChecker() override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<DeclarationDescriptor> = KonanDescriptorExportChecker()
override fun getMangleComputer(mode: MangleMode): DescriptorMangleComputer = override fun getMangleComputer(mode: MangleMode): DescriptorMangleComputer = KonanDescriptorMangleComputer(StringBuilder(256), mode)
KonanDescriptorMangleComputer(StringBuilder(256), mode)
private class KonanDescriptorExportChecker : DescriptorExportCheckerVisitor() { private inner class KonanDescriptorExportChecker : DescriptorExportCheckerVisitor() {
override fun DeclarationDescriptor.isPlatformSpecificExported(): Boolean { override fun DeclarationDescriptor.isPlatformSpecificExported(): Boolean = isPlatformSpecificExport()
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 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) { private class KonanDescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) : DescriptorMangleComputer(builder, mode) {