Fir2Ir: introduce Fir2IrExtensions

This allows us to remove DeclarationStubGenerator from Fir2IrConverter,
thus reducing dependency on descriptor-based code.
This commit is contained in:
Georgy Bronnikov
2021-12-07 20:02:03 +03:00
committed by Alexander Udalov
parent 6bc01f031c
commit 3c3c1be543
14 changed files with 158 additions and 46 deletions
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsForFile
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
@@ -18,7 +19,6 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.FirSealedClassInheritorsProcessor
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.test.model.TestFile
class LowLevelFirAnalyzerFacade(
@@ -48,7 +48,7 @@ class LowLevelFirAnalyzerFacade(
}
override fun runResolution(): List<FirFile> = shouldNotBeCalled()
override fun convertToIr(extensions: GeneratorExtensions): Fir2IrResult = shouldNotBeCalled()
override fun convertToIr(fir2IrExtensions: Fir2IrExtensions): Fir2IrResult = shouldNotBeCalled()
}
private fun shouldNotBeCalled(): Nothing = error("Should not be called for LL test")
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
@@ -160,11 +161,15 @@ object FirKotlinToJvmBytecodeCompiler {
performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted()
val extensions = JvmGeneratorExtensionsImpl(moduleConfiguration)
val fir2IrResult = firResult.session.convertToIr(firResult.scopeSession, firResult.fir, extensions, irGenerationExtensions)
val fir2IrResult = firResult.session.convertToIr(
firResult.scopeSession, firResult.fir,
JvmFir2IrExtensions(moduleConfiguration),
irGenerationExtensions
)
performanceManager?.notifyIRTranslationFinished()
val extensions = JvmGeneratorExtensionsImpl(moduleConfiguration)
val generationState = runBackend(
allSources,
fir2IrResult,
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
import org.jetbrains.kotlin.fir.backend.jvm.Fir2IrJvmSpecialAnnotationSymbolProvider
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
@@ -26,7 +27,7 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
fun FirSession.convertToIr(
scopeSession: ScopeSession,
firFiles: List<FirFile>,
extensions: GeneratorExtensions,
fir2IrExtensions: Fir2IrExtensions,
irGeneratorExtensions: Collection<IrGenerationExtension>
): Fir2IrResult {
val mangler = JvmDescriptorMangler(null)
@@ -39,8 +40,9 @@ fun FirSession.convertToIr(
return Fir2IrConverter.createModuleFragment(
this, scopeSession, firFiles + commonFirFiles,
languageVersionSettings, mangler, signaturer,
extensions, FirJvmKotlinMangler(this), IrFactoryImpl,
languageVersionSettings, signaturer,
fir2IrExtensions,
FirJvmKotlinMangler(this), IrFactoryImpl,
FirJvmVisibilityConverter,
Fir2IrJvmSpecialAnnotationSymbolProvider(),
irGeneratorExtensions
@@ -15,8 +15,10 @@ dependencies {
compileOnly(project(":compiler:fir:fir2ir"))
compileOnly(project(":compiler:fir:fir-serialization"))
compileOnly(project(":compiler:ir.tree"))
compileOnly(project(":compiler:ir.tree.impl"))
compileOnly(project(":compiler:backend"))
compileOnly(project(":compiler:backend.jvm"))
compileOnly(project(":compiler:backend.jvm.entrypoint"))
api(project(":compiler:ir.serialization.common"))
compileOnly(intellijCore())
@@ -0,0 +1,71 @@
/*
* Copyright 2010-2021 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.fir.backend.jvm
import org.jetbrains.kotlin.backend.jvm.CachedFieldsForObjectInstances
import org.jetbrains.kotlin.backend.jvm.JvmFileFacadeClass
import org.jetbrains.kotlin.backend.jvm.JvmIrTypeSystemContext
import org.jetbrains.kotlin.backend.jvm.handleJvmStaticInSingletonObjects
import org.jetbrains.kotlin.backend.jvm.serialization.deserializeFromByteArray
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.JvmSerializeIrMode
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.FirIrProvider
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrMemberWithContainerSource
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
class JvmFir2IrExtensions(configuration: CompilerConfiguration) : Fir2IrExtensions {
// TODO: make these available to backend context
private val classNameOverride: MutableMap<IrClass, JvmClassName> = mutableMapOf()
private val cachedFields = CachedFieldsForObjectInstances(IrFactoryImpl, configuration.languageVersionSettings)
override val irNeedsDeserialization: Boolean =
configuration.get(JVMConfigurationKeys.SERIALIZE_IR, JvmSerializeIrMode.NONE) != JvmSerializeIrMode.NONE
override fun generateOrGetFacadeClass(declaration: IrMemberWithContainerSource, components: Fir2IrComponents): IrClass? {
val deserializedSource = declaration.containerSource ?: return null
if (deserializedSource !is FacadeClassSource) return null
val facadeName = deserializedSource.facadeClassName ?: deserializedSource.className
return JvmFileFacadeClass(
if (deserializedSource.facadeClassName != null) IrDeclarationOrigin.JVM_MULTIFILE_CLASS else IrDeclarationOrigin.FILE_CLASS,
facadeName.fqNameForTopLevelClassMaybeWithDollars.shortName(),
deserializedSource,
deserializeIr = { irClass -> deserializeToplevelClass(irClass, components) }
).also {
it.createParameterDeclarations()
classNameOverride[it] = facadeName
}
}
override fun deserializeToplevelClass(irClass: IrClass, components: Fir2IrComponents): Boolean {
with(components) {
val serializedIr = when (val source = irClass.source) {
is KotlinJvmBinarySourceElement -> source.binaryClass.classHeader.serializedIr
is JvmPackagePartSource -> source.knownJvmBinaryClass?.classHeader?.serializedIr
else -> null
} ?: return false
deserializeFromByteArray(
serializedIr,
irBuiltIns, symbolTable, listOf(FirIrProvider(this)),
irClass,
JvmIrTypeSystemContext(irBuiltIns), allowErrorNodes = false
)
irClass.handleJvmStaticInSingletonObjects(irBuiltIns, cachedFields)
return true
}
}
}
@@ -6,25 +6,26 @@
package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
// TODO: could be a lowering
internal class ExternalPackageParentPatcher(private val stubGenerator: DeclarationStubGenerator) : IrElementVisitorVoid {
// TODO: should be a lowering
internal class ExternalPackageParentPatcher(
private val components: Fir2IrComponents,
private val fir2IrExtensions: Fir2IrExtensions
) : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitMemberAccess(expression: IrMemberAccessExpression<*>) {
super.visitMemberAccess(expression)
val callee = expression.symbol.owner as? IrDeclaration ?: return
val callee = expression.symbol.owner as? IrMemberWithContainerSource ?: return
if (callee.parent is IrExternalPackageFragment) {
@OptIn(ObsoleteDescriptorBasedAPI::class)
val parentClass = stubGenerator.generateOrGetFacadeClass(callee.descriptor) ?: return
val parentClass = fir2IrExtensions.generateOrGetFacadeClass(callee, components) ?: return
parentClass.parent = callee.parent
callee.parent = parentClass
when (callee) {
is IrProperty -> handleProperty(callee, parentClass)
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.KtSourceFileLinesMappingFromLineStartOffsets
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinderImpl
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -47,8 +46,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.generators.DeclarationStubGeneratorImpl
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.resolve.BindingContext
class Fir2IrConverter(
@@ -67,8 +64,7 @@ class Fir2IrConverter(
irGenerationExtensions: Collection<IrGenerationExtension>,
fir2irVisitor: Fir2IrVisitor,
languageVersionSettings: LanguageVersionSettings,
descriptorMangler: KotlinMangler.DescriptorMangler,
extensions: StubGeneratorExtensions,
fir2IrExtensions: Fir2IrExtensions,
) {
for (firFile in allFirFiles) {
registerFileAndClasses(firFile, irModuleFragment)
@@ -105,12 +101,7 @@ class Fir2IrConverter(
firFile.accept(fir2irVisitor, null)
}
val stubGenerator = DeclarationStubGeneratorImpl(
irModuleFragment.descriptor, symbolTable, irBuiltIns,
DescriptorByIdSignatureFinderImpl(irModuleFragment.descriptor, descriptorMangler),
extensions
)
irModuleFragment.acceptVoid(ExternalPackageParentPatcher(stubGenerator))
irModuleFragment.acceptVoid(ExternalPackageParentPatcher(components, fir2IrExtensions))
evaluateConstants(irModuleFragment)
@@ -428,9 +419,8 @@ class Fir2IrConverter(
scopeSession: ScopeSession,
firFiles: List<FirFile>,
languageVersionSettings: LanguageVersionSettings,
descriptorMangler: KotlinMangler.DescriptorMangler,
signaturer: IdSignatureComposer,
generatorExtensions: GeneratorExtensions,
fir2IrExtensions: Fir2IrExtensions,
mangler: FirMangler,
irFactory: IrFactory,
visibilityConverter: Fir2IrVisibilityConverter,
@@ -478,8 +468,7 @@ class Fir2IrConverter(
}
converter.runSourcesConversion(
allFirFiles, irModuleFragment, irGenerationExtensions, fir2irVisitor, languageVersionSettings,
descriptorMangler, generatorExtensions
allFirFiles, irModuleFragment, irGenerationExtensions, fir2irVisitor, languageVersionSettings, fir2IrExtensions
)
return Fir2IrResult(irModuleFragment, symbolTable, components)
@@ -1257,15 +1257,14 @@ class Fir2IrDeclarationStorage(
private fun createIrLazyFunction(
fir: FirSimpleFunction,
signature: IdSignature,
lazyParent: Fir2IrLazyClass,
lazyParent: IrDeclarationParent,
declarationOrigin: IrDeclarationOrigin
): IrSimpleFunction {
val symbol = Fir2IrSimpleFunctionSymbol(signature, fir.containerSource)
val firFunctionSymbol = fir.symbol
val irFunction = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareSimpleFunction(signature, { symbol }) {
val isFakeOverride = firFunctionSymbol is FirNamedFunctionSymbol &&
fir.isSubstitutionOrIntersectionOverride &&
val isFakeOverride = fir.isSubstitutionOrIntersectionOverride &&
firFunctionSymbol.dispatchReceiverClassOrNull() !=
firFunctionSymbol.originalForSubstitutionOverride?.dispatchReceiverClassOrNull()
Fir2IrLazySimpleFunction(
@@ -1336,7 +1335,7 @@ class Fir2IrDeclarationStorage(
private fun createIrLazyProperty(
fir: FirProperty,
signature: IdSignature,
lazyParent: Fir2IrLazyClass,
lazyParent: IrDeclarationParent,
declarationOrigin: IrDeclarationOrigin
): IrProperty {
val symbol = Fir2IrPropertySymbol(signature, fir.containerSource)
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2021 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.fir.backend
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrMemberWithContainerSource
interface Fir2IrExtensions {
val irNeedsDeserialization: Boolean
fun generateOrGetFacadeClass(declaration: IrMemberWithContainerSource, components: Fir2IrComponents): IrClass?
fun deserializeToplevelClass(irClass: IrClass, components: Fir2IrComponents): Boolean
object Default : Fir2IrExtensions {
override val irNeedsDeserialization: Boolean
get() = false
override fun generateOrGetFacadeClass(declaration: IrMemberWithContainerSource, components: Fir2IrComponents): IrClass? = null
override fun deserializeToplevelClass(irClass: IrClass, components: Fir2IrComponents): Boolean = false
}
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2021 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.backend.jvm
import org.jetbrains.kotlin.backend.jvm.lower.SingletonObjectJvmStaticTransformer
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrClass
fun IrClass.handleJvmStaticInSingletonObjects(irBuiltIns: IrBuiltIns, cachedFields: CachedFieldsForObjectInstances) {
transform(SingletonObjectJvmStaticTransformer(irBuiltIns, cachedFields), null)
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.serialization.signature.PublicIdSignatureComputer
import org.jetbrains.kotlin.backend.jvm.lower.SingletonObjectJvmStaticTransformer
import org.jetbrains.kotlin.backend.jvm.serialization.deserializeFromByteArray
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
@@ -106,9 +105,7 @@ open class JvmGeneratorExtensionsImpl(
if (deserializedSource.facadeClassName != null) IrDeclarationOrigin.JVM_MULTIFILE_CLASS else IrDeclarationOrigin.FILE_CLASS,
facadeName.fqNameForTopLevelClassMaybeWithDollars.shortName(),
deserializedSource,
deserializeIr = { facade ->
stubGenerator.extensions.deserializeClass(facade, stubGenerator, facade.parent, allowErrorNodes = false)
}
deserializeIr = { facade -> deserializeClass(facade, stubGenerator, facade.parent, allowErrorNodes = false) }
).also {
it.createParameterDeclarations()
classNameOverride[it] = facadeName
@@ -132,7 +129,7 @@ open class JvmGeneratorExtensionsImpl(
irClass,
JvmIrTypeSystemContext(stubGenerator.irBuiltIns), allowErrorNodes
)
irClass.transform(SingletonObjectJvmStaticTransformer(stubGenerator.irBuiltIns, cachedFields), null)
irClass.handleJvmStaticInSingletonObjects(stubGenerator.irBuiltIns, cachedFields)
return true
}
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment
@@ -40,11 +41,13 @@ class Fir2IrResultsConverter(
): IrBackendInput {
val compilerConfigurationProvider = testServices.compilerConfigurationProvider
val configuration = compilerConfigurationProvider.getCompilerConfiguration(module)
val extensions = JvmGeneratorExtensionsImpl(configuration)
val (irModuleFragment, symbolTable, components) = inputArtifact.firAnalyzerFacade.convertToIr(extensions)
val (irModuleFragment, symbolTable, components) = inputArtifact.firAnalyzerFacade.convertToIr(
JvmFir2IrExtensions(configuration)
)
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
val extensions = JvmGeneratorExtensionsImpl(configuration)
val phaseConfig = configuration.get(CLIConfigurationKeys.PHASE_CONFIG)
val codegenFactory = JvmIrCodegenFactory(configuration, phaseConfig, jvmGeneratorExtensions = extensions)
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.fir.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions
import org.jetbrains.kotlin.fir.createSessionForTests
import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
@@ -113,10 +114,12 @@ object GenerationUtils {
emptyList(),
IrGenerationExtension.getInstances(project)
)
val extensions = JvmGeneratorExtensionsImpl(configuration)
val (moduleFragment, symbolTable, components) = firAnalyzerFacade.convertToIr(extensions)
val (moduleFragment, symbolTable, components) = firAnalyzerFacade.convertToIr(
JvmFir2IrExtensions(configuration)
)
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
val extensions = JvmGeneratorExtensionsImpl(configuration)
val codegenFactory = JvmIrCodegenFactory(
configuration,
configuration.get(CLIConfigurationKeys.PHASE_CONFIG),
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
import org.jetbrains.kotlin.fir.backend.jvm.Fir2IrJvmSpecialAnnotationSymbolProvider
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
@@ -36,7 +37,7 @@ abstract class AbstractFirAnalyzerFacade {
abstract fun runResolution(): List<FirFile>
abstract fun convertToIr(extensions: GeneratorExtensions): Fir2IrResult
abstract fun convertToIr(fir2IrExtensions: Fir2IrExtensions): Fir2IrResult
}
class FirAnalyzerFacade(
@@ -99,7 +100,7 @@ class FirAnalyzerFacade(
return collectedDiagnostics!!
}
override fun convertToIr(extensions: GeneratorExtensions): Fir2IrResult {
override fun convertToIr(fir2IrExtensions: Fir2IrExtensions): Fir2IrResult {
if (_scopeSession == null) runResolution()
val mangler = JvmDescriptorMangler(null)
val signaturer = JvmIdSignatureDescriptor(mangler)
@@ -111,8 +112,9 @@ class FirAnalyzerFacade(
return Fir2IrConverter.createModuleFragment(
session, _scopeSession!!, firFiles!! + commonFirFiles,
languageVersionSettings, mangler, signaturer,
extensions, FirJvmKotlinMangler(session), IrFactoryImpl,
languageVersionSettings, signaturer,
fir2IrExtensions,
FirJvmKotlinMangler(session), IrFactoryImpl,
FirJvmVisibilityConverter,
Fir2IrJvmSpecialAnnotationSymbolProvider(),
irGeneratorExtensions