diff --git a/build.gradle.kts b/build.gradle.kts index 8ea5580e3c7..8c0165201ea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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", diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 27bba2545f0..7c8e83979c4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -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() } -} +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index c7d58f1ba5a..362bb52c6ff 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -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) diff --git a/compiler/ir/backend.jvm/build.gradle.kts b/compiler/ir/backend.jvm/build.gradle.kts index 5d9ddd18612..db95227e83e 100644 --- a/compiler/ir/backend.jvm/build.gradle.kts +++ b/compiler/ir/backend.jvm/build.gradle.kts @@ -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) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 630c8c67552..f3781d6d096 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -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 ) : CommonBackendContext { override val transformedFunction: MutableMap get() = TODO("not implemented") @@ -86,10 +89,6 @@ class JvmBackendContext( internal val localDelegatedProperties = mutableMapOf>() - // 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 - internal val multifileFacadesToAdd = mutableMapOf>() internal val multifileFacadeForPart = mutableMapOf() internal val multifileFacadeMemberToPartMember = mutableMapOf() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt index 1ac93357a56..97feca4e0e6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt @@ -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) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index 5f51a3e1b18..ea59a12e4e2 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -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, fqName: FqName): PackageCodegen { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt index 82ce503af0a..210d6308094 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt @@ -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) -} +} \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt index f18917826e3..65ec1938c6f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt @@ -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() @@ -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, - deserializer: IrDeserializer? = null, - irProviders: List = emptyList(), - stubGeneratorExtensions: StubGeneratorExtensions = StubGeneratorExtensions() + irProviders: List ): 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 } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ModuleGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ModuleGenerator.kt index 5a3304b059d..792a47d1832 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ModuleGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ModuleGenerator.kt @@ -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): IrModuleFragment = + fun generateModuleFragment(ktFiles: Collection, deserializer: IrDeserializer, extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY): IrModuleFragment = + generateModuleFragmentWithoutDependencies(ktFiles).also { irModule -> + generateUnboundSymbolsAsDependencies(irModule, deserializer, extensions) + } + + fun generateModuleFragmentWithoutDependencies(ktFiles: Collection): 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 = 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) { + ExternalDependenciesGenerator(context.symbolTable, irProviders).generateUnboundSymbolsAsDependencies() } private fun generateFiles(ktFiles: Collection): List { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt index 294c0c18329..763cf77c1b2 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt @@ -101,6 +101,8 @@ abstract class WrappedDeclarationDescriptor(annotations: Anno fun bind(declaration: T) { owner = declaration } + + fun isBound(): Boolean = _owner != null } abstract class WrappedCallableDescriptor( diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt index 63dd8a798fb..7830d982131 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt @@ -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 = 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 + + fun setIrProviders(value: List) { + irProviders_ = value + irProviders_.filterIsInstance().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().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) } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt index d231229a0d5..c67ed02616f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt @@ -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 = 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) { fun generateUnboundSymbolsAsDependencies() { - stubGenerator.unboundSymbolGeneration = true - do { - fun haveNotStabilized(prev: ArrayList, cur: Set) = - 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, 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 + 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 + get() { + val r = mutableListOf() + 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.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 { + val stubGenerator = DeclarationStubGenerator( + moduleDescriptor, symbolTable, irBuiltins.languageVersionSettings, extensions + ) + return listOfNotNull(deserializer, stubGenerator).also { + stubGenerator.setIrProviders(it) + } +} \ No newline at end of file diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinMangler.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinMangler.kt index 52d17640b02..80856a26f56 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinMangler.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinMangler.kt @@ -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." diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 8dcae052702..2c2955b0959 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -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, 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, deserializer: IrDeserializer? = null) = - Psi2IrTranslator(languageVersionSettings, configuration).generateModuleFragment(this, files, deserializer) +fun GeneratorContext.generateModuleFragment(files: List, 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) {} diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsCoreScriptingCompiler.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsCoreScriptingCompiler.kt index 7b32f1ce4f7..6865b79dc97 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsCoreScriptingCompiler.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsCoreScriptingCompiler.kt @@ -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) diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsScriptDependencyCompiler.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsScriptDependencyCompiler.kt index f45cf7e6b33..bc34af15e37 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsScriptDependencyCompiler.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsScriptDependencyCompiler.kt @@ -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 }