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
+1
View File
@@ -214,6 +214,7 @@ extra["compilerModules"] = arrayOf(
":compiler:backend.wasm",
":compiler:ir.serialization.common",
":compiler:ir.serialization.js",
":compiler:ir.serialization.jvm",
":kotlin-util-io",
":kotlin-util-klib",
":kotlin-util-klib-metadata",
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.ConstantValueGenerator
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
@@ -57,6 +54,7 @@ object Fir2IrConverter {
builtIns: IrBuiltIns
) {
// TODO: provide StubGeneratorExtensions for correct lazy stub IR generation on JVM
ExternalDependenciesGenerator(irModule.descriptor, symbolTable, builtIns).generateUnboundSymbolsAsDependencies()
ExternalDependenciesGenerator(symbolTable, generateTypicalIrProviderList(irModule.descriptor, builtIns, symbolTable))
.generateUnboundSymbolsAsDependencies()
}
}
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.library.KotlinLibrary
@@ -67,7 +68,8 @@ fun compile(
// Load declarations referenced during `context` initialization
dependencyModules.forEach {
ExternalDependenciesGenerator(it.descriptor, symbolTable, irBuiltIns, deserializer).generateUnboundSymbolsAsDependencies()
val irProviders = generateTypicalIrProviderList(it.descriptor, irBuiltIns, symbolTable, deserializer)
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
}
val irFiles = dependencyModules.flatMap { it.files } + moduleFragment.files
@@ -75,8 +77,9 @@ fun compile(
moduleFragment.files.clear()
moduleFragment.files += irFiles
val irProvidersWithoutDeserializer = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable)
// Create stubs
ExternalDependenciesGenerator(moduleDescriptor, symbolTable, irBuiltIns).generateUnboundSymbolsAsDependencies()
ExternalDependenciesGenerator(symbolTable, irProvidersWithoutDeserializer).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents()
moveBodilessDeclarationsToSeparatePlace(context, moduleFragment)
+1
View File
@@ -9,6 +9,7 @@ dependencies {
compile(project(":compiler:ir.tree"))
compile(project(":compiler:ir.psi2ir"))
compile(project(":compiler:ir.backend.common"))
compile(project(":compiler:ir.serialization.jvm"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "asm-all", "guava", rootProject = rootProject) }
compileOnly(intellijDep()) { includeJars("trove4j", rootProject = rootProject) }
}
@@ -47,7 +47,10 @@ class JvmBackendContext(
override val irBuiltIns: IrBuiltIns,
irModuleFragment: IrModuleFragment,
symbolTable: SymbolTable,
val phaseConfig: PhaseConfig
val phaseConfig: PhaseConfig,
// If the JVM fqname of a class differs from what is implied by its parent, e.g. if it's a file class
// annotated with @JvmPackageName, the correct name is recorded here.
internal val classNameOverride: MutableMap<IrClass, JvmClassName>
) : CommonBackendContext {
override val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
get() = TODO("not implemented")
@@ -86,10 +89,6 @@ class JvmBackendContext(
internal val localDelegatedProperties = mutableMapOf<IrClass, List<IrLocalDelegatedPropertySymbol>>()
// If the JVM fqname of a class differs from what is implied by its parent, e.g. if it's a file class
// annotated with @JvmPackageName, the correct name is recorded here.
internal lateinit var classNameOverride: MutableMap<IrClass, JvmClassName>
internal val multifileFacadesToAdd = mutableMapOf<JvmClassName, MutableList<IrClass>>()
internal val multifileFacadeForPart = mutableMapOf<IrClass, JvmClassName>()
internal val multifileFacadeMemberToPartMember = mutableMapOf<IrFunction, IrFunction>()
@@ -7,16 +7,16 @@ package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
import org.jetbrains.kotlin.backend.jvm.serialization.JvmMangler
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.psi.KtFile
@@ -30,7 +30,7 @@ object JvmBackendFacade {
errorHandler: CompilationErrorHandler,
phaseConfig: PhaseConfig
) {
val psi2ir = Psi2IrTranslator(state.languageVersionSettings)
val psi2ir = Psi2IrTranslator(state.languageVersionSettings, mangler = JvmMangler)
val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = JvmGeneratorExtensions)
val extensions = JvmStubGeneratorExtensions()
@@ -50,7 +50,11 @@ object JvmBackendFacade {
}
}
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, stubGeneratorExtensions = extensions)
val irProviders = generateTypicalIrProviderList(
psi2irContext.moduleDescriptor, psi2irContext.irBuiltIns, psi2irContext.symbolTable,
extensions = extensions
)
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, irProviders = irProviders)
doGenerateFilesInternal(
state, errorHandler, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, extensions
)
@@ -66,7 +70,7 @@ object JvmBackendFacade {
extensions: JvmStubGeneratorExtensions = JvmStubGeneratorExtensions()
) {
val context = JvmBackendContext(
state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig
state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig, extensions.classNameOverride
)
state.irBasedMapAsmMethod = { descriptor ->
context.methodSignatureMapper.mapAsmMethod(context.referenceFunction(descriptor).owner)
@@ -75,15 +79,6 @@ object JvmBackendFacade {
context.typeMapper.mapType(context.referenceClass(descriptor).defaultType)
}
ExternalDependenciesGenerator(
irModuleFragment.descriptor,
symbolTable,
irModuleFragment.irBuiltins,
extensions = extensions
).generateUnboundSymbolsAsDependencies()
context.classNameOverride = extensions.classNameOverride
try {
JvmLower(context).lower(irModuleFragment)
} catch (e: Throwable) {
@@ -21,7 +21,9 @@ import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
@@ -39,7 +41,14 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory
symbolTable: SymbolTable,
sourceManager: PsiSourceManager
) {
JvmBackendFacade.doGenerateFilesInternal(state, errorHandler, irModuleFragment, symbolTable, sourceManager, phaseConfig)
val stubGeneratorExtensions = JvmStubGeneratorExtensions()
val irProviders = generateTypicalIrProviderList(
irModuleFragment.descriptor, irModuleFragment.irBuiltins, symbolTable, extensions = stubGeneratorExtensions
)
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
JvmBackendFacade.doGenerateFilesInternal(
state, errorHandler, irModuleFragment, symbolTable, sourceManager, phaseConfig, stubGeneratorExtensions
)
}
override fun createPackageCodegen(state: GenerationState, files: Collection<KtFile>, fqName: FqName): PackageCodegen {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.wasm.codegen.IrModuleToWasm
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.backend.js.loadIr
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
@@ -37,7 +38,8 @@ fun compileWasm(
// Load declarations referenced during `context` initialization
dependencyModules.forEach {
ExternalDependenciesGenerator(it.descriptor, symbolTable, irBuiltIns, deserializer).generateUnboundSymbolsAsDependencies()
val irProviders = generateTypicalIrProviderList(it.descriptor, irBuiltIns, symbolTable, deserializer)
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
}
val irFiles = dependencyModules.flatMap { it.files } + moduleFragment.files
@@ -46,10 +48,11 @@ fun compileWasm(
moduleFragment.files += irFiles
// Create stubs
ExternalDependenciesGenerator(moduleDescriptor, symbolTable, irBuiltIns).generateUnboundSymbolsAsDependencies()
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer)
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents()
wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment)
return IrModuleToWasm(context).generateModule(moduleFragment)
}
}
@@ -35,7 +35,8 @@ typealias Psi2IrPostprocessingStep = (IrModuleFragment) -> Unit
class Psi2IrTranslator(
val languageVersionSettings: LanguageVersionSettings,
val configuration: Psi2IrConfiguration = Psi2IrConfiguration()
val configuration: Psi2IrConfiguration = Psi2IrConfiguration(),
val mangler: KotlinMangler? = null
) {
private val postprocessingSteps = SmartList<Psi2IrPostprocessingStep>()
@@ -51,13 +52,19 @@ class Psi2IrTranslator(
stubGeneratorExtensions: StubGeneratorExtensions
): IrModuleFragment {
val context = createGeneratorContext(moduleDescriptor, bindingContext, extensions = generatorExtensions)
return generateModuleFragment(context, ktFiles, stubGeneratorExtensions = stubGeneratorExtensions)
return generateModuleFragment(
context, ktFiles,
irProviders = generateTypicalIrProviderList(
moduleDescriptor, context.irBuiltIns, context.symbolTable,
extensions = stubGeneratorExtensions
)
)
}
fun createGeneratorContext(
moduleDescriptor: ModuleDescriptor,
bindingContext: BindingContext,
symbolTable: SymbolTable = SymbolTable(),
symbolTable: SymbolTable = SymbolTable(mangler),
extensions: GeneratorExtensions = GeneratorExtensions()
): GeneratorContext =
GeneratorContext(configuration, moduleDescriptor, bindingContext, languageVersionSettings, symbolTable, extensions)
@@ -65,16 +72,17 @@ class Psi2IrTranslator(
fun generateModuleFragment(
context: GeneratorContext,
ktFiles: Collection<KtFile>,
deserializer: IrDeserializer? = null,
irProviders: List<IrProvider> = emptyList(),
stubGeneratorExtensions: StubGeneratorExtensions = StubGeneratorExtensions()
irProviders: List<IrProvider>
): IrModuleFragment {
val moduleGenerator = ModuleGenerator(context)
val irModule = moduleGenerator.generateModuleFragment(ktFiles)
val irModule = moduleGenerator.generateModuleFragmentWithoutDependencies(ktFiles)
moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders)
irModule.patchDeclarationParents()
postprocess(context, irModule)
moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, stubGeneratorExtensions)
irModule.computeUniqIdForDeclarations(context.symbolTable)
moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders)
return irModule
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.IrDeserializer
import org.jetbrains.kotlin.ir.util.IrProvider
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile
@@ -35,7 +36,12 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
private val constantValueGenerator = context.constantValueGenerator
fun generateModuleFragment(ktFiles: Collection<KtFile>): IrModuleFragment =
fun generateModuleFragment(ktFiles: Collection<KtFile>, deserializer: IrDeserializer, extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY): IrModuleFragment =
generateModuleFragmentWithoutDependencies(ktFiles).also { irModule ->
generateUnboundSymbolsAsDependencies(irModule, deserializer, extensions)
}
fun generateModuleFragmentWithoutDependencies(ktFiles: Collection<KtFile>): IrModuleFragment =
IrModuleFragmentImpl(context.moduleDescriptor, context.irBuiltIns).also { irModule ->
irModule.files.addAll(generateFiles(ktFiles))
}
@@ -43,12 +49,17 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
fun generateUnboundSymbolsAsDependencies(
irModule: IrModuleFragment,
deserializer: IrDeserializer? = null,
irProviders: List<IrProvider> = emptyList(),
extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY
) {
ExternalDependenciesGenerator(
irModule.descriptor, context.symbolTable, context.irBuiltIns, deserializer, irProviders, extensions
).generateUnboundSymbolsAsDependencies()
val fullIrProvidersList = generateTypicalIrProviderList(
irModule.descriptor, context.irBuiltIns, context.symbolTable, deserializer,
extensions
)
ExternalDependenciesGenerator(context.symbolTable, fullIrProvidersList).generateUnboundSymbolsAsDependencies()
}
fun generateUnboundSymbolsAsDependencies(irProviders: List<IrProvider>) {
ExternalDependenciesGenerator(context.symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
}
private fun generateFiles(ktFiles: Collection<KtFile>): List<IrFile> {
@@ -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)
}
}
@@ -257,7 +257,7 @@ abstract class KotlinManglerImpl : KotlinMangler {
private val IrProperty.symbolName: String
get() {
val extensionReceiver: String = getter!!.extensionReceiverParameter?.extensionReceiverNamePart ?: ""
val extensionReceiver: String = getter?.extensionReceiverParameter?.extensionReceiverNamePart ?: ""
val containingDeclarationPart = parent.fqNameForIrSerialization.let {
if (it.isRoot) "" else "$it."
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.ExpectDeclarationRemover
import org.jetbrains.kotlin.ir.util.IrDeserializer
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
@@ -201,7 +202,8 @@ fun GeneratorContext.generateModuleFragmentWithPlugins(
files: List<KtFile>,
deserializer: IrDeserializer? = null
): IrModuleFragment {
val psi2Ir = Psi2IrTranslator(languageVersionSettings, configuration)
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer)
val psi2Ir = Psi2IrTranslator(languageVersionSettings, configuration, mangler = JsMangler)
for (extension in IrGenerationExtension.getInstances(project)) {
psi2Ir.addPostprocessingStep { module ->
@@ -223,13 +225,17 @@ fun GeneratorContext.generateModuleFragmentWithPlugins(
psi2Ir.generateModuleFragment(
this,
files,
deserializer
irProviders
)
return moduleFragment
}
fun GeneratorContext.generateModuleFragment(files: List<KtFile>, deserializer: IrDeserializer? = null) =
Psi2IrTranslator(languageVersionSettings, configuration).generateModuleFragment(this, files, deserializer)
fun GeneratorContext.generateModuleFragment(files: List<KtFile>, deserializer: IrDeserializer? = null): IrModuleFragment {
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer)
return Psi2IrTranslator(
languageVersionSettings, configuration, mangler = JsMangler
).generateModuleFragment(this, files, irProviders)
}
private fun createBuiltIns(storageManager: StorageManager) = object : KotlinBuiltIns(storageManager) {}
@@ -18,9 +18,11 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
import org.jetbrains.kotlin.ir.backend.js.generateModuleFragment
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsMangler
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzer
@@ -58,7 +60,7 @@ class JsCoreScriptingCompiler(
val module = analysisResult.moduleDescriptor
val bindingContext = analysisResult.bindingContext
val psi2ir = Psi2IrTranslator(environment.configuration.languageVersionSettings)
val psi2ir = Psi2IrTranslator(environment.configuration.languageVersionSettings, mangler = JsMangler)
val psi2irContext = psi2ir.createGeneratorContext(module, bindingContext, symbolTable)
val irModuleFragment = psi2irContext.generateModuleFragment(listOf(snippetKtFile))
@@ -74,9 +76,12 @@ class JsCoreScriptingCompiler(
)
ExternalDependenciesGenerator(
irModuleFragment.descriptor,
psi2irContext.symbolTable,
psi2irContext.irBuiltIns
generateTypicalIrProviderList(
irModuleFragment.descriptor,
psi2irContext.irBuiltIns,
psi2irContext.symbolTable
)
).generateUnboundSymbolsAsDependencies()
environment.configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
@@ -50,8 +50,9 @@ class JsScriptDependencyCompiler(
val moduleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns)
val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it) }
val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer = jsLinker)
ExternalDependenciesGenerator(moduleDescriptor, symbolTable, irBuiltIns, jsLinker).generateUnboundSymbolsAsDependencies()
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents()
val backendContext = JsIrBackendContext(
@@ -64,7 +65,7 @@ class JsScriptDependencyCompiler(
true
)
ExternalDependenciesGenerator(moduleDescriptor, symbolTable, irBuiltIns, jsLinker).generateUnboundSymbolsAsDependencies()
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents()
moduleFragment.files += irDependencies.flatMap { it.files }