IR: reorganize IrProvider handling

Make DeclarationStubGenerator a subclass of IrProvider,
anticipating deserialization of IR structures for JVM_IR backend.
This commit is contained in:
Georgy Bronnikov
2019-11-25 14:03:34 +03:00
parent be04912f6f
commit 1ed23d7c54
17 changed files with 198 additions and 138 deletions
@@ -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)
}
}
@@ -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)
}
}