[FIR] Implement support for MPP in Native

^KT-56071
This commit is contained in:
Svyatoslav Scherbina
2023-01-26 16:49:20 +01:00
committed by Space Team
parent cf4934f539
commit d8bae5a6f8
5 changed files with 73 additions and 76 deletions
@@ -16,16 +16,10 @@ import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentTypeTransformer import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentTypeTransformer
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.jvm.Fir2IrJvmSpecialAnnotationSymbolProvider
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
@@ -36,10 +30,6 @@ internal fun PhaseContext.fir2Ir(
input: FirOutput.Full, input: FirOutput.Full,
): Fir2IrOutput { ): Fir2IrOutput {
val fir2IrExtensions = Fir2IrExtensions.Default val fir2IrExtensions = Fir2IrExtensions.Default
val commonFirFiles = input.session.moduleData.dependsOnDependencies
.map { it.session }
.filter { it.kind == FirSession.Kind.Source }
.flatMap { (it.firProvider as FirProviderImpl).getAllFirFiles() }
var builtInsModule: KotlinBuiltIns? = null var builtInsModule: KotlinBuiltIns? = null
val dependencies = mutableListOf<ModuleDescriptorImpl>() val dependencies = mutableListOf<ModuleDescriptorImpl>()
@@ -70,31 +60,21 @@ internal fun PhaseContext.fir2Ir(
moduleDescriptor.setDependencies(ArrayList(dependencies)) moduleDescriptor.setDependencies(ArrayList(dependencies))
} }
val commonMemberStorage = Fir2IrCommonMemberStorage( val fir2irResult = input.firResult.convertToIrAndActualize(
generateSignatures = false,
signatureComposerCreator = null,
manglerCreator = { FirJvmKotlinMangler() } // TODO: replace with potentially simpler JS version
)
val fir2irResult = Fir2IrConverter.createModuleFragmentWithSignaturesIfNeeded(
input.session, input.scopeSession, input.firFiles + commonFirFiles,
configuration.languageVersionSettings,
fir2IrExtensions, fir2IrExtensions,
KonanManglerIr, IrFactoryImpl,
Fir2IrVisibilityConverter.Default,
Fir2IrJvmSpecialAnnotationSymbolProvider(), // TODO: replace with appropriate (probably empty) implementation
IrGenerationExtension.getInstances(config.project), IrGenerationExtension.getInstances(config.project),
generateSignatures = false, linkViaSignatures = false,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance, // TODO: consider passing externally signatureComposerCreator = null,
commonMemberStorage = commonMemberStorage, irMangler = KonanManglerIr,
initializedIrBuiltIns = null visibilityConverter = Fir2IrVisibilityConverter.Default,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
).also { ).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors } (it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors }
} }
val symbols = createKonanSymbols(fir2irResult) val symbols = createKonanSymbols(fir2irResult)
// TODO KT-55580 Invoke CopyDefaultValuesToActualPhase, same as PsiToir phase does. // TODO KT-55580 Invoke CopyDefaultValuesToActualPhase, same as PsiToir phase does.
return Fir2IrOutput(input.session, input.scopeSession, input.firFiles, fir2irResult, symbols) return Fir2IrOutput(input.firResult, fir2irResult, symbols)
} }
private fun PhaseContext.createKonanSymbols( private fun PhaseContext.createKonanSymbols(
@@ -7,24 +7,22 @@ import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.BinaryModuleData import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirModuleDataImpl
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.pipeline.buildFirFromKtFiles import org.jetbrains.kotlin.fir.pipeline.*
import org.jetbrains.kotlin.fir.pipeline.runCheckers
import org.jetbrains.kotlin.fir.pipeline.runResolution
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.session.FirNativeSessionFactory import org.jetbrains.kotlin.fir.session.FirNativeSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
internal fun PhaseContext.firFrontend( internal fun PhaseContext.firFrontend(
input: KotlinCoreEnvironment input: KotlinCoreEnvironment
@@ -61,31 +59,49 @@ internal fun PhaseContext.firFrontend(
configuration.languageVersionSettings, configuration.languageVersionSettings,
registerExtraComponents = {}, registerExtraComponents = {},
) )
val mainModuleData = FirModuleDataImpl(
mainModuleName, fun runFrontend(
dependencyList.regularDependencies, moduleName: Name,
dependencyList.dependsOnDependencies, dependsOn: List<FirModuleData>,
dependencyList.friendsDependencies, ktFiles: List<KtFile>
CommonPlatforms.defaultCommonPlatform, ): ModuleCompilerAnalyzedOutput {
NativePlatformAnalyzerServices val moduleData = FirModuleDataImpl(
) moduleName,
val session = FirNativeSessionFactory.createModuleBasedSession( dependencyList.regularDependencies,
mainModuleData, dependsOn,
sessionProvider, dependencyList.friendsDependencies,
extensionRegistrars, CommonPlatforms.defaultCommonPlatform,
configuration.languageVersionSettings, NativePlatformAnalyzerServices
sessionConfigurator, )
) val session = FirNativeSessionFactory.createModuleBasedSession(
val rawFirFiles = session.buildFirFromKtFiles(ktFiles) moduleData,
val (scopeSession, firFiles) = session.runResolution(rawFirFiles) sessionProvider,
if (shouldPrintFiles()) extensionRegistrars,
firFiles.forEach { println(it.render()) } configuration.languageVersionSettings,
session.runCheckers(scopeSession, firFiles, diagnosticsReporter) sessionConfigurator,
)
val output = buildResolveAndCheckFir(session, ktFiles, diagnosticsReporter)
if (shouldPrintFiles())
output.fir.forEach { println(it.render()) }
return output
}
val isMppEnabled = configuration.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
val firResult = if (isMppEnabled) {
val (commonKtFiles, platformKtFiles) = ktFiles.partition { it.isCommonSource == true }
val commonOutput = runFrontend(Name.identifier("${mainModuleName}-common"), emptyList(), commonKtFiles)
val platformOutput = runFrontend(mainModuleName, listOf(commonOutput.session.moduleData), platformKtFiles)
FirResult(platformOutput, commonOutput)
} else {
FirResult(runFrontend(mainModuleName, emptyList(), ktFiles), null)
}
return if (syntaxErrors || diagnosticsReporter.hasErrors) { return if (syntaxErrors || diagnosticsReporter.hasErrors) {
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames) FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
FirOutput.ShouldNotGenerateCode FirOutput.ShouldNotGenerateCode
} else { } else {
FirOutput.Full(session, scopeSession, firFiles) FirOutput.Full(firResult)
} }
} }
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.serialization.* import org.jetbrains.kotlin.fir.serialization.*
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
@@ -29,13 +30,22 @@ import org.jetbrains.kotlin.utils.toMetadataVersion
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
import org.jetbrains.kotlin.psi import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.utils.addIfNotNull
internal fun PhaseContext.firSerializer( internal fun PhaseContext.firSerializer(
input: Fir2IrOutput input: Fir2IrOutput
): SerializerOutput { ): SerializerOutput {
val configuration = config.configuration val configuration = config.configuration
val sourceFiles = input.firFiles.mapNotNull { it.sourceFile } val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesBySourceFile = input.firFiles.associateBy { it.sourceFile } val firFilesAndSessionsBySourceFile = mutableMapOf<KtSourceFile, Triple<FirFile, FirSession, ScopeSession>>()
for (firOutput in listOfNotNull(input.firResult.commonOutput, input.firResult.platformOutput)) {
for (firFile in firOutput.fir) {
sourceFiles.add(firFile.sourceFile!!)
firFilesAndSessionsBySourceFile[firFile.sourceFile!!] = Triple(firFile, firOutput.session, firOutput.scopeSession)
}
}
val metadataVersion = val metadataVersion =
configuration.get(CommonConfigurationKeys.METADATA_VERSION) configuration.get(CommonConfigurationKeys.METADATA_VERSION)
?: configuration.languageVersionSettings.languageVersion.toMetadataVersion() ?: configuration.languageVersionSettings.languageVersion.toMetadataVersion()
@@ -49,12 +59,13 @@ internal fun PhaseContext.firSerializer(
input.fir2irResult.irModuleFragment, input.fir2irResult.irModuleFragment,
expectDescriptorToSymbol = mutableMapOf() // TODO: expect -> actual mapping expectDescriptorToSymbol = mutableMapOf() // TODO: expect -> actual mapping
) { file -> ) { file ->
val firFile = firFilesBySourceFile[file] ?: error("cannot find FIR file by source file ${file.name} (${file.path})") val (firFile, session, scopeSession) = firFilesAndSessionsBySourceFile[file]
?: error("cannot find FIR file by source file ${file.name} (${file.path})")
serializeSingleFirFile( serializeSingleFirFile(
firFile, firFile,
input.session, session,
input.scopeSession, scopeSession,
FirNativeKLibSerializerExtension(input.session, metadataVersion, FirElementAwareSerializableStringTable()), FirNativeKLibSerializerExtension(session, metadataVersion, FirElementAwareSerializableStringTable()),
configuration.languageVersionSettings, configuration.languageVersionSettings,
) )
} }
@@ -9,15 +9,11 @@ import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine
import org.jetbrains.kotlin.backend.konan.fir2Ir import org.jetbrains.kotlin.backend.konan.fir2Ir
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.Fir2IrResult import org.jetbrains.kotlin.fir.backend.Fir2IrResult
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.resolve.ScopeSession
internal data class Fir2IrOutput( internal data class Fir2IrOutput(
val session: FirSession, val firResult: FirResult,
val scopeSession: ScopeSession,
val firFiles: List<FirFile>,
val fir2irResult: Fir2IrResult, val fir2irResult: Fir2IrResult,
val symbols: KonanSymbols val symbols: KonanSymbols
) )
@@ -9,18 +9,12 @@ import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine
import org.jetbrains.kotlin.backend.konan.firFrontend import org.jetbrains.kotlin.backend.konan.firFrontend
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
sealed class FirOutput { sealed class FirOutput {
object ShouldNotGenerateCode : FirOutput() object ShouldNotGenerateCode : FirOutput()
data class Full( data class Full(val firResult: FirResult) : FirOutput()
val session: FirSession,
val scopeSession: ScopeSession,
val firFiles: List<FirFile>,
) : FirOutput()
} }
internal val FIRPhase = createSimpleNamedCompilerPhase( internal val FIRPhase = createSimpleNamedCompilerPhase(