[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.impl.ModuleDescriptorImpl
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.jvm.Fir2IrJvmSpecialAnnotationSymbolProvider
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
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.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.storage.LockBasedStorageManager
@@ -36,10 +30,6 @@ internal fun PhaseContext.fir2Ir(
input: FirOutput.Full,
): Fir2IrOutput {
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
val dependencies = mutableListOf<ModuleDescriptorImpl>()
@@ -70,31 +60,21 @@ internal fun PhaseContext.fir2Ir(
moduleDescriptor.setDependencies(ArrayList(dependencies))
}
val commonMemberStorage = Fir2IrCommonMemberStorage(
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,
val fir2irResult = input.firResult.convertToIrAndActualize(
fir2IrExtensions,
KonanManglerIr, IrFactoryImpl,
Fir2IrVisibilityConverter.Default,
Fir2IrJvmSpecialAnnotationSymbolProvider(), // TODO: replace with appropriate (probably empty) implementation
IrGenerationExtension.getInstances(config.project),
generateSignatures = false,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance, // TODO: consider passing externally
commonMemberStorage = commonMemberStorage,
initializedIrBuiltIns = null
linkViaSignatures = false,
signatureComposerCreator = null,
irMangler = KonanManglerIr,
visibilityConverter = Fir2IrVisibilityConverter.Default,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors }
}
val symbols = createKonanSymbols(fir2irResult)
// 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(
@@ -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.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirModuleDataImpl
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.pipeline.buildFirFromKtFiles
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.pipeline.*
import org.jetbrains.kotlin.fir.session.FirNativeSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name
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.multiplatform.isCommonSource
internal fun PhaseContext.firFrontend(
input: KotlinCoreEnvironment
@@ -61,31 +59,49 @@ internal fun PhaseContext.firFrontend(
configuration.languageVersionSettings,
registerExtraComponents = {},
)
val mainModuleData = FirModuleDataImpl(
mainModuleName,
dependencyList.regularDependencies,
dependencyList.dependsOnDependencies,
dependencyList.friendsDependencies,
CommonPlatforms.defaultCommonPlatform,
NativePlatformAnalyzerServices
)
val session = FirNativeSessionFactory.createModuleBasedSession(
mainModuleData,
sessionProvider,
extensionRegistrars,
configuration.languageVersionSettings,
sessionConfigurator,
)
val rawFirFiles = session.buildFirFromKtFiles(ktFiles)
val (scopeSession, firFiles) = session.runResolution(rawFirFiles)
if (shouldPrintFiles())
firFiles.forEach { println(it.render()) }
session.runCheckers(scopeSession, firFiles, diagnosticsReporter)
fun runFrontend(
moduleName: Name,
dependsOn: List<FirModuleData>,
ktFiles: List<KtFile>
): ModuleCompilerAnalyzedOutput {
val moduleData = FirModuleDataImpl(
moduleName,
dependencyList.regularDependencies,
dependsOn,
dependencyList.friendsDependencies,
CommonPlatforms.defaultCommonPlatform,
NativePlatformAnalyzerServices
)
val session = FirNativeSessionFactory.createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
configuration.languageVersionSettings,
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) {
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
FirOutput.ShouldNotGenerateCode
} 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.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.serialization.*
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
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.serialization.MutableVersionRequirementTable
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.utils.addIfNotNull
internal fun PhaseContext.firSerializer(
input: Fir2IrOutput
): SerializerOutput {
val configuration = config.configuration
val sourceFiles = input.firFiles.mapNotNull { it.sourceFile }
val firFilesBySourceFile = input.firFiles.associateBy { it.sourceFile }
val sourceFiles = mutableListOf<KtSourceFile>()
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 =
configuration.get(CommonConfigurationKeys.METADATA_VERSION)
?: configuration.languageVersionSettings.languageVersion.toMetadataVersion()
@@ -49,12 +59,13 @@ internal fun PhaseContext.firSerializer(
input.fir2irResult.irModuleFragment,
expectDescriptorToSymbol = mutableMapOf() // TODO: expect -> actual mapping
) { 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(
firFile,
input.session,
input.scopeSession,
FirNativeKLibSerializerExtension(input.session, metadataVersion, FirElementAwareSerializableStringTable()),
session,
scopeSession,
FirNativeKLibSerializerExtension(session, metadataVersion, FirElementAwareSerializableStringTable()),
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.fir2Ir
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.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.pipeline.FirResult
internal data class Fir2IrOutput(
val session: FirSession,
val scopeSession: ScopeSession,
val firFiles: List<FirFile>,
val firResult: FirResult,
val fir2irResult: Fir2IrResult,
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.firFrontend
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.pipeline.FirResult
sealed class FirOutput {
object ShouldNotGenerateCode : FirOutput()
data class Full(
val session: FirSession,
val scopeSession: ScopeSession,
val firFiles: List<FirFile>,
) : FirOutput()
data class Full(val firResult: FirResult) : FirOutput()
}
internal val FIRPhase = createSimpleNamedCompilerPhase(