JVM_IR: generate facade classes for imported toplevel declarations

This commit is contained in:
Georgy Bronnikov
2019-06-20 18:38:10 +03:00
parent bb0f467f63
commit 3a9b94235f
10 changed files with 82 additions and 26 deletions
@@ -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<JvmPackagePartSource>() ?: return null
val facadeName = jvmPackagePartSource.facadeClassName ?: jvmPackagePartSource.className
return buildClass {
origin = IrDeclarationOrigin.FILE_CLASS
name = facadeName.fqNameForTopLevelClassMaybeWithDollars.shortName()
}.also {
it.createParameterDeclarations()
}
}
}
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager
class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory {
override fun generateModule(state: GenerationState, files: Collection<KtFile>, 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)
@@ -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<IrClass>()?.fqNameWhenAvailable ?: owner.parent.safeAs<IrPackageFragment>()?.fqName ?: return null,
ownerFqName,
getParameterFqName(owner.extensionReceiverParameter),
owner.name.asString(),
owner.valueParameters.map(::getParameterFqName)
@@ -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
}
@@ -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()
}
@@ -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)
@@ -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<DeserializedContainerSource, IrClass?>()
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<DescriptorWithContainerSource>()?.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 ->
@@ -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() {
@@ -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
@@ -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