Psi2ir: refactor ModuleGenerator.generateModuleFragment

Move `postprocess` into `generateSingleFile` and do those steps on each
file instead. This will allow to create
`GeneratorContext.callToSubstitutedDescriptorMap` for each file and
clear it after its only call site (InsertImplicitCasts) has used it.
Also simplify code a bit.
This commit is contained in:
Alexander Udalov
2020-10-22 13:47:54 +02:00
parent 7b53d668ab
commit 7ac981d4d3
3 changed files with 120 additions and 121 deletions
@@ -19,18 +19,19 @@ package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.linkage.IrDeserializer import org.jetbrains.kotlin.ir.linkage.IrDeserializer
import org.jetbrains.kotlin.ir.linkage.IrProvider import org.jetbrains.kotlin.ir.linkage.IrProvider
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.ConstantValueGenerator
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.noUnboundLeft
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.generators.* import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
@@ -76,12 +77,8 @@ class Psi2IrTranslator(
linkerExtensions: Collection<IrDeserializer.IrLinkerExtension>, linkerExtensions: Collection<IrDeserializer.IrLinkerExtension>,
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>? = null expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>? = null
): IrModuleFragment { ): IrModuleFragment {
val moduleGenerator = ModuleGenerator(context) val moduleGenerator = ModuleGenerator(context, expectDescriptorToSymbol)
val irModule = moduleGenerator.generateModuleFragmentWithoutDependencies(ktFiles) val irModule = moduleGenerator.generateModuleFragment(ktFiles)
irModule.patchDeclarationParents()
expectDescriptorToSymbol?.let { referenceExpectsForUsedActuals(it, context.symbolTable, irModule) }
postprocess(context, irModule)
val deserializers = irProviders.filterIsInstance<IrDeserializer>() val deserializers = irProviders.filterIsInstance<IrDeserializer>()
deserializers.forEach { it.init(irModule, linkerExtensions) } deserializers.forEach { it.init(irModule, linkerExtensions) }
@@ -100,22 +97,4 @@ class Psi2IrTranslator(
return irModule return irModule
} }
private fun postprocess(context: GeneratorContext, irElement: IrModuleFragment) {
generateSyntheticDeclarations(irElement, context)
insertImplicitCasts(irElement, context)
generateAnnotationsForDeclarations(context, irElement)
irElement.patchDeclarationParents()
}
private fun generateAnnotationsForDeclarations(context: GeneratorContext, irElement: IrElement) {
val annotationGenerator = AnnotationGenerator(context)
irElement.acceptVoid(annotationGenerator)
}
private fun generateSyntheticDeclarations(moduleFragment: IrModuleFragment, context: GeneratorContext) {
val generator = IrSyntheticDeclarationGenerator(context)
moduleFragment.acceptChildrenVoid(generator)
}
} }
@@ -1,3 +1,8 @@
/*
* Copyright 2010-2020 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.psi2ir.generators package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -11,80 +16,84 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.resolve.multiplatform.findExpects import org.jetbrains.kotlin.resolve.multiplatform.findExpects
// Need to create unbound symbols for expects corresponding to actuals of the currently compiled module. // Need to create unbound symbols for expects corresponding to actuals of the currently compiled module.
// This is neccessary because there is no explicit links between expects and actuals // This is necessary because there are no explicit links between expects and actuals
// neither in descriptors nor in IR. // neither in descriptors nor in IR.
fun referenceExpectsForUsedActuals( internal fun referenceExpectsForUsedActuals(
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
symbolTable: SymbolTable, symbolTable: SymbolTable,
irModule: IrModuleFragment element: IrElement,
) { ) {
irModule.acceptVoid(object : IrElementVisitorVoid { element.acceptVoid(ExpectDependencyGenerator(expectDescriptorToSymbol, symbolTable))
}
private fun <T> T.forEachExpect(body: (DeclarationDescriptor) -> Unit) where T : IrDeclaration {
this.descriptor.findExpects().forEach { private class ExpectDependencyGenerator(
body(it) private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
} private val symbolTable: SymbolTable,
} ) : IrElementVisitorVoid {
private fun <T> T.forEachExpect(body: (DeclarationDescriptor) -> Unit) where T : IrDeclaration {
override fun visitElement(element: IrElement) { this.descriptor.findExpects().forEach {
element.acceptChildrenVoid(this) body(it)
} }
}
override fun visitClass(declaration: IrClass) {
declaration.forEachExpect { expectDescriptor -> override fun visitElement(element: IrElement) {
val symbol = symbolTable.referenceClass(expectDescriptor as ClassDescriptor) element.acceptChildrenVoid(this)
expectDescriptorToSymbol[expectDescriptor] = symbol }
expectDescriptor.constructors.forEach {
expectDescriptorToSymbol[it] = symbolTable.referenceConstructor(it as ClassConstructorDescriptor) override fun visitClass(declaration: IrClass) {
} declaration.forEachExpect { expectDescriptor ->
} val symbol = symbolTable.referenceClass(expectDescriptor as ClassDescriptor)
super.visitDeclaration(declaration) expectDescriptorToSymbol[expectDescriptor] = symbol
} expectDescriptor.constructors.forEach {
expectDescriptorToSymbol[it] = symbolTable.referenceConstructor(it as ClassConstructorDescriptor)
override fun visitSimpleFunction(declaration: IrSimpleFunction) { }
declaration.forEachExpect { }
val symbol = symbolTable.referenceSimpleFunction(it as FunctionDescriptor) super.visitDeclaration(declaration)
expectDescriptorToSymbol[it] = symbol }
}
super.visitDeclaration(declaration) override fun visitSimpleFunction(declaration: IrSimpleFunction) {
} declaration.forEachExpect {
val symbol = symbolTable.referenceSimpleFunction(it as FunctionDescriptor)
override fun visitConstructor(declaration: IrConstructor) { expectDescriptorToSymbol[it] = symbol
declaration.forEachExpect { }
val symbol = symbolTable.referenceConstructor(it as ClassConstructorDescriptor) super.visitDeclaration(declaration)
expectDescriptorToSymbol[it] = symbol }
} override fun visitConstructor(declaration: IrConstructor) {
super.visitDeclaration(declaration) declaration.forEachExpect {
} val symbol = symbolTable.referenceConstructor(it as ClassConstructorDescriptor)
expectDescriptorToSymbol[it] = symbol
override fun visitProperty(declaration: IrProperty) {
declaration.forEachExpect { }
val symbol = symbolTable.referenceProperty(it as PropertyDescriptor) super.visitDeclaration(declaration)
expectDescriptorToSymbol[it] = symbol }
}
super.visitDeclaration(declaration) override fun visitProperty(declaration: IrProperty) {
} declaration.forEachExpect {
val symbol = symbolTable.referenceProperty(it as PropertyDescriptor)
override fun visitEnumEntry(declaration: IrEnumEntry) { expectDescriptorToSymbol[it] = symbol
declaration.forEachExpect { }
val symbol = symbolTable.referenceEnumEntry(it as ClassDescriptor) super.visitDeclaration(declaration)
expectDescriptorToSymbol[it] = symbol }
} override fun visitEnumEntry(declaration: IrEnumEntry) {
super.visitDeclaration(declaration) declaration.forEachExpect {
} val symbol = symbolTable.referenceEnumEntry(it as ClassDescriptor)
expectDescriptorToSymbol[it] = symbol
override fun visitTypeAlias(declaration: IrTypeAlias) {
declaration.forEachExpect { }
val symbol = when (it) { super.visitDeclaration(declaration)
is ClassDescriptor -> symbolTable.referenceClass(it) }
else -> error("Unexpected expect for actual type alias: $it")
} override fun visitTypeAlias(declaration: IrTypeAlias) {
expectDescriptorToSymbol[it] = symbol declaration.forEachExpect {
val symbol = when (it) {
} is ClassDescriptor -> symbolTable.referenceClass(it)
super.visitDeclaration(declaration) else -> error("Unexpected expect for actual type alias: $it")
} }
}) expectDescriptorToSymbol[it] = symbol
}
super.visitDeclaration(declaration)
}
} }
@@ -17,31 +17,38 @@
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.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource
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.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.linkage.IrDeserializer import org.jetbrains.kotlin.ir.linkage.IrDeserializer
import org.jetbrains.kotlin.ir.linkage.IrProvider import org.jetbrains.kotlin.ir.linkage.IrProvider
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts
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.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
class ModuleGenerator(override val context: GeneratorContext) : Generator { class ModuleGenerator(
override val context: GeneratorContext,
private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>? = null
) : Generator {
private val constantValueGenerator = context.constantValueGenerator private val constantValueGenerator = context.constantValueGenerator
fun generateModuleFragment(ktFiles: Collection<KtFile>, deserializer: IrDeserializer, extensions: StubGeneratorExtensions = StubGeneratorExtensions.EMPTY): IrModuleFragment = fun generateModuleFragment(ktFiles: Collection<KtFile>): IrModuleFragment =
generateModuleFragmentWithoutDependencies(ktFiles).also { irModule ->
generateUnboundSymbolsAsDependencies(irModule, deserializer, extensions)
}
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)) val irDeclarationGenerator = DeclarationGenerator(context)
ktFiles.mapTo(irModule.files) { ktFile ->
generateSingleFile(irDeclarationGenerator, ktFile)
}
} }
fun generateUnboundSymbolsAsDependencies( fun generateUnboundSymbolsAsDependencies(
@@ -62,14 +69,6 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
.generateUnboundSymbolsAsDependencies() .generateUnboundSymbolsAsDependencies()
} }
private fun generateFiles(ktFiles: Collection<KtFile>): List<IrFile> {
val irDeclarationGenerator = DeclarationGenerator(context)
return ktFiles.map { ktFile ->
generateSingleFile(irDeclarationGenerator, ktFile)
}
}
private fun generateSingleFile(irDeclarationGenerator: DeclarationGenerator, ktFile: KtFile): IrFileImpl { private fun generateSingleFile(irDeclarationGenerator: DeclarationGenerator, ktFile: KtFile): IrFileImpl {
val irFile = createEmptyIrFile(ktFile) val irFile = createEmptyIrFile(ktFile)
@@ -84,6 +83,18 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
irFile.declarations.addIfNotNull(irDeclarationGenerator.generateMemberDeclaration(ktDeclaration)) irFile.declarations.addIfNotNull(irDeclarationGenerator.generateMemberDeclaration(ktDeclaration))
} }
irFile.patchDeclarationParents()
if (expectDescriptorToSymbol != null) {
referenceExpectsForUsedActuals(expectDescriptorToSymbol, context.symbolTable, irFile)
}
irFile.acceptChildrenVoid(IrSyntheticDeclarationGenerator(context))
insertImplicitCasts(irFile, context)
irFile.acceptVoid(AnnotationGenerator(context))
irFile.patchDeclarationParents()
return irFile return irFile
} }