IR: introduce StubGeneratorExtensions for ExternalDependenciesGenerator

This is a refactoring to simplify the API of
ExternalDependenciesGenerator and to constrain future additions of
platform-specific stub generator extensions.
This commit is contained in:
Alexander Udalov
2019-11-18 16:02:47 +01:00
parent c3af2d5a10
commit 608449f41d
13 changed files with 114 additions and 134 deletions
@@ -56,6 +56,7 @@ object Fir2IrConverter {
symbolTable: SymbolTable, symbolTable: SymbolTable,
builtIns: IrBuiltIns builtIns: IrBuiltIns
) { ) {
// TODO: provide StubGeneratorExtensions for correct lazy stub IR generation on JVM
ExternalDependenciesGenerator(irModule.descriptor, symbolTable, builtIns).generateUnboundSymbolsAsDependencies() ExternalDependenciesGenerator(irModule.descriptor, symbolTable, builtIns).generateUnboundSymbolsAsDependencies()
} }
} }
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.ir.backend.js package org.jetbrains.kotlin.ir.backend.js
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -18,6 +17,7 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.DFS
@@ -57,12 +57,7 @@ fun compile(
// Load declarations referenced during `context` initialization // Load declarations referenced during `context` initialization
dependencyModules.forEach { dependencyModules.forEach {
ExternalDependenciesGenerator( ExternalDependenciesGenerator(it.descriptor, symbolTable, irBuiltIns, deserializer).generateUnboundSymbolsAsDependencies()
it.descriptor,
symbolTable,
irBuiltIns,
deserializer = deserializer
).generateUnboundSymbolsAsDependencies()
} }
val irFiles = dependencyModules.flatMap { it.files } + moduleFragment.files val irFiles = dependencyModules.flatMap { it.files } + moduleFragment.files
@@ -71,11 +66,7 @@ fun compile(
moduleFragment.files += irFiles moduleFragment.files += irFiles
// Create stubs // Create stubs
ExternalDependenciesGenerator( ExternalDependenciesGenerator(moduleDescriptor, symbolTable, irBuiltIns).generateUnboundSymbolsAsDependencies()
moduleDescriptor = moduleDescriptor,
symbolTable = symbolTable,
irBuiltIns = irBuiltIns
).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents() moduleFragment.patchDeclarationParents()
moveBodilessDeclarationsToSeparatePlace(context, moduleFragment) moveBodilessDeclarationsToSeparatePlace(context, moduleFragment)
@@ -6,27 +6,20 @@
package org.jetbrains.kotlin.backend.jvm package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
import org.jetbrains.kotlin.codegen.CompilationErrorHandler import org.jetbrains.kotlin.codegen.CompilationErrorHandler
import org.jetbrains.kotlin.codegen.state.GenerationState 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.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object JvmBackendFacade { object JvmBackendFacade {
fun doGenerateFiles( fun doGenerateFiles(
@@ -35,12 +28,12 @@ object JvmBackendFacade {
errorHandler: CompilationErrorHandler, errorHandler: CompilationErrorHandler,
phaseConfig: PhaseConfig phaseConfig: PhaseConfig
) { ) {
val facadeGenerator = FacadeClassGenerator() val psi2ir = Psi2IrTranslator(state.languageVersionSettings)
val psi2ir = Psi2IrTranslator(state.languageVersionSettings, facadeClassGenerator = facadeGenerator::generate)
val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = JvmGeneratorExtensions) val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = JvmGeneratorExtensions)
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files) val extensions = JvmStubGeneratorExtensions()
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, stubGeneratorExtensions = extensions)
doGenerateFilesInternal( doGenerateFilesInternal(
state, errorHandler, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, facadeGenerator state, errorHandler, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, extensions
) )
} }
@@ -51,7 +44,7 @@ object JvmBackendFacade {
symbolTable: SymbolTable, symbolTable: SymbolTable,
sourceManager: PsiSourceManager, sourceManager: PsiSourceManager,
phaseConfig: PhaseConfig, phaseConfig: PhaseConfig,
facadeGenerator: FacadeClassGenerator = FacadeClassGenerator() extensions: JvmStubGeneratorExtensions = JvmStubGeneratorExtensions()
) { ) {
val context = JvmBackendContext( val context = JvmBackendContext(
state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig
@@ -62,15 +55,15 @@ object JvmBackendFacade {
state.mapInlineClass = { descriptor -> state.mapInlineClass = { descriptor ->
context.typeMapper.mapType(context.referenceClass(descriptor).defaultType) context.typeMapper.mapType(context.referenceClass(descriptor).defaultType)
} }
//TODO
ExternalDependenciesGenerator( ExternalDependenciesGenerator(
irModuleFragment.descriptor, irModuleFragment.descriptor,
symbolTable, symbolTable,
irModuleFragment.irBuiltins, irModuleFragment.irBuiltins,
JvmGeneratorExtensions.externalDeclarationOrigin, extensions = extensions
facadeClassGenerator = facadeGenerator::generate
).generateUnboundSymbolsAsDependencies() ).generateUnboundSymbolsAsDependencies()
context.classNameOverride = facadeGenerator.classNameOverride
context.classNameOverride = extensions.classNameOverride
for (irFile in irModuleFragment.files) { for (irFile in irModuleFragment.files) {
for (extension in IrGenerationExtension.getInstances(context.state.project)) { for (extension in IrGenerationExtension.getInstances(context.state.project)) {
@@ -107,20 +100,4 @@ object JvmBackendFacade {
} }
} }
} }
internal class FacadeClassGenerator {
val classNameOverride = mutableMapOf<IrClass, JvmClassName>()
fun generate(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()
classNameOverride[it] = facadeName
}
}
}
} }
@@ -5,31 +5,31 @@
package org.jetbrains.kotlin.backend.jvm package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
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.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
object JvmGeneratorExtensions : GeneratorExtensions() { object JvmGeneratorExtensions : GeneratorExtensions() {
override val externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = { descriptor ->
if (descriptor is JavaCallableMemberDescriptor)
IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
else
IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
}
override val samConversion: SamConversion override val samConversion: SamConversion
get() = JvmSamConversion get() = JvmSamConversion
@@ -66,3 +66,25 @@ object JvmGeneratorExtensions : GeneratorExtensions() {
else else
null null
} }
class JvmStubGeneratorExtensions : StubGeneratorExtensions() {
val classNameOverride = mutableMapOf<IrClass, JvmClassName>()
override fun computeExternalDeclarationOrigin(descriptor: DeclarationDescriptor): IrDeclarationOrigin? =
if (descriptor is JavaCallableMemberDescriptor)
IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
else
IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
override fun generateFacadeClass(source: DeserializedContainerSource): IrClass? {
val jvmPackagePartSource = source as? JvmPackagePartSource ?: return null
val facadeName = jvmPackagePartSource.facadeClassName ?: jvmPackagePartSource.className
return buildClass {
origin = IrDeclarationOrigin.FILE_CLASS
name = facadeName.fqNameForTopLevelClassMaybeWithDollars.shortName()
}.also {
it.createParameterDeclarations()
classNameOverride[it] = facadeName
}
}
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.backend.wasm package org.jetbrains.kotlin.backend.wasm
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.backend.wasm.codegen.IrModuleToWasm import org.jetbrains.kotlin.backend.wasm.codegen.IrModuleToWasm
@@ -15,6 +14,7 @@ import org.jetbrains.kotlin.ir.backend.js.loadIr
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -37,12 +37,7 @@ fun compileWasm(
// Load declarations referenced during `context` initialization // Load declarations referenced during `context` initialization
dependencyModules.forEach { dependencyModules.forEach {
ExternalDependenciesGenerator( ExternalDependenciesGenerator(it.descriptor, symbolTable, irBuiltIns, deserializer).generateUnboundSymbolsAsDependencies()
it.descriptor,
symbolTable,
irBuiltIns,
deserializer = deserializer
).generateUnboundSymbolsAsDependencies()
} }
val irFiles = dependencyModules.flatMap { it.files } + moduleFragment.files val irFiles = dependencyModules.flatMap { it.files } + moduleFragment.files
@@ -51,11 +46,7 @@ fun compileWasm(
moduleFragment.files += irFiles moduleFragment.files += irFiles
// Create stubs // Create stubs
ExternalDependenciesGenerator( ExternalDependenciesGenerator(moduleDescriptor, symbolTable, irBuiltIns).generateUnboundSymbolsAsDependencies()
moduleDescriptor = moduleDescriptor,
symbolTable = symbolTable,
irBuiltIns = irBuiltIns
).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents() moduleFragment.patchDeclarationParents()
wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment) wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment)
@@ -19,12 +19,8 @@ package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrElement 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.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.IrDeserializer import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.IrProvider
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.generators.AnnotationGenerator import org.jetbrains.kotlin.psi2ir.generators.AnnotationGenerator
@@ -33,13 +29,11 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator
import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
class Psi2IrTranslator( class Psi2IrTranslator(
val languageVersionSettings: LanguageVersionSettings, val languageVersionSettings: LanguageVersionSettings,
val configuration: Psi2IrConfiguration = Psi2IrConfiguration(), val configuration: Psi2IrConfiguration = Psi2IrConfiguration()
val facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null }
) { ) {
interface PostprocessingStep { interface PostprocessingStep {
fun postprocess(context: GeneratorContext, irElement: IrElement) fun postprocess(context: GeneratorContext, irElement: IrElement)
@@ -55,10 +49,11 @@ class Psi2IrTranslator(
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
ktFiles: Collection<KtFile>, ktFiles: Collection<KtFile>,
bindingContext: BindingContext, bindingContext: BindingContext,
generatorExtensions: GeneratorExtensions generatorExtensions: GeneratorExtensions,
stubGeneratorExtensions: StubGeneratorExtensions
): IrModuleFragment { ): IrModuleFragment {
val context = createGeneratorContext(moduleDescriptor, bindingContext, extensions = generatorExtensions) val context = createGeneratorContext(moduleDescriptor, bindingContext, extensions = generatorExtensions)
return generateModuleFragment(context, ktFiles) return generateModuleFragment(context, ktFiles, stubGeneratorExtensions = stubGeneratorExtensions)
} }
fun createGeneratorContext( fun createGeneratorContext(
@@ -73,17 +68,18 @@ class Psi2IrTranslator(
context: GeneratorContext, context: GeneratorContext,
ktFiles: Collection<KtFile>, ktFiles: Collection<KtFile>,
deserializer: IrDeserializer? = null, deserializer: IrDeserializer? = null,
irProviders: List<IrProvider> = emptyList() irProviders: List<IrProvider> = emptyList(),
stubGeneratorExtensions: StubGeneratorExtensions = StubGeneratorExtensions()
): IrModuleFragment { ): IrModuleFragment {
val moduleGenerator = ModuleGenerator(context) val moduleGenerator = ModuleGenerator(context)
val irModule = moduleGenerator.generateModuleFragmentWithoutDependencies(ktFiles) val irModule = moduleGenerator.generateModuleFragment(ktFiles)
// This is required for implicit casts insertion on IrTypes (work-in-progress). // This is required for implicit casts insertion on IrTypes (work-in-progress).
moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, facadeClassGenerator) moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, stubGeneratorExtensions)
irModule.patchDeclarationParents() irModule.patchDeclarationParents()
postprocess(context, irModule) postprocess(context, irModule)
moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, facadeClassGenerator) moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, stubGeneratorExtensions)
return irModule return irModule
} }
@@ -6,16 +6,11 @@
package org.jetbrains.kotlin.psi2ir.generators package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
open class GeneratorExtensions { open class GeneratorExtensions {
open val externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)?
get() = null
open val samConversion: SamConversion open val samConversion: SamConversion
get() = SamConversion get() = SamConversion
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.psi2ir.generators package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.backend.common.CodegenUtil 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.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.MetadataSource import org.jetbrains.kotlin.ir.declarations.MetadataSource
@@ -26,10 +25,10 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.IrDeserializer import org.jetbrains.kotlin.ir.util.IrDeserializer
import org.jetbrains.kotlin.ir.util.IrProvider import org.jetbrains.kotlin.ir.util.IrProvider
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
class ModuleGenerator(override val context: GeneratorContext) : Generator { class ModuleGenerator(override val context: GeneratorContext) : Generator {
@@ -37,11 +36,6 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
private val constantValueGenerator = context.constantValueGenerator private val constantValueGenerator = context.constantValueGenerator
fun generateModuleFragment(ktFiles: Collection<KtFile>): IrModuleFragment = fun generateModuleFragment(ktFiles: Collection<KtFile>): IrModuleFragment =
generateModuleFragmentWithoutDependencies(ktFiles).also { irModule ->
generateUnboundSymbolsAsDependencies(irModule)
}
fun generateModuleFragmentWithoutDependencies(ktFiles: Collection<KtFile>): IrModuleFragment =
IrModuleFragmentImpl(context.moduleDescriptor, context.irBuiltIns).also { irModule -> IrModuleFragmentImpl(context.moduleDescriptor, context.irBuiltIns).also { irModule ->
irModule.files.addAll(generateFiles(ktFiles)) irModule.files.addAll(generateFiles(ktFiles))
} }
@@ -50,16 +44,10 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
irModule: IrModuleFragment, irModule: IrModuleFragment,
deserializer: IrDeserializer? = null, deserializer: IrDeserializer? = null,
irProviders: List<IrProvider> = emptyList(), irProviders: List<IrProvider> = emptyList(),
facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY
) { ) {
ExternalDependenciesGenerator( ExternalDependenciesGenerator(
irModule.descriptor, irModule.descriptor, context.symbolTable, context.irBuiltIns, deserializer, irProviders, extensions
context.symbolTable,
context.irBuiltIns,
context.extensions.externalDeclarationOrigin,
deserializer,
irProviders,
facadeClassGenerator
).generateUnboundSymbolsAsDependencies() ).generateUnboundSymbolsAsDependencies()
} }
@@ -36,9 +36,8 @@ class DeclarationStubGenerator(
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
languageVersionSettings: LanguageVersionSettings, languageVersionSettings: LanguageVersionSettings,
private val externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = null,
private val irProviders: List<IrProvider> = emptyList(), private val irProviders: List<IrProvider> = emptyList(),
private val facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } private val extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY
) { ) {
private val lazyTable = symbolTable.lazyWrapper private val lazyTable = symbolTable.lazyWrapper
@@ -49,7 +48,8 @@ class DeclarationStubGenerator(
} }
val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, moduleDescriptor.builtIns, LazyScopedTypeParametersResolver(lazyTable), true) val typeTranslator =
TypeTranslator(lazyTable, languageVersionSettings, moduleDescriptor.builtIns, LazyScopedTypeParametersResolver(lazyTable), true)
private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable) private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable)
private val facadeClassMap = mutableMapOf<DeserializedContainerSource, IrClass?>() private val facadeClassMap = mutableMapOf<DeserializedContainerSource, IrClass?>()
@@ -79,7 +79,7 @@ class DeclarationStubGenerator(
val packageFragment = directMember.containingDeclaration as? PackageFragmentDescriptor ?: return null val packageFragment = directMember.containingDeclaration as? PackageFragmentDescriptor ?: return null
val containerSource = directMember.safeAs<DescriptorWithContainerSource>()?.containerSource ?: return null val containerSource = directMember.safeAs<DescriptorWithContainerSource>()?.containerSource ?: return null
return facadeClassMap.getOrPut(containerSource) { return facadeClassMap.getOrPut(containerSource) {
facadeClassGenerator(containerSource)?.also { facade -> extensions.generateFacadeClass(containerSource)?.also { facade ->
val packageStub = generateOrGetEmptyExternalPackageFragmentStub(packageFragment) val packageStub = generateOrGetEmptyExternalPackageFragmentStub(packageFragment)
facade.parent = packageStub facade.parent = packageStub
packageStub.declarations.add(facade) packageStub.declarations.add(facade)
@@ -106,7 +106,7 @@ class DeclarationStubGenerator(
} }
private fun computeOrigin(descriptor: DeclarationDescriptor): IrDeclarationOrigin = private fun computeOrigin(descriptor: DeclarationDescriptor): IrDeclarationOrigin =
externalDeclarationOrigin?.invoke(descriptor) ?: IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB extensions.computeExternalDeclarationOrigin(descriptor) ?: IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
internal fun generatePropertyStub( internal fun generatePropertyStub(
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
@@ -16,34 +16,28 @@
package org.jetbrains.kotlin.ir.util package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor 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.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import kotlin.math.min import kotlin.math.min
class ExternalDependenciesGenerator( class ExternalDependenciesGenerator(
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
val irBuiltIns: IrBuiltIns, val irBuiltIns: IrBuiltIns,
externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = null,
private val deserializer: IrDeserializer? = null, private val deserializer: IrDeserializer? = null,
irProviders: List<IrProvider> = emptyList(), irProviders: List<IrProvider> = emptyList(),
facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY
) { ) {
private val stubGenerator = DeclarationStubGenerator( private val stubGenerator = DeclarationStubGenerator(
moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings, externalDeclarationOrigin, moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings, listOfNotNull(deserializer) + irProviders, extensions
listOfNotNull(deserializer) + irProviders, facadeClassGenerator
) )
fun generateUnboundSymbolsAsDependencies() { fun generateUnboundSymbolsAsDependencies() {
stubGenerator.unboundSymbolGeneration = true stubGenerator.unboundSymbolGeneration = true
do { do {
fun <T> haveNotStabilized(prev: ArrayList<T>, cur: Set<T>) = fun <T> haveNotStabilized(prev: ArrayList<T>, cur: Set<T>) =
cur.isNotEmpty() && (prev.size != cur.size || prev.any { !cur.contains(it) }) cur.isNotEmpty() && (prev.size != cur.size || prev.any { !cur.contains(it) })
val unboundClasses = ArrayList(symbolTable.unboundClasses) val unboundClasses = ArrayList(symbolTable.unboundClasses)
val unboundConstructors = ArrayList(symbolTable.unboundConstructors) val unboundConstructors = ArrayList(symbolTable.unboundConstructors)
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
open class StubGeneratorExtensions {
open fun computeExternalDeclarationOrigin(descriptor: DeclarationDescriptor): IrDeclarationOrigin? = null
open fun generateFacadeClass(source: DeserializedContainerSource): IrClass? = null
companion object {
@JvmField
val EMPTY = StubGeneratorExtensions()
}
}
@@ -16,16 +16,19 @@
package org.jetbrains.kotlin.ir package org.jetbrains.kotlin.ir
import junit.framework.TestCase
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions
import org.jetbrains.kotlin.backend.jvm.JvmStubGeneratorExtensions
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.CodegenTestCase import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsGeneratorExtensions import org.jetbrains.kotlin.ir.backend.js.JsGeneratorExtensions
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
@@ -37,8 +40,6 @@ import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar import org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar
import java.io.File import java.io.File
import java.io.FileWriter
import java.io.PrintWriter
import java.util.* import java.util.*
abstract class AbstractIrGeneratorTestCase : CodegenTestCase() { abstract class AbstractIrGeneratorTestCase : CodegenTestCase() {
@@ -114,27 +115,39 @@ abstract class AbstractIrGeneratorTestCase : CodegenTestCase() {
moduleDescriptors = emptyList(), moduleDescriptors = emptyList(),
friendModuleDescriptors = emptyList() friendModuleDescriptors = emptyList()
), ),
psi2ir, ktFilesToAnalyze, JsGeneratorExtensions() psi2ir, ktFilesToAnalyze, JsGeneratorExtensions(), StubGeneratorExtensions.EMPTY
) )
fun generateIrModuleWithJvmResolve( fun generateIrModuleWithJvmResolve(
ktFilesToAnalyze: List<KtFile>, environment: KotlinCoreEnvironment, psi2ir: Psi2IrTranslator ktFilesToAnalyze: List<KtFile>, environment: KotlinCoreEnvironment, psi2ir: Psi2IrTranslator
): IrModuleFragment = ): IrModuleFragment =
generateIrModule(JvmResolveUtil.analyze(ktFilesToAnalyze, environment), psi2ir, ktFilesToAnalyze, JvmGeneratorExtensions) generateIrModule(
JvmResolveUtil.analyze(ktFilesToAnalyze, environment), psi2ir, ktFilesToAnalyze, JvmGeneratorExtensions,
IrTestStubGeneratorExtensions
)
private fun generateIrModule( private fun generateIrModule(
analysisResult: AnalysisResult, analysisResult: AnalysisResult,
psi2ir: Psi2IrTranslator, psi2ir: Psi2IrTranslator,
ktFilesToAnalyze: List<KtFile>, ktFilesToAnalyze: List<KtFile>,
generatorExtensions: GeneratorExtensions generatorExtensions: GeneratorExtensions,
stubGeneratorExtensions: StubGeneratorExtensions
): IrModuleFragment { ): IrModuleFragment {
if (!psi2ir.configuration.ignoreErrors) { if (!psi2ir.configuration.ignoreErrors) {
analysisResult.throwIfError() analysisResult.throwIfError()
AnalyzingUtils.throwExceptionOnErrors(analysisResult.bindingContext) AnalyzingUtils.throwExceptionOnErrors(analysisResult.bindingContext)
} }
return psi2ir.generateModule( return psi2ir.generateModule(
analysisResult.moduleDescriptor, ktFilesToAnalyze, analysisResult.bindingContext, generatorExtensions analysisResult.moduleDescriptor, ktFilesToAnalyze, analysisResult.bindingContext, generatorExtensions,
stubGeneratorExtensions
) )
} }
} }
private object IrTestStubGeneratorExtensions : StubGeneratorExtensions() {
private val jvm = JvmStubGeneratorExtensions()
override fun computeExternalDeclarationOrigin(descriptor: DeclarationDescriptor): IrDeclarationOrigin? =
jvm.computeExternalDeclarationOrigin(descriptor)
}
} }
@@ -12,8 +12,8 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
import org.jetbrains.kotlin.ir.backend.js.emptyLoggingContext import org.jetbrains.kotlin.ir.backend.js.emptyLoggingContext
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsMangler 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.backend.js.utils.NameTables
@@ -51,12 +51,7 @@ class JsScriptDependencyCompiler(
val moduleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns) val moduleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns)
val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it) } val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it) }
ExternalDependenciesGenerator( ExternalDependenciesGenerator(moduleDescriptor, symbolTable, irBuiltIns, jsLinker).generateUnboundSymbolsAsDependencies()
moduleDescriptor = moduleDescriptor,
symbolTable = symbolTable,
irBuiltIns = irBuiltIns,
deserializer = jsLinker
).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents() moduleFragment.patchDeclarationParents()
val backendContext = JsIrBackendContext( val backendContext = JsIrBackendContext(
@@ -69,12 +64,7 @@ class JsScriptDependencyCompiler(
true true
) )
ExternalDependenciesGenerator( ExternalDependenciesGenerator(moduleDescriptor, symbolTable, irBuiltIns, jsLinker).generateUnboundSymbolsAsDependencies()
moduleDescriptor = moduleDescriptor,
symbolTable = symbolTable,
irBuiltIns = irBuiltIns,
deserializer = jsLinker
).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents() moduleFragment.patchDeclarationParents()
moduleFragment.files += irDependencies.flatMap { it.files } moduleFragment.files += irDependencies.flatMap { it.files }