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 5595fe8c58d..8fbf043de44 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 @@ -5,16 +5,23 @@ package org.jetbrains.kotlin.backend.jvm +import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.codegen.CompilationErrorHandler import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.ir.builders.declarations.buildClass +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin 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.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource +import org.jetbrains.kotlin.utils.addToStdlib.safeAs object JvmBackendFacade { fun doGenerateFiles( @@ -23,7 +30,7 @@ object JvmBackendFacade { errorHandler: CompilationErrorHandler, phaseConfig: PhaseConfig ) { - val psi2ir = Psi2IrTranslator(state.languageVersionSettings) + val psi2ir = Psi2IrTranslator(state.languageVersionSettings, facadeClassGenerator = ::facadeClassGenerator) val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = JvmGeneratorExtensions) val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files) @@ -59,7 +66,8 @@ object JvmBackendFacade { irModuleFragment.descriptor, symbolTable, irModuleFragment.irBuiltins, - JvmGeneratorExtensions.externalDeclarationOrigin + JvmGeneratorExtensions.externalDeclarationOrigin, + facadeClassGenerator = ::facadeClassGenerator ).generateUnboundSymbolsAsDependencies() val jvmBackend = JvmBackend(jvmBackendContext) @@ -81,4 +89,15 @@ object JvmBackendFacade { } } } + + internal fun facadeClassGenerator(source: DeserializedContainerSource): IrClass? { + val jvmPackagePartSource = source.safeAs() ?: return null + val facadeName = jvmPackagePartSource.facadeClassName ?: jvmPackagePartSource.className + return buildClass { + origin = IrDeclarationOrigin.FILE_CLASS + name = facadeName.fqNameForTopLevelClassMaybeWithDollars.shortName() + }.also { + it.createParameterDeclarations() + } + } } 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 9c766ccbbc8..3d623f97f3b 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 @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory { override fun generateModule(state: GenerationState, files: Collection, errorHandler: CompilationErrorHandler) { - val psi2ir = Psi2IrTranslator(state.languageVersionSettings) + val psi2ir = Psi2IrTranslator(state.languageVersionSettings, facadeClassGenerator = JvmBackendFacade::facadeClassGenerator) val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = JvmGeneratorExtensions) val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files) JvmBackendFacade.doGenerateFilesInternal(state, errorHandler, irModuleFragment, psi2irContext, phaseConfig) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt index dbfb54639b3..2c3e835db23 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt @@ -19,10 +19,7 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics import org.jetbrains.kotlin.backend.jvm.JvmSymbols import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.PrimitiveType -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrPackageFragment -import org.jetbrains.kotlin.ir.declarations.IrTypeParameter -import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol @@ -209,8 +206,16 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { private val EQUALS = Equals(KtTokens.EQEQ) private fun IrFunctionSymbol.toKey(): Key? { + val parent = owner.parent + val ownerFqName = when { + parent is IrClass && parent.origin == IrDeclarationOrigin.FILE_CLASS -> + (parent.parent as IrPackageFragment).fqName + parent is IrClass -> parent.fqNameWhenAvailable ?: return null + parent is IrPackageFragment -> parent.fqName + else -> return null + } return Key( - owner.parent.safeAs()?.fqNameWhenAvailable ?: owner.parent.safeAs()?.fqName ?: return null, + ownerFqName, getParameterFqName(owner.extensionReceiverParameter), owner.name.asString(), owner.valueParameters.map(::getParameterFqName) 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 eb7114458cd..b4aa1a2b5fc 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 @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.IrDeserializer import org.jetbrains.kotlin.ir.util.SymbolTable @@ -31,11 +32,13 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.utils.SmartList class Psi2IrTranslator( val languageVersionSettings: LanguageVersionSettings, - val configuration: Psi2IrConfiguration = Psi2IrConfiguration() + val configuration: Psi2IrConfiguration = Psi2IrConfiguration(), + val facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } ) { interface PostprocessingStep { fun postprocess(context: GeneratorContext, irElement: IrElement) @@ -78,7 +81,7 @@ class Psi2IrTranslator( irModule.patchDeclarationParents() postprocess(context, irModule) - moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer) + moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, facadeClassGenerator) 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 b7b7dbcd332..939393471ce 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 @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.backend.common.CodegenUtil +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.MetadataSource @@ -27,6 +28,7 @@ import org.jetbrains.kotlin.ir.util.IrDeserializer import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.utils.addIfNotNull class ModuleGenerator(override val context: GeneratorContext) : Generator { @@ -43,9 +45,18 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator { irModule.files.addAll(generateFiles(ktFiles)) } - fun generateUnboundSymbolsAsDependencies(irModule: IrModuleFragment, deserializer: IrDeserializer? = null) { + fun generateUnboundSymbolsAsDependencies( + irModule: IrModuleFragment, + deserializer: IrDeserializer? = null, + facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } + ) { ExternalDependenciesGenerator( - irModule.descriptor, context.symbolTable, context.irBuiltIns, context.extensions.externalDeclarationOrigin, deserializer + irModule.descriptor, + context.symbolTable, + context.irBuiltIns, + context.extensions.externalDeclarationOrigin, + deserializer, + facadeClassGenerator ).generateUnboundSymbolsAsDependencies() } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt index 83f3fa82769..38fffa3547d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt @@ -7,13 +7,9 @@ package org.jetbrains.kotlin.ir.declarations.lazy import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent -import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrDeclarationBase import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl -import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator import org.jetbrains.kotlin.ir.util.TypeTranslator @@ -68,8 +64,12 @@ abstract class IrLazyDeclarationBase( ((currentDescriptor as? PropertyAccessorDescriptor)?.correspondingProperty ?: currentDescriptor).containingDeclaration return when (containingDeclaration) { - is PackageFragmentDescriptor -> stubGenerator.generateOrGetEmptyExternalPackageFragmentStub(containingDeclaration).also { - it.declarations.add(this) + is PackageFragmentDescriptor -> run { + val parent = this.takeUnless { it is IrClass }?.let { + stubGenerator.generateOrGetFacadeClass(descriptor) + } ?: stubGenerator.generateOrGetEmptyExternalPackageFragmentStub(containingDeclaration) + parent.declarations.add(this) + parent } is ClassDescriptor -> stubGenerator.generateClassStub(containingDeclaration) is FunctionDescriptor -> stubGenerator.generateFunctionStub(containingDeclaration) 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 93f936aa345..bdfaacfbe75 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 @@ -26,14 +26,18 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.addToStdlib.safeAs class DeclarationStubGenerator( moduleDescriptor: ModuleDescriptor, val symbolTable: SymbolTable, languageVersionSettings: LanguageVersionSettings, private val externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = null, - private val deserializer: IrDeserializer? = null + private val deserializer: IrDeserializer? = null, + private val facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } ) { private val lazyTable = symbolTable.lazyWrapper @@ -47,6 +51,8 @@ class DeclarationStubGenerator( private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, moduleDescriptor.builtIns, LazyScopedTypeParametersResolver(lazyTable), true) private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable) + private val facadeClassMap = mutableMapOf() + init { typeTranslator.constantValueGenerator = constantValueGenerator constantValueGenerator.typeTranslator = typeTranslator @@ -60,6 +66,19 @@ class DeclarationStubGenerator( return symbolTable.declareExternalPackageFragment(descriptor) } + fun generateOrGetFacadeClass(descriptor: DeclarationDescriptor): IrClass? { + val packageFragment = descriptor.containingDeclaration as? PackageFragmentDescriptor ?: return null + val containerSource = descriptor.safeAs()?.containerSource ?: return null + return facadeClassMap.getOrPut(containerSource) { + facadeClassGenerator(containerSource)?.also { facade -> + val packageStub = generateOrGetEmptyExternalPackageFragmentStub(packageFragment) + facade.parent = packageStub + packageStub.declarations.add(facade) + } + } + } + + fun generateMemberStub(descriptor: DeclarationDescriptor): IrDeclaration = when (descriptor) { is ClassDescriptor -> 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 c4214715a23..5b85faeebc5 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 @@ -18,9 +18,11 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import kotlin.math.min class ExternalDependenciesGenerator( @@ -28,10 +30,11 @@ class ExternalDependenciesGenerator( val symbolTable: SymbolTable, val irBuiltIns: IrBuiltIns, externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = null, - private val deserializer: IrDeserializer? = null + private val deserializer: IrDeserializer? = null, + facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } ) { private val stubGenerator = DeclarationStubGenerator( - moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings, externalDeclarationOrigin, deserializer + moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings, externalDeclarationOrigin, deserializer, facadeClassGenerator ) fun generateUnboundSymbolsAsDependencies() { diff --git a/compiler/testData/codegen/box/ranges/unsigned/expression/overflowZeroDownToMaxValue.kt b/compiler/testData/codegen/box/ranges/unsigned/expression/overflowZeroDownToMaxValue.kt index 619b28c44fc..7d439e3a62d 100644 --- a/compiler/testData/codegen/box/ranges/unsigned/expression/overflowZeroDownToMaxValue.kt +++ b/compiler/testData/codegen/box/ranges/unsigned/expression/overflowZeroDownToMaxValue.kt @@ -1,6 +1,4 @@ // KJS_WITH_FULL_RUNTIME -// TODO: muted automatically, investigate should it be ran for JVM_IR or not -// IGNORE_BACKEND: JVM_IR // Auto-generated by org.jetbrains.kotlin.generators.tests.GenerateRangesCodegenTestData. DO NOT EDIT! // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/ranges/unsigned/literal/overflowZeroDownToMaxValue.kt b/compiler/testData/codegen/box/ranges/unsigned/literal/overflowZeroDownToMaxValue.kt index eccf33a93bd..0ee21c920e5 100644 --- a/compiler/testData/codegen/box/ranges/unsigned/literal/overflowZeroDownToMaxValue.kt +++ b/compiler/testData/codegen/box/ranges/unsigned/literal/overflowZeroDownToMaxValue.kt @@ -1,6 +1,4 @@ // KJS_WITH_FULL_RUNTIME -// TODO: muted automatically, investigate should it be ran for JVM_IR or not -// IGNORE_BACKEND: JVM_IR // Auto-generated by org.jetbrains.kotlin.generators.tests.GenerateRangesCodegenTestData. DO NOT EDIT! // WITH_RUNTIME