IR: reorganize IrProvider handling
Make DeclarationStubGenerator a subclass of IrProvider, anticipating deserialization of IR structures for JVM_IR backend.
This commit is contained in:
@@ -101,6 +101,8 @@ abstract class WrappedDeclarationDescriptor<T : IrDeclaration>(annotations: Anno
|
||||
fun bind(declaration: T) {
|
||||
owner = declaration
|
||||
}
|
||||
|
||||
fun isBound(): Boolean = _owner != null
|
||||
}
|
||||
|
||||
abstract class WrappedCallableDescriptor<T : IrDeclaration>(
|
||||
|
||||
@@ -22,9 +22,15 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
@@ -36,9 +42,8 @@ class DeclarationStubGenerator(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
val symbolTable: SymbolTable,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
private val irProviders: List<IrProvider> = emptyList(),
|
||||
val extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY
|
||||
) {
|
||||
) : IrProvider {
|
||||
private val lazyTable = symbolTable.lazyWrapper
|
||||
|
||||
internal var unboundSymbolGeneration: Boolean
|
||||
@@ -47,6 +52,12 @@ class DeclarationStubGenerator(
|
||||
lazyTable.stubGenerator = if (value) this else null
|
||||
}
|
||||
|
||||
private lateinit var irProviders_: List<IrProvider>
|
||||
|
||||
fun setIrProviders(value: List<IrProvider>) {
|
||||
irProviders_ = value
|
||||
irProviders_.filterIsInstance<LazyIrProvider>().forEach { it.declarationStubGenerator = this }
|
||||
}
|
||||
|
||||
val typeTranslator =
|
||||
TypeTranslator(lazyTable, languageVersionSettings, moduleDescriptor.builtIns, LazyScopedTypeParametersResolver(lazyTable), true)
|
||||
@@ -57,14 +68,15 @@ class DeclarationStubGenerator(
|
||||
init {
|
||||
typeTranslator.constantValueGenerator = constantValueGenerator
|
||||
constantValueGenerator.typeTranslator = typeTranslator
|
||||
irProviders.filterIsInstance<LazyIrProvider>().forEach { it.declarationStubGenerator = this }
|
||||
}
|
||||
|
||||
private fun getDeclaration(symbol: IrSymbol): IrDeclaration? {
|
||||
for (irProvider in irProviders)
|
||||
irProvider.getDeclaration(symbol)?.let { return it }
|
||||
return null
|
||||
}
|
||||
override fun getDeclaration(symbol: IrSymbol): IrDeclaration? = when {
|
||||
// Special case: generating field for an already generated property.
|
||||
symbol is IrFieldSymbol && (symbol.descriptor as? WrappedPropertyDescriptor)?.isBound() == true ->
|
||||
generateStubBySymbol(symbol)
|
||||
symbol.descriptor is WrappedDeclarationDescriptor<*> -> null
|
||||
else -> generateStubBySymbol(symbol)
|
||||
}
|
||||
|
||||
fun generateOrGetEmptyExternalPackageFragmentStub(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment {
|
||||
val referenced = symbolTable.referenceExternalPackageFragment(descriptor)
|
||||
@@ -101,10 +113,21 @@ class DeclarationStubGenerator(
|
||||
generateFunctionStub(descriptor)
|
||||
is PropertyDescriptor ->
|
||||
generatePropertyStub(descriptor)
|
||||
is TypeAliasDescriptor ->
|
||||
generateTypeAliasStub(descriptor)
|
||||
else ->
|
||||
throw AssertionError("Unexpected member descriptor: $descriptor")
|
||||
}
|
||||
|
||||
private fun generateStubBySymbol(symbol: IrSymbol): IrDeclaration = when (symbol) {
|
||||
is IrFieldSymbol ->
|
||||
generateFieldStub(symbol.descriptor)
|
||||
is IrTypeParameterSymbol ->
|
||||
generateOrGetTypeParameterStub(symbol.descriptor)
|
||||
else ->
|
||||
generateMemberStub(symbol.descriptor)
|
||||
}
|
||||
|
||||
private fun computeOrigin(descriptor: DeclarationDescriptor): IrDeclarationOrigin =
|
||||
extensions.computeExternalDeclarationOrigin(descriptor) ?: IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
|
||||
|
||||
@@ -122,8 +145,7 @@ class DeclarationStubGenerator(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original,
|
||||
isDelegated = @Suppress("DEPRECATION") descriptor.isDelegated
|
||||
) {
|
||||
getDeclaration(referenced) as? IrProperty
|
||||
?: IrLazyProperty(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator, bindingContext)
|
||||
IrLazyProperty(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator, bindingContext)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,8 +161,7 @@ class DeclarationStubGenerator(
|
||||
else computeOrigin(descriptor)
|
||||
|
||||
return symbolTable.declareField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original, descriptor.type.toIrType()) {
|
||||
getDeclaration(referenced) as? IrField
|
||||
?: IrLazyField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
IrLazyField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,10 +172,14 @@ class DeclarationStubGenerator(
|
||||
}
|
||||
|
||||
if (createPropertyIfNeeded && descriptor is PropertyGetterDescriptor) {
|
||||
return generatePropertyStub(descriptor.correspondingProperty).getter!!
|
||||
val propertySymbol = symbolTable.referenceProperty(descriptor.correspondingProperty)
|
||||
val property = irProviders_.getDeclaration(propertySymbol) as IrProperty
|
||||
return property.getter!!
|
||||
}
|
||||
if (createPropertyIfNeeded && descriptor is PropertySetterDescriptor) {
|
||||
return generatePropertyStub(descriptor.correspondingProperty).setter!!
|
||||
val propertySymbol = symbolTable.referenceProperty(descriptor.correspondingProperty)
|
||||
val property = irProviders_.getDeclaration(propertySymbol) as IrProperty
|
||||
return property.setter!!
|
||||
}
|
||||
|
||||
val origin =
|
||||
@@ -166,8 +191,7 @@ class DeclarationStubGenerator(
|
||||
origin,
|
||||
descriptor.original
|
||||
) {
|
||||
getDeclaration(referenced) as? IrSimpleFunction
|
||||
?: IrLazyFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
IrLazyFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,8 +205,7 @@ class DeclarationStubGenerator(
|
||||
return symbolTable.declareConstructor(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original
|
||||
) {
|
||||
getDeclaration(referenced) as? IrConstructor
|
||||
?: IrLazyConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
IrLazyConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,8 +235,7 @@ class DeclarationStubGenerator(
|
||||
}
|
||||
val origin = computeOrigin(descriptor)
|
||||
return symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
|
||||
getDeclaration(referenceClass) as? IrClass
|
||||
?: IrLazyClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
IrLazyClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,8 +246,7 @@ class DeclarationStubGenerator(
|
||||
}
|
||||
val origin = computeOrigin(descriptor)
|
||||
return symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
|
||||
getDeclaration(referenced) as? IrEnumEntry
|
||||
?: IrLazyEnumEntryImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
IrLazyEnumEntryImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,8 +257,7 @@ class DeclarationStubGenerator(
|
||||
}
|
||||
val origin = computeOrigin(descriptor)
|
||||
return symbolTable.declareGlobalTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
|
||||
getDeclaration(referenced) as? IrTypeParameter
|
||||
?: IrLazyTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
IrLazyTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+58
-60
@@ -17,70 +17,68 @@
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import kotlin.math.min
|
||||
|
||||
class ExternalDependenciesGenerator(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
val symbolTable: SymbolTable,
|
||||
val irBuiltIns: IrBuiltIns,
|
||||
private val deserializer: IrDeserializer? = null,
|
||||
irProviders: List<IrProvider> = emptyList(),
|
||||
extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY
|
||||
) {
|
||||
private val stubGenerator = DeclarationStubGenerator(
|
||||
moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings, listOfNotNull(deserializer) + irProviders, extensions
|
||||
)
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
class ExternalDependenciesGenerator(val symbolTable: SymbolTable, private val irProviders: List<IrProvider>) {
|
||||
fun generateUnboundSymbolsAsDependencies() {
|
||||
stubGenerator.unboundSymbolGeneration = true
|
||||
do {
|
||||
fun <T> haveNotStabilized(prev: ArrayList<T>, cur: Set<T>) =
|
||||
cur.isNotEmpty() && (prev.size != cur.size || prev.any { !cur.contains(it) })
|
||||
|
||||
val unboundClasses = ArrayList(symbolTable.unboundClasses)
|
||||
val unboundConstructors = ArrayList(symbolTable.unboundConstructors)
|
||||
val unboundEnumEntries = ArrayList(symbolTable.unboundEnumEntries)
|
||||
val unboundFields = ArrayList(symbolTable.unboundFields)
|
||||
val unboundSimpleFunctions = ArrayList(symbolTable.unboundSimpleFunctions)
|
||||
val unboundProperties = ArrayList(symbolTable.unboundProperties)
|
||||
val unboundTypeParameters = ArrayList(symbolTable.unboundTypeParameters)
|
||||
val unboundTypeAliases = ArrayList(symbolTable.unboundTypeAliases)
|
||||
unboundClasses.forEach { stubGenerator.generateClassStub(it.descriptor) }
|
||||
unboundConstructors.forEach { stubGenerator.generateConstructorStub(it.descriptor) }
|
||||
unboundEnumEntries.forEach { stubGenerator.generateEnumEntryStub(it.descriptor) }
|
||||
unboundFields.forEach { stubGenerator.generateFieldStub(it.descriptor) }
|
||||
unboundSimpleFunctions.forEach { stubGenerator.generateFunctionStub(it.descriptor) }
|
||||
unboundProperties.forEach { stubGenerator.generatePropertyStub(it.descriptor) }
|
||||
unboundTypeParameters.forEach { stubGenerator.generateOrGetTypeParameterStub(it.descriptor) }
|
||||
unboundTypeAliases.forEach { stubGenerator.generateTypeAliasStub(it.descriptor) }
|
||||
} while (haveNotStabilized(unboundClasses, symbolTable.unboundClasses)
|
||||
|| haveNotStabilized(unboundConstructors, symbolTable.unboundConstructors)
|
||||
|| haveNotStabilized(unboundEnumEntries, symbolTable.unboundEnumEntries)
|
||||
|| haveNotStabilized(unboundFields, symbolTable.unboundFields)
|
||||
|| haveNotStabilized(unboundSimpleFunctions, symbolTable.unboundSimpleFunctions)
|
||||
|| haveNotStabilized(unboundProperties, symbolTable.unboundProperties)
|
||||
|| haveNotStabilized(unboundTypeParameters, symbolTable.unboundTypeParameters)
|
||||
|| haveNotStabilized(unboundTypeAliases, symbolTable.unboundTypeAliases)
|
||||
)
|
||||
|
||||
deserializer?.declareForwardDeclarations()
|
||||
|
||||
assertEmpty(symbolTable.unboundClasses, "classes")
|
||||
assertEmpty(symbolTable.unboundConstructors, "constructors")
|
||||
assertEmpty(symbolTable.unboundEnumEntries, "enum entries")
|
||||
assertEmpty(symbolTable.unboundFields, "fields")
|
||||
assertEmpty(symbolTable.unboundSimpleFunctions, "simple functions")
|
||||
assertEmpty(symbolTable.unboundProperties, "properties")
|
||||
assertEmpty(symbolTable.unboundTypeParameters, "type parameters")
|
||||
assertEmpty(symbolTable.unboundTypeAliases, "type aliases")
|
||||
}
|
||||
|
||||
private fun assertEmpty(s: Set<IrSymbol>, marker: String) {
|
||||
assert(s.isEmpty()) {
|
||||
"$marker: ${s.size} unbound:\n" +
|
||||
s.toList().subList(0, min(10, s.size)).joinToString(separator = "\n") { it.descriptor.toString() }
|
||||
// There should be at most one DeclarationStubGenerator (none in closed world?)
|
||||
irProviders.singleOrNull { it is DeclarationStubGenerator }?.let {
|
||||
(it as DeclarationStubGenerator).unboundSymbolGeneration = true
|
||||
}
|
||||
/*
|
||||
Deserializing a reference may lead to new unbound references, so we loop until none are left.
|
||||
*/
|
||||
lateinit var unbound: List<IrSymbol>
|
||||
do {
|
||||
unbound = symbolTable.allUnbound
|
||||
|
||||
for (symbol in unbound) {
|
||||
// Symbol could get bound as a side effect of deserializing other symbols.
|
||||
if (!symbol.isBound) {
|
||||
irProviders.getDeclaration(symbol)
|
||||
}
|
||||
assert(symbol.isBound) { "$symbol unbound even after deserialization attempt" }
|
||||
}
|
||||
} while (unbound.isNotEmpty())
|
||||
|
||||
irProviders.forEach { (it as? IrDeserializer)?.declareForwardDeclarations() }
|
||||
}
|
||||
}
|
||||
|
||||
private val SymbolTable.allUnbound: List<IrSymbol>
|
||||
get() {
|
||||
val r = mutableListOf<IrSymbol>()
|
||||
r.addAll(unboundClasses)
|
||||
r.addAll(unboundConstructors)
|
||||
r.addAll(unboundEnumEntries)
|
||||
r.addAll(unboundFields)
|
||||
r.addAll(unboundSimpleFunctions)
|
||||
r.addAll(unboundProperties)
|
||||
r.addAll(unboundTypeParameters)
|
||||
r.addAll(unboundTypeAliases)
|
||||
return r
|
||||
}
|
||||
|
||||
fun List<IrProvider>.getDeclaration(symbol: IrSymbol): IrDeclaration =
|
||||
firstNotNullResult { provider ->
|
||||
provider.getDeclaration(symbol)
|
||||
} ?: error("Could not find declaration for unbound symbol $symbol")
|
||||
|
||||
// In most cases, IrProviders list consist of an optional deserializer and a DeclarationStubGenerator.
|
||||
fun generateTypicalIrProviderList(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
irBuiltins: IrBuiltIns,
|
||||
symbolTable: SymbolTable,
|
||||
deserializer: IrDeserializer? = null,
|
||||
extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY
|
||||
): List<IrProvider> {
|
||||
val stubGenerator = DeclarationStubGenerator(
|
||||
moduleDescriptor, symbolTable, irBuiltins.languageVersionSettings, extensions
|
||||
)
|
||||
return listOfNotNull(deserializer, stubGenerator).also {
|
||||
stubGenerator.setIrProviders(it)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user