[Native][IR] Partial linkage support for cached inline functions
- Support partial linkage for declarations from inline functions that are lazily deserialized from a KLIB with static cache - Linker API: Split IrModuleDeserializer.deserializeIrSymbol() into deserializeIrSymbolOrFail() and tryDeserializeIrSymbol() - Linker API: Refactor KotlinIrLinker.handleSignatureIdNotFoundInModuleWithDependencies() to deserializeOrReturnUnboundIrSymbolIfPartialLinkageEnabled() ^KT-52478
This commit is contained in:
@@ -13,6 +13,7 @@ dependencies {
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
|
||||
compileOnly(intellijCore())
|
||||
compileOnly(commonDependency("org.jetbrains.intellij.deps:trove4j"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
+4
-4
@@ -97,7 +97,7 @@ abstract class BasicIrModuleDeserializer(
|
||||
// TODO: fix to topLevel checker
|
||||
override fun contains(idSig: IdSignature): Boolean = idSig in moduleReversedFileIndex
|
||||
|
||||
open fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
|
||||
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
|
||||
val topLevelSignature = idSig.topLevelSignature()
|
||||
val fileLocalDeserializationState = moduleReversedFileIndex[topLevelSignature] ?: return null
|
||||
|
||||
@@ -107,9 +107,9 @@ abstract class BasicIrModuleDeserializer(
|
||||
return fileLocalDeserializationState.fileDeserializer.symbolDeserializer.deserializeIrSymbol(idSig, symbolKind)
|
||||
}
|
||||
|
||||
final override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind) =
|
||||
tryDeserializeIrSymbol(idSig, symbolKind)
|
||||
?: error("No file for ${idSig.topLevelSignature()} (@ $idSig) in module $moduleDescriptor")
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing {
|
||||
error("No file for ${idSig.topLevelSignature()} (@ $idSig) in module $moduleDescriptor")
|
||||
}
|
||||
|
||||
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, linker.builtIns, emptyList())
|
||||
|
||||
|
||||
+5
-3
@@ -113,14 +113,16 @@ class CurrentModuleWithICDeserializer(
|
||||
return idSig in dirtyDeclarations || idSig.topLevelSignature() in icDeserializer || idSig in delegate
|
||||
}
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
dirtyDeclarations[idSig]?.let { return it }
|
||||
|
||||
if (idSig.topLevelSignature() in icDeserializer) return icDeserializer.deserializeIrSymbol(idSig, symbolKind)
|
||||
if (idSig.topLevelSignature() in icDeserializer) return icDeserializer.deserializeIrSymbolOrFail(idSig, symbolKind)
|
||||
|
||||
return delegate.deserializeIrSymbol(idSig, symbolKind)
|
||||
return delegate.deserializeIrSymbolOrFail(idSig, symbolKind)
|
||||
}
|
||||
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = delegate.deserializedSymbolNotFound(idSig)
|
||||
|
||||
override fun addModuleReachableTopLevel(idSig: IdSignature) {
|
||||
assert(idSig in icDeserializer)
|
||||
icDeserializer.addModuleReachableTopLevel(idSig)
|
||||
|
||||
+2
-12
@@ -74,18 +74,8 @@ class FileDeserializationState(
|
||||
::addIdSignature,
|
||||
linker::handleExpectActualMapping,
|
||||
symbolProcessor = linker.symbolProcessor,
|
||||
) { idSig, symbolKind ->
|
||||
|
||||
val topLevelSig = idSig.topLevelSignature()
|
||||
val actualModuleDeserializer = moduleDeserializer.findModuleDeserializerForTopLevelId(topLevelSig)
|
||||
?: run {
|
||||
// The symbol might be gone in newer version of dependency KLIB. Then the KLIB that was compiled against
|
||||
// the older version of dependency KLIB will still have a reference to non-existing symbol. And the linker will have to
|
||||
// handle such situation appropriately. See KT-41378.
|
||||
linker.handleSignatureIdNotFoundInModuleWithDependencies(idSig, moduleDeserializer)
|
||||
}
|
||||
|
||||
actualModuleDeserializer.deserializeIrSymbol(idSig, symbolKind)
|
||||
) { idSignature, symbolKind ->
|
||||
linker.deserializeOrReturnUnboundIrSymbolIfPartialLinkageEnabled(idSignature, symbolKind, moduleDeserializer)
|
||||
}
|
||||
|
||||
val declarationDeserializer = IrDeclarationDeserializer(
|
||||
|
||||
+15
-8
@@ -58,7 +58,8 @@ enum class IrModuleDeserializerKind {
|
||||
|
||||
abstract class IrModuleDeserializer(private val _moduleDescriptor: ModuleDescriptor?, val libraryAbiVersion: KotlinAbiVersion) {
|
||||
abstract operator fun contains(idSig: IdSignature): Boolean
|
||||
abstract fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol
|
||||
abstract fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol?
|
||||
abstract fun deserializedSymbolNotFound(idSig: IdSignature): Nothing
|
||||
|
||||
val moduleDescriptor: ModuleDescriptor get() = _moduleDescriptor ?: error("No ModuleDescriptor provided")
|
||||
|
||||
@@ -72,7 +73,7 @@ abstract class IrModuleDeserializer(private val _moduleDescriptor: ModuleDescrip
|
||||
val signature = symbol.signature
|
||||
require(signature != null) { "Symbol is not public API: ${symbol.descriptor}" }
|
||||
assert(symbol.hasDescriptor)
|
||||
deserializeIrSymbol(signature, symbol.kind())
|
||||
deserializeIrSymbolOrFail(signature, symbol.kind())
|
||||
}
|
||||
|
||||
open val klib: IrLibrary get() = error("Unsupported operation")
|
||||
@@ -104,6 +105,9 @@ abstract class IrModuleDeserializer(private val _moduleDescriptor: ModuleDescrip
|
||||
open fun signatureDeserializerForFile(fileName: String): IdSignatureDeserializer = error("Unsupported")
|
||||
}
|
||||
|
||||
fun IrModuleDeserializer.deserializeIrSymbolOrFail(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol =
|
||||
tryDeserializeIrSymbol(idSig, symbolKind) ?: deserializedSymbolNotFound(idSig)
|
||||
|
||||
// Used to resolve built in symbols like `kotlin.ir.internal.*` or `kotlin.FunctionN`
|
||||
class IrModuleDeserializerWithBuiltIns(
|
||||
private val builtIns: IrBuiltIns,
|
||||
@@ -199,16 +203,17 @@ class IrModuleDeserializerWithBuiltIns(
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
|
||||
irBuiltInsMap[idSig]?.let { return it }
|
||||
|
||||
val topLevel = idSig.topLevelSignature()
|
||||
|
||||
if (checkIsFunctionInterface(topLevel)) return resolveFunctionalInterface(idSig, symbolKind)
|
||||
|
||||
return delegate.deserializeIrSymbol(idSig, symbolKind)
|
||||
return delegate.tryDeserializeIrSymbol(idSig, symbolKind)
|
||||
}
|
||||
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = delegate.deserializedSymbolNotFound(idSig)
|
||||
|
||||
override fun declareIrSymbol(symbol: IrSymbol) {
|
||||
val signature = symbol.signature
|
||||
if (signature != null && checkIsFunctionInterface(signature))
|
||||
@@ -253,11 +258,13 @@ open class CurrentModuleDeserializer(
|
||||
) : IrModuleDeserializer(moduleFragment.descriptor, KotlinAbiVersion.CURRENT) {
|
||||
override fun contains(idSig: IdSignature): Boolean = false // TODO:
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): Nothing =
|
||||
error("Unreachable execution: there could not be back-links (sig: $idSig)")
|
||||
}
|
||||
|
||||
override fun declareIrSymbol(symbol: IrSymbol) {}
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing =
|
||||
error("Unreachable execution: there could not be back-links (sig: $idSig)")
|
||||
|
||||
override fun declareIrSymbol(symbol: IrSymbol) = Unit
|
||||
|
||||
override val kind get() = IrModuleDeserializerKind.CURRENT
|
||||
}
|
||||
|
||||
+29
-112
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
|
||||
import org.jetbrains.kotlin.backend.common.overrides.FileLocalAwareLinker
|
||||
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
|
||||
import org.jetbrains.kotlin.backend.common.serialization.linkerissues.*
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsProcessor
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
@@ -19,14 +18,7 @@ import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.uniqueName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -59,34 +51,36 @@ abstract class KotlinIrLinker(
|
||||
|
||||
private lateinit var linkerExtensions: Collection<IrDeserializer.IrLinkerExtension>
|
||||
|
||||
protected open val unlinkedDeclarationsSupport: UnlinkedDeclarationsSupport = UnlinkedDeclarationsSupport.DISABLED
|
||||
protected open val userVisibleIrModulesSupport: UserVisibleIrModulesSupport = UserVisibleIrModulesSupport.DEFAULT
|
||||
protected open val unlinkedDeclarationsSupport: UnlinkedDeclarationsSupport get() = UnlinkedDeclarationsSupport.DISABLED
|
||||
protected open val userVisibleIrModulesSupport: UserVisibleIrModulesSupport get() = UserVisibleIrModulesSupport.DEFAULT
|
||||
|
||||
fun handleSignatureIdNotFoundInModuleWithDependencies(
|
||||
fun deserializeOrReturnUnboundIrSymbolIfPartialLinkageEnabled(
|
||||
idSignature: IdSignature,
|
||||
symbolKind: BinarySymbolData.SymbolKind,
|
||||
moduleDeserializer: IrModuleDeserializer
|
||||
): IrModuleDeserializer {
|
||||
if (unlinkedDeclarationsSupport.allowUnboundSymbols) {
|
||||
return object : IrModuleDeserializer(null, KotlinAbiVersion.CURRENT) {
|
||||
override fun contains(idSig: IdSignature): Boolean = false
|
||||
): IrSymbol {
|
||||
val topLevelSignature: IdSignature = idSignature.topLevelSignature()
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
return referenceDeserializedSymbol(symbolTable, null, symbolKind, idSig)
|
||||
}
|
||||
// Note: The top-level symbol might be gone in newer version of dependency KLIB. Then the KLIB that was compiled against
|
||||
// the older version of dependency KLIB will still have a reference to non-existing symbol. And the linker will have to
|
||||
// handle such situation appropriately. See KT-41378.
|
||||
val actualModuleDeserializer: IrModuleDeserializer? = moduleDeserializer.findModuleDeserializerForTopLevelId(topLevelSignature)
|
||||
|
||||
override val moduleFragment: IrModuleFragment
|
||||
get() = TODO("Not yet implemented")
|
||||
override val moduleDependencies: Collection<IrModuleDeserializer> get() = emptyList()
|
||||
override val kind: IrModuleDeserializerKind
|
||||
get() = TODO("Not yet implemented")
|
||||
}
|
||||
} else {
|
||||
throw SignatureIdNotFoundInModuleWithDependencies(
|
||||
idSignature = idSignature,
|
||||
problemModuleDeserializer = moduleDeserializer,
|
||||
allModuleDeserializers = deserializersForModules.values,
|
||||
userVisibleIrModulesSupport = userVisibleIrModulesSupport
|
||||
).raiseIssue(messageLogger)
|
||||
// Note: It might happen that the top-level symbol still exists in KLIB, but nested symbol has been removed.
|
||||
// Then the `actualModuleDeserializer` will be non-null, but `actualModuleDeserializer.tryDeserializeIrSymbol()` call
|
||||
// will return null.
|
||||
val symbol: IrSymbol? = actualModuleDeserializer?.tryDeserializeIrSymbol(idSignature, symbolKind)
|
||||
|
||||
return symbol ?: run {
|
||||
if (unlinkedDeclarationsSupport.allowUnboundSymbols)
|
||||
referenceDeserializedSymbol(symbolTable, null, symbolKind, idSignature)
|
||||
else
|
||||
throw SignatureIdNotFoundInModuleWithDependencies(
|
||||
idSignature = idSignature,
|
||||
problemModuleDeserializer = moduleDeserializer,
|
||||
allModuleDeserializers = deserializersForModules.values,
|
||||
userVisibleIrModulesSupport = userVisibleIrModulesSupport
|
||||
).raiseIssue(messageLogger)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,93 +215,16 @@ abstract class KotlinIrLinker(
|
||||
deserializersForModules.values.forEach { it.init() }
|
||||
}
|
||||
|
||||
|
||||
private fun markUnlinkedClassifiers(): Set<IrClassifierSymbol> {
|
||||
if (!unlinkedDeclarationsSupport.allowUnboundSymbols) return emptySet()
|
||||
val entries = fakeOverrideBuilder.fakeOverrideCandidates
|
||||
val result = mutableSetOf<IrClassifierSymbol>()
|
||||
|
||||
fun IrType.isUnlinked(visited: MutableSet<IrClassifierSymbol>): Boolean {
|
||||
val simpleType = this as? IrSimpleType ?: return this !is IrErrorType
|
||||
|
||||
val classifier = simpleType.classifier
|
||||
|
||||
if (!classifier.isBound) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (classifier in result) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!visited.add(classifier)) return false
|
||||
|
||||
val superTypes = when (val decl = classifier.owner) {
|
||||
is IrClass -> decl.superTypes
|
||||
is IrTypeParameter -> decl.superTypes
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
if (superTypes.any { it.isUnlinked(visited) }) {
|
||||
result.add(classifier)
|
||||
return true
|
||||
}
|
||||
|
||||
for (ta in simpleType.arguments) {
|
||||
if (ta is IrTypeProjection) {
|
||||
val projected = ta.type
|
||||
if (projected.isUnlinked(visited)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun IrClass.isUnlinked(visited: MutableSet<IrClassifierSymbol>): Boolean {
|
||||
if (symbol in result) return true
|
||||
for (s in superTypes) {
|
||||
if (s.isUnlinked(visited)) {
|
||||
result.add(symbol)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
val toRemove = mutableListOf<IrClass>()
|
||||
|
||||
for (e in entries) {
|
||||
val klass = e.key
|
||||
if (klass.isUnlinked(mutableSetOf())) {
|
||||
toRemove.add(klass)
|
||||
}
|
||||
}
|
||||
|
||||
toRemove.forEach { entries.remove(it) }
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun applyToModules(transformer: IrElementTransformerVoid) {
|
||||
deserializersForModules.values.forEach { it.moduleFragment.transformChildrenVoid(transformer) }
|
||||
}
|
||||
|
||||
override fun postProcess() {
|
||||
finalizeExpectActualLinker()
|
||||
|
||||
val unlinkedClassifiers = markUnlinkedClassifiers()
|
||||
unlinkedDeclarationsSupport.markUsedClassifiersExcludingUnlinkedFromFakeOverrideBuilding(fakeOverrideBuilder)
|
||||
|
||||
fakeOverrideBuilder.provideFakeOverrides()
|
||||
triedToDeserializeDeclarationForSymbol.clear()
|
||||
|
||||
unlinkedDeclarationsSupport.whenUnboundSymbolsAllowed { unlinkedMarkerTypeHandler ->
|
||||
val t = UnlinkedDeclarationsProcessor(builtIns, unlinkedClassifiers, unlinkedMarkerTypeHandler, messageLogger)
|
||||
t.addLinkageErrorIntoUnlinkedClasses()
|
||||
|
||||
applyToModules(t.signatureTransformer())
|
||||
applyToModules(t.usageTransformer())
|
||||
unlinkedDeclarationsSupport.processUnlinkedDeclarations(messageLogger) {
|
||||
deserializersForModules.values.map { it.moduleFragment }
|
||||
}
|
||||
|
||||
// TODO: fix IrPluginContext to make it not produce additional external reference
|
||||
@@ -359,7 +276,7 @@ abstract class KotlinIrLinker(
|
||||
?: error("No module for name '$moduleName' found")
|
||||
assert(signature == signature.topLevelSignature()) { "Signature '$signature' has to be top level" }
|
||||
if (signature !in moduleDeserializer) error("No signature $signature in module $moduleName")
|
||||
return moduleDeserializer.deserializeIrSymbol(signature, topLevelKindToSymbolKind(kind)).also {
|
||||
return moduleDeserializer.deserializeIrSymbolOrFail(signature, topLevelKindToSymbolKind(kind)).also {
|
||||
deserializeAllReachableTopLevels()
|
||||
}
|
||||
}
|
||||
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.unlinked
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UsedClassifierSymbolStatus.*
|
||||
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstantObject
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
abstract class BasicUnlinkedDeclarationsSupport : UnlinkedDeclarationsSupport {
|
||||
protected abstract val handler: UnlinkedDeclarationsSupport.UnlinkedMarkerTypeHandler
|
||||
protected abstract val builtIns: IrBuiltIns
|
||||
|
||||
private val usedClassifierSymbols = UsedClassifierSymbols()
|
||||
|
||||
final override fun markUsedClassifiersExcludingUnlinkedFromFakeOverrideBuilding(fakeOverrideBuilder: FakeOverrideBuilder) {
|
||||
if (!allowUnboundSymbols) return
|
||||
|
||||
val entries = fakeOverrideBuilder.fakeOverrideCandidates
|
||||
if (entries.isEmpty()) return
|
||||
|
||||
val toRemove = hashSetOf<IrClass>()
|
||||
for (clazz in entries.keys) {
|
||||
if (clazz.symbol.isUnlinkedClassifier(visited = hashSetOf())) {
|
||||
toRemove += clazz
|
||||
}
|
||||
}
|
||||
|
||||
entries -= toRemove
|
||||
}
|
||||
|
||||
private fun IrType.isUnlinkedType(visited: MutableSet<IrClassifierSymbol>): Boolean {
|
||||
val simpleType = this as? IrSimpleType ?: return this !is IrErrorType
|
||||
|
||||
if (simpleType.classifier.isUnlinkedClassifier(visited))
|
||||
return true
|
||||
|
||||
for (argument in simpleType.arguments) {
|
||||
if (argument is IrTypeProjection) {
|
||||
if (argument.type.isUnlinkedType(visited))
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun IrClassifierSymbol.isUnlinkedClassifier(visited: MutableSet<IrClassifierSymbol>): Boolean {
|
||||
when (val status = usedClassifierSymbols[this]) {
|
||||
UNLINKED, LINKED -> return status.isUnlinked
|
||||
null -> {
|
||||
// Unknown classifier. Continue.
|
||||
}
|
||||
}
|
||||
|
||||
if (!isBound || (hasDescriptor && descriptor is NotFoundClasses.MockClassDescriptor))
|
||||
return usedClassifierSymbols.register(this, UNLINKED)
|
||||
|
||||
if (!visited.add(this))
|
||||
return false // Recursion avoidance.
|
||||
|
||||
when (val classifier = owner) {
|
||||
is IrClass -> {
|
||||
if (classifier.parentClassOrNull?.symbol?.isUnlinkedClassifier(visited) == true)
|
||||
return usedClassifierSymbols.register(this, UNLINKED)
|
||||
|
||||
for (typeParameter in classifier.typeParameters) {
|
||||
if (typeParameter.superTypes.any { it.isUnlinkedType(visited) })
|
||||
return usedClassifierSymbols.register(this, UNLINKED)
|
||||
}
|
||||
|
||||
if (classifier.superTypes.any { it.isUnlinkedType(visited) })
|
||||
return usedClassifierSymbols.register(this, UNLINKED)
|
||||
}
|
||||
is IrTypeParameter -> {
|
||||
if (classifier.superTypes.any { it.isUnlinkedType(visited) })
|
||||
return usedClassifierSymbols.register(this, UNLINKED)
|
||||
}
|
||||
}
|
||||
|
||||
return usedClassifierSymbols.register(this, LINKED)
|
||||
}
|
||||
|
||||
override fun markUsedClassifiersInInlineLazyIrFunction(function: IrFunction) {
|
||||
if (!allowUnboundSymbols) return
|
||||
|
||||
function.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
fun visitType(type: IrType?) {
|
||||
type?.isUnlinkedType(visited = hashSetOf())
|
||||
}
|
||||
|
||||
override fun visitValueParameter(declaration: IrValueParameter) {
|
||||
visitType(declaration.type)
|
||||
super.visitValueParameter(declaration)
|
||||
}
|
||||
|
||||
override fun visitTypeParameter(declaration: IrTypeParameter) {
|
||||
declaration.superTypes.forEach(::visitType)
|
||||
super.visitTypeParameter(declaration)
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
visitType(declaration.returnType)
|
||||
super.visitFunction(declaration)
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
visitType(declaration.type)
|
||||
super.visitField(declaration)
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable) {
|
||||
visitType(declaration.type)
|
||||
super.visitVariable(declaration)
|
||||
}
|
||||
|
||||
override fun visitExpression(expression: IrExpression) {
|
||||
visitType(expression.type)
|
||||
super.visitExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitClassReference(expression: IrClassReference) {
|
||||
visitType(expression.classType)
|
||||
super.visitClassReference(expression)
|
||||
}
|
||||
|
||||
override fun visitConstantObject(expression: IrConstantObject) {
|
||||
expression.typeArguments.forEach(::visitType)
|
||||
super.visitConstantObject(expression)
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall) {
|
||||
visitType(expression.typeOperand)
|
||||
super.visitTypeOperator(expression)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun processUnlinkedDeclarations(messageLogger: IrMessageLogger, lazyRoots: () -> List<IrElement>) {
|
||||
if (!allowUnboundSymbols) return
|
||||
|
||||
val processor = UnlinkedDeclarationsProcessor(builtIns, usedClassifierSymbols, handler, messageLogger)
|
||||
processor.addLinkageErrorIntoUnlinkedClasses()
|
||||
|
||||
val roots = lazyRoots()
|
||||
|
||||
val signatureTransformer = processor.signatureTransformer()
|
||||
roots.forEach { it.transformChildrenVoid(signatureTransformer) }
|
||||
|
||||
val usageTransformer = processor.usageTransformer()
|
||||
roots.forEach { it.transformChildrenVoid(usageTransformer) }
|
||||
}
|
||||
}
|
||||
+23
-27
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.common.serialization.unlinked
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport.UnlinkedMarkerTypeHandler
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UsedClassifierSymbolStatus.Companion.isUnlinked
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -27,39 +28,34 @@ import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class UnlinkedDeclarationsProcessor(
|
||||
private val builtIns: IrBuiltIns,
|
||||
private val unlinkedClassifiers: Set<IrClassifierSymbol>,
|
||||
private val usedClassifierSymbols: UsedClassifierSymbols,
|
||||
private val unlinkedMarkerTypeHandler: UnlinkedMarkerTypeHandler,
|
||||
private val messageLogger: IrMessageLogger
|
||||
) {
|
||||
|
||||
companion object {
|
||||
private val errorOrigin = object : IrStatementOriginImpl("LINKAGE ERROR") {}
|
||||
private val ERROR_ORIGIN = object : IrStatementOriginImpl("LINKAGE ERROR") {}
|
||||
}
|
||||
|
||||
fun addLinkageErrorIntoUnlinkedClasses() {
|
||||
for (u in unlinkedClassifiers) {
|
||||
if (u is IrClassSymbol) {
|
||||
val klass = u.owner
|
||||
val anonInitializer = klass.declarations.firstOrNull { it is IrAnonymousInitializer } as IrAnonymousInitializer? ?: run {
|
||||
builtIns.irFactory.createAnonymousInitializer(
|
||||
klass.startOffset,
|
||||
klass.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrAnonymousInitializerSymbolImpl()
|
||||
).also {
|
||||
it.body = builtIns.irFactory.createBlockBody(klass.startOffset, klass.endOffset)
|
||||
it.parent = klass
|
||||
klass.declarations.add(it)
|
||||
}
|
||||
usedClassifierSymbols.forEachClassSymbolToPatch { unlinkedSymbol ->
|
||||
val clazz = unlinkedSymbol.owner
|
||||
clazz.reportUnlinkedSymbolsWarning("Class", clazz.fqNameForIrSerialization)
|
||||
|
||||
val anonInitializer = clazz.declarations.firstNotNullOfOrNull { it as? IrAnonymousInitializer }
|
||||
?: builtIns.irFactory.createAnonymousInitializer(
|
||||
clazz.startOffset,
|
||||
clazz.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrAnonymousInitializerSymbolImpl()
|
||||
).also {
|
||||
it.body = builtIns.irFactory.createBlockBody(clazz.startOffset, clazz.endOffset)
|
||||
it.parent = clazz
|
||||
clazz.declarations.add(it)
|
||||
}
|
||||
anonInitializer.body.statements.clear()
|
||||
anonInitializer.body.statements.clear()
|
||||
anonInitializer.body.statements.add(clazz.throwLinkageError(clazz.symbol))
|
||||
|
||||
klass.reportUnlinkedSymbolsWarning("Class", klass.fqNameForIrSerialization)
|
||||
|
||||
anonInitializer.body.statements.add(klass.throwLinkageError(klass.symbol))
|
||||
|
||||
klass.superTypes = klass.superTypes.filter { !it.isUnlinked() }
|
||||
}
|
||||
clazz.superTypes = clazz.superTypes.filter { !it.isUnlinked() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +251,7 @@ internal class UnlinkedDeclarationsProcessor(
|
||||
return false
|
||||
}
|
||||
|
||||
private fun IrClassifierSymbol.isUnlinked(): Boolean = !isBound || this in unlinkedClassifiers
|
||||
private fun IrClassifierSymbol.isUnlinked(): Boolean = !isBound || usedClassifierSymbols[this].isUnlinked
|
||||
|
||||
private fun IrType.isUnlinked(): Boolean {
|
||||
val simpleType = this as? IrSimpleType ?: return false
|
||||
@@ -287,7 +283,7 @@ internal class UnlinkedDeclarationsProcessor(
|
||||
private fun IrElement.throwLinkageError(unlinkedSymbol: IrSymbol?, message: String = "Unlinked IR symbol"): IrCall {
|
||||
val messageLiteral = message + unlinkedSymbol?.signature?.render()?.let { " $it" }.orEmpty()
|
||||
|
||||
val irCall = IrCallImpl(startOffset, endOffset, builtIns.nothingType, builtIns.linkageErrorSymbol, 0, 1, errorOrigin)
|
||||
val irCall = IrCallImpl(startOffset, endOffset, builtIns.nothingType, builtIns.linkageErrorSymbol, 0, 1, ERROR_ORIGIN)
|
||||
irCall.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, builtIns.stringType, messageLiteral))
|
||||
return irCall
|
||||
}
|
||||
@@ -338,7 +334,7 @@ internal class UnlinkedDeclarationsProcessor(
|
||||
if (!symbol.isUnlinked() && !expression.type.isUnlinked()) return expression
|
||||
|
||||
reportWarning(
|
||||
"Accessing declaration contains unlinked symbol ${symbol.signature?.render() ?: ""}",
|
||||
"Accessing declaration with unlinked symbol ${symbol.signature?.render() ?: ""}",
|
||||
currentFile?.location(expression.startOffset)
|
||||
)
|
||||
|
||||
|
||||
+15
-2
@@ -5,11 +5,22 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.unlinked
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||
|
||||
interface UnlinkedDeclarationsSupport {
|
||||
val allowUnboundSymbols: Boolean
|
||||
fun <T : Any> whenUnboundSymbolsAllowed(action: (UnlinkedMarkerTypeHandler) -> T): T?
|
||||
|
||||
/** For general use in IR linker. */
|
||||
fun markUsedClassifiersExcludingUnlinkedFromFakeOverrideBuilding(fakeOverrideBuilder: FakeOverrideBuilder)
|
||||
|
||||
/** For local use only in inline lazy-IR functions. */
|
||||
fun markUsedClassifiersInInlineLazyIrFunction(function: IrFunction)
|
||||
|
||||
fun processUnlinkedDeclarations(messageLogger: IrMessageLogger, lazyRoots: () -> List<IrElement>)
|
||||
|
||||
interface UnlinkedMarkerTypeHandler {
|
||||
val unlinkedMarkerType: IrType
|
||||
@@ -19,7 +30,9 @@ interface UnlinkedDeclarationsSupport {
|
||||
companion object {
|
||||
val DISABLED = object : UnlinkedDeclarationsSupport {
|
||||
override val allowUnboundSymbols get() = false
|
||||
override fun <T : Any> whenUnboundSymbolsAllowed(action: (UnlinkedMarkerTypeHandler) -> T): T? = null
|
||||
override fun markUsedClassifiersExcludingUnlinkedFromFakeOverrideBuilding(fakeOverrideBuilder: FakeOverrideBuilder) = Unit
|
||||
override fun markUsedClassifiersInInlineLazyIrFunction(function: IrFunction) = Unit
|
||||
override fun processUnlinkedDeclarations(messageLogger: IrMessageLogger, lazyRoots: () -> List<IrElement>) = Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.unlinked
|
||||
|
||||
import gnu.trove.THashSet
|
||||
import gnu.trove.TObjectByteHashMap
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UsedClassifierSymbolStatus.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
|
||||
internal enum class UsedClassifierSymbolStatus(val isUnlinked: Boolean) {
|
||||
/** IR symbol of unlinked classifier. */
|
||||
UNLINKED(true),
|
||||
|
||||
/** IR symbol of linked classifier. */
|
||||
LINKED(false);
|
||||
|
||||
companion object {
|
||||
val UsedClassifierSymbolStatus?.isUnlinked: Boolean get() = this?.isUnlinked == true
|
||||
}
|
||||
}
|
||||
|
||||
internal class UsedClassifierSymbols {
|
||||
private val symbols = TObjectByteHashMap<IrClassifierSymbol>()
|
||||
private val patchedSymbols = THashSet<IrClassSymbol>() // To avoid re-patching what already has been patched.
|
||||
|
||||
fun forEachClassSymbolToPatch(patchAction: (IrClassSymbol) -> Unit) {
|
||||
symbols.forEachEntry { symbol, code ->
|
||||
if (symbol.isBound && code.status == UNLINKED && symbol is IrClassSymbol && patchedSymbols.add(symbol)) {
|
||||
patchAction(symbol)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(symbol: IrClassifierSymbol): UsedClassifierSymbolStatus? = symbols[symbol].status
|
||||
|
||||
fun register(symbol: IrClassifierSymbol, status: UsedClassifierSymbolStatus): Boolean {
|
||||
symbols.put(symbol, status.code)
|
||||
return status.isUnlinked
|
||||
}
|
||||
|
||||
companion object {
|
||||
private inline val Byte.status: UsedClassifierSymbolStatus?
|
||||
get() = when (this) {
|
||||
1.toByte() -> UNLINKED
|
||||
2.toByte() -> LINKED
|
||||
else -> null
|
||||
}
|
||||
|
||||
private inline val UsedClassifierSymbolStatus.code: Byte
|
||||
get() = when (this) {
|
||||
UNLINKED -> 1.toByte()
|
||||
LINKED -> 2.toByte()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,7 +376,7 @@ fun getIrModuleInfoForKlib(
|
||||
val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable)
|
||||
|
||||
val allowUnboundSymbols = configuration[JSConfigurationKeys.PARTIAL_LINKAGE] ?: false
|
||||
val unlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(allowUnboundSymbols)
|
||||
val unlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(irBuiltIns, allowUnboundSymbols)
|
||||
|
||||
val irLinker = JsIrLinker(
|
||||
currentModule = null,
|
||||
@@ -435,7 +435,7 @@ fun getIrModuleInfoForSourceFiles(
|
||||
}
|
||||
|
||||
val allowUnboundSymbols = configuration[JSConfigurationKeys.PARTIAL_LINKAGE] ?: false
|
||||
val unlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(allowUnboundSymbols)
|
||||
val unlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(irBuiltIns, allowUnboundSymbols)
|
||||
|
||||
val irLinker = JsIrLinker(
|
||||
currentModule = psi2IrContext.moduleDescriptor,
|
||||
|
||||
+4
-1
@@ -30,7 +30,10 @@ class JsIrLinker(
|
||||
override val translationPluginContext: TranslationPluginContext?,
|
||||
private val icData: ICData? = null,
|
||||
friendModules: Map<String, Collection<String>> = emptyMap(),
|
||||
override val unlinkedDeclarationsSupport: UnlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(allowUnboundSymbols = false),
|
||||
override val unlinkedDeclarationsSupport: UnlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(
|
||||
builtIns,
|
||||
allowUnboundSymbols = false
|
||||
),
|
||||
private val stubGenerator: DeclarationStubGenerator? = null
|
||||
) : KotlinIrLinker(
|
||||
currentModule = currentModule,
|
||||
|
||||
+4
-6
@@ -35,12 +35,8 @@ class JsLazyIrModuleDeserializer(
|
||||
|
||||
private val descriptorFinder = DescriptorByIdSignatureFinderImpl(moduleDescriptor, JsManglerDesc)
|
||||
|
||||
private fun resolveDescriptor(idSig: IdSignature): DeclarationDescriptor {
|
||||
return descriptorFinder.findDescriptorBySignature(idSig) ?: error("No descriptor found for $idSig")
|
||||
}
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
val descriptor = resolveDescriptor(idSig)
|
||||
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
|
||||
val descriptor = descriptorFinder.findDescriptorBySignature(idSig) ?: return null
|
||||
|
||||
val declaration = stubGenerator.run {
|
||||
when (symbolKind) {
|
||||
@@ -57,6 +53,8 @@ class JsLazyIrModuleDeserializer(
|
||||
return declaration.symbol
|
||||
}
|
||||
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = error("No descriptor found for $idSig")
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
override fun declareIrSymbol(symbol: IrSymbol) {
|
||||
if (symbol is IrFieldSymbol) {
|
||||
|
||||
+7
-6
@@ -5,19 +5,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.BasicUnlinkedDeclarationsSupport
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport.UnlinkedMarkerTypeHandler
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class JsUnlinkedDeclarationsSupport(override val allowUnboundSymbols: Boolean) : UnlinkedDeclarationsSupport {
|
||||
private val handler = object : UnlinkedMarkerTypeHandler {
|
||||
class JsUnlinkedDeclarationsSupport(
|
||||
override val builtIns: IrBuiltIns,
|
||||
override val allowUnboundSymbols: Boolean
|
||||
) : BasicUnlinkedDeclarationsSupport() {
|
||||
override val handler = object : UnlinkedMarkerTypeHandler {
|
||||
override val unlinkedMarkerType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
|
||||
override fun IrType.isUnlinkedMarkerType() = this is IrErrorType
|
||||
}
|
||||
|
||||
override fun <T : Any> whenUnboundSymbolsAllowed(action: (UnlinkedMarkerTypeHandler) -> T): T? =
|
||||
if (allowUnboundSymbols) action(handler) else null
|
||||
}
|
||||
|
||||
+5
-5
@@ -134,12 +134,10 @@ class JvmIrLinker(
|
||||
DescriptorByIdSignatureFinderImpl.LookupMode.MODULE_ONLY
|
||||
)
|
||||
|
||||
private fun resolveDescriptor(idSig: IdSignature): DeclarationDescriptor {
|
||||
return descriptorFinder.findDescriptorBySignature(idSig) ?: error("No descriptor found for $idSig")
|
||||
}
|
||||
private fun resolveDescriptor(idSig: IdSignature): DeclarationDescriptor? = descriptorFinder.findDescriptorBySignature(idSig)
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
val descriptor = resolveDescriptor(idSig)
|
||||
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
|
||||
val descriptor = resolveDescriptor(idSig) ?: return null
|
||||
|
||||
val declaration = stubGenerator.run {
|
||||
when (symbolKind) {
|
||||
@@ -156,6 +154,8 @@ class JvmIrLinker(
|
||||
return declaration.symbol
|
||||
}
|
||||
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = error("No descriptor found for $idSig")
|
||||
|
||||
override fun declareIrSymbol(symbol: IrSymbol) {
|
||||
if (symbol is IrFieldSymbol) {
|
||||
declareJavaFieldStub(symbol)
|
||||
|
||||
+1
@@ -112,6 +112,7 @@ internal class IrProviderForCEnumAndCStructStubs(
|
||||
generateIrIfNeeded(s, file)
|
||||
s.owner
|
||||
}
|
||||
// TODO: better error message?
|
||||
else -> error("Unexpected symbol kind $symbolKind for sig $idSignature")
|
||||
}
|
||||
}
|
||||
|
||||
+18
-7
@@ -606,8 +606,8 @@ internal class KonanIrLinker(
|
||||
return cenumsProvider.getDeclaration(descriptor, idSig, file, symbolKind).symbol
|
||||
}
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
val descriptor = descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) ?: error("Expecting descriptor for $idSig")
|
||||
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
|
||||
val descriptor = descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) ?: return null
|
||||
// If library is cached we don't need to create an IrClass for struct or enum.
|
||||
if (!isLibraryCached && descriptor.isCEnumsOrCStruct()) return resolveCEnumsOrStruct(descriptor, idSig, symbolKind)
|
||||
|
||||
@@ -616,6 +616,8 @@ internal class KonanIrLinker(
|
||||
return symbolOwner.symbol
|
||||
}
|
||||
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = error("No descriptor found for $idSig")
|
||||
|
||||
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns)
|
||||
override val moduleDependencies: Collection<IrModuleDeserializer> = listOfNotNull(forwardDeclarationDeserializer)
|
||||
|
||||
@@ -664,6 +666,8 @@ internal class KonanIrLinker(
|
||||
return (stubGenerator.generateMemberStub(descriptor) as IrSymbolOwner).symbol
|
||||
}
|
||||
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = error("No descriptor found for $idSig")
|
||||
|
||||
private val inlineFunctionReferences by lazy {
|
||||
cachedLibraries.getLibraryCache(klib)!!.serializedInlineFunctionBodies.associateBy {
|
||||
fileDeserializationStates[it.file].declarationDeserializer.symbolDeserializer.deserializeIdSignature(it.functionSignature)
|
||||
@@ -673,7 +677,7 @@ internal class KonanIrLinker(
|
||||
fun deserializeInlineFunction(function: IrFunction): InlineFunctionOriginInfo {
|
||||
val packageFragment = function.getPackageFragment() as? IrExternalPackageFragment
|
||||
?: error("Expected an external package fragment for ${function.render()}")
|
||||
if (function.parents.any { (it as? IrFunction)?.isInline == true}) {
|
||||
if (function.parents.any { (it as? IrFunction)?.isInline == true }) {
|
||||
// Already deserialized by the top-most inline function.
|
||||
return InlineFunctionOriginInfo(
|
||||
function,
|
||||
@@ -742,8 +746,13 @@ internal class KonanIrLinker(
|
||||
}
|
||||
}
|
||||
|
||||
unlinkedDeclarationsSupport.markUsedClassifiersExcludingUnlinkedFromFakeOverrideBuilding(fakeOverrideBuilder)
|
||||
unlinkedDeclarationsSupport.markUsedClassifiersInInlineLazyIrFunction(function)
|
||||
|
||||
fakeOverrideBuilder.provideFakeOverrides()
|
||||
|
||||
unlinkedDeclarationsSupport.processUnlinkedDeclarations(linker.messageLogger) { listOf(function) }
|
||||
|
||||
return InlineFunctionOriginInfo(function, fileDeserializationState.file, inlineFunctionReference.startOffset, inlineFunctionReference.endOffset)
|
||||
}
|
||||
|
||||
@@ -829,10 +838,10 @@ internal class KonanIrLinker(
|
||||
|
||||
override fun contains(idSig: IdSignature): Boolean = idSig.isForwardDeclarationSignature()
|
||||
|
||||
private fun resolveDescriptor(idSig: IdSignature): ClassDescriptor =
|
||||
private fun resolveDescriptor(idSig: IdSignature): ClassDescriptor? =
|
||||
with(idSig as IdSignature.CommonSignature) {
|
||||
val classId = ClassId(packageFqName(), FqName(declarationFqName), false)
|
||||
moduleDescriptor.findClassAcrossModuleDependencies(classId) ?: error("No declaration found with $idSig")
|
||||
moduleDescriptor.findClassAcrossModuleDependencies(classId)
|
||||
}
|
||||
|
||||
private fun buildForwardDeclarationStub(descriptor: ClassDescriptor): IrClass {
|
||||
@@ -841,11 +850,11 @@ internal class KonanIrLinker(
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
||||
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
|
||||
require(symbolKind == BinarySymbolData.SymbolKind.CLASS_SYMBOL) {
|
||||
"Only class could be a Forward declaration $idSig (kind $symbolKind)"
|
||||
}
|
||||
val descriptor = resolveDescriptor(idSig)
|
||||
val descriptor = resolveDescriptor(idSig) ?: return null
|
||||
val actualModule = descriptor.module
|
||||
if (actualModule !== moduleDescriptor) {
|
||||
val moduleDeserializer = resolveModuleDeserializer(actualModule, idSig)
|
||||
@@ -856,6 +865,8 @@ internal class KonanIrLinker(
|
||||
return declaredDeclaration.getOrPut(idSig) { buildForwardDeclarationStub(descriptor) }.symbol
|
||||
}
|
||||
|
||||
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = error("No descriptor found for $idSig")
|
||||
|
||||
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns)
|
||||
override val moduleDependencies: Collection<IrModuleDeserializer> = emptyList()
|
||||
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.serialization
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.BasicUnlinkedDeclarationsSupport
|
||||
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport.UnlinkedMarkerTypeHandler
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
@@ -16,10 +16,13 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
* Kotlin/Native backend does not support [IrErrorType].
|
||||
* So, let's use a special instance of nullable [kotlin.Any] as a marker-type instead.
|
||||
*/
|
||||
class KonanUnlinkedDeclarationsSupport(irBuiltIns: IrBuiltIns, override val allowUnboundSymbols: Boolean) : UnlinkedDeclarationsSupport {
|
||||
private val handler = object : UnlinkedMarkerTypeHandler {
|
||||
class KonanUnlinkedDeclarationsSupport(
|
||||
override val builtIns: IrBuiltIns,
|
||||
override val allowUnboundSymbols: Boolean
|
||||
) : BasicUnlinkedDeclarationsSupport() {
|
||||
override val handler = object : UnlinkedMarkerTypeHandler {
|
||||
override val unlinkedMarkerType = IrSimpleTypeImpl(
|
||||
classifier = irBuiltIns.anyClass,
|
||||
classifier = builtIns.anyClass,
|
||||
hasQuestionMark = true,
|
||||
arguments = emptyList(),
|
||||
annotations = emptyList()
|
||||
@@ -27,7 +30,4 @@ class KonanUnlinkedDeclarationsSupport(irBuiltIns: IrBuiltIns, override val allo
|
||||
|
||||
override fun IrType.isUnlinkedMarkerType(): Boolean = this === unlinkedMarkerType
|
||||
}
|
||||
|
||||
override fun <T : Any> whenUnboundSymbolsAllowed(action: (UnlinkedMarkerTypeHandler) -> T): T? =
|
||||
if (allowUnboundSymbols) action(handler) else null
|
||||
}
|
||||
Reference in New Issue
Block a user