[FIR & FIR2IR] Prepare test and CLI infrastructure to support MPP

- Move out getAnalyzerServices from FirFrontendFacade to TestSetupUtils
- Simplify DependencyListForCliModule. Now it takes BinaryModuleData as input
- FirOutArtifact contains several FirOutputArtifactPart
- Simplify FirFrontendFacade
This commit is contained in:
Ivan Kochurkin
2022-11-18 19:51:58 +01:00
committed by Space Team
parent 3029e47609
commit 5d273ce839
44 changed files with 1025 additions and 788 deletions
@@ -48,7 +48,9 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter
import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
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.fir.session.environment.AbstractProjectFileSearchScope
@@ -203,7 +205,7 @@ class IncrementalFirJvmCompilerRunner(
var incrementalExcludesScope: AbstractProjectFileSearchScope? = null
fun firIncrementalCycle(): ModuleCompilerAnalyzedOutput? {
fun firIncrementalCycle(): FirResult? {
while (true) {
val compilerInput = ModuleCompilerInput(
@@ -229,7 +231,7 @@ class IncrementalFirJvmCompilerRunner(
// TODO: consider what to do if many compilations find a main class
if (mainClassFqName == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
mainClassFqName = findMainClass(analysisResults.fir)
mainClassFqName = findMainClass(analysisResults.platformOutput.fir)
}
// TODO: switch the whole IC to KtSourceFile instead of FIle
@@ -273,19 +275,7 @@ class IncrementalFirJvmCompilerRunner(
val extensions = JvmFir2IrExtensions(configuration, JvmIrDeserializerImpl(), JvmIrMangler)
val irGenerationExtensions =
(projectEnvironment as? VfsBasedProjectEnvironment)?.project?.let { IrGenerationExtension.getInstances(it) }.orEmpty()
val allCommonFirFiles = cycleResult.session.moduleData.dependsOnDependencies
.map { it.session }
.filter { it.kind == FirSession.Kind.Source }
.flatMap { (it.firProvider as FirProviderImpl).getAllFirFiles() }
val (irModuleFragment, components, pluginContext) = Fir2IrConverter.createModuleFragmentWithoutSignatures(
cycleResult.session, cycleResult.scopeSession, cycleResult.fir + allCommonFirFiles,
cycleResult.session.languageVersionSettings, extensions,
FirJvmKotlinMangler(cycleResult.session), JvmIrMangler, IrFactoryImpl, FirJvmVisibilityConverter,
Fir2IrJvmSpecialAnnotationSymbolProvider(),
irGenerationExtensions,
kotlinBuiltIns = DefaultBuiltIns.Instance // TODO: consider passing externally
)
val platformIrOutput = cycleResult.convertToIrAndActualize(extensions, irGenerationExtensions, linkViaSignatures = false)
performanceManager?.notifyIRTranslationFinished()
@@ -293,11 +283,11 @@ class IncrementalFirJvmCompilerRunner(
targetId,
configuration,
extensions,
irModuleFragment,
components.symbolTable,
components,
cycleResult.session,
pluginContext
platformIrOutput.irModuleFragment,
platformIrOutput.components.symbolTable,
platformIrOutput.components,
cycleResult.platformOutput.session,
platformIrOutput.pluginContext
)
val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment, performanceManager)
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.backend.jvm.makeLocalFirMetadataSerializerForMetadataSource
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
import org.jetbrains.kotlin.fir.visitors.FirVisitor
@@ -26,7 +27,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method
import java.io.File
internal fun collectNewDirtySources(
analysisResults: ModuleCompilerAnalyzedOutput,
analysisResults: FirResult,
targetId: TargetId,
configuration: CompilerConfiguration,
caches: IncrementalJvmCachesManager,
@@ -35,96 +36,101 @@ internal fun collectNewDirtySources(
): LinkedHashSet<File> {
val changesCollector = ChangesCollector()
val globalSerializationBindings = JvmSerializationBindings()
analysisResults.fir.forEach {
it.accept(object : FirVisitor<Unit, MutableList<MetadataSerializer>>() {
inline fun withMetadataSerializer(
metadata: FirMetadataSource,
data: MutableList<MetadataSerializer>,
body: (MetadataSerializer) -> Unit
) {
val serializer = makeLocalFirMetadataSerializerForMetadataSource(
metadata,
analysisResults.session,
analysisResults.scopeSession,
globalSerializationBindings,
data.lastOrNull(),
targetId,
configuration
)
data.push(serializer)
body(serializer)
data.pop()
}
override fun visitElement(element: FirElement, data: MutableList<MetadataSerializer>) {
element.acceptChildren(this, data)
}
override fun visitRegularClass(regularClass: FirRegularClass, data: MutableList<MetadataSerializer>) {
visitClass(regularClass, data)
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: MutableList<MetadataSerializer>) {
visitClass(anonymousObject, data)
}
override fun visitFile(file: FirFile, data: MutableList<MetadataSerializer>) {
val metadata = FirMetadataSource.File(listOf(file))
withMetadataSerializer(metadata, data) {
file.acceptChildren(this, data)
// TODO: compare package fragments?
}
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: MutableList<MetadataSerializer>) {
data.firstOrNull()?.let { serializer ->
super.visitFunction(simpleFunction, data)
serializer.bindMethodMetadata(
FirMetadataSource.Function(simpleFunction),
Method(simpleFunction.name.asString(), simpleFunction.computeJvmDescriptor())
fun visitFirFiles(analyzedOutput: ModuleCompilerAnalyzedOutput) {
analyzedOutput.fir.forEach {
it.accept(object : FirVisitor<Unit, MutableList<MetadataSerializer>>() {
inline fun withMetadataSerializer(
metadata: FirMetadataSource,
data: MutableList<MetadataSerializer>,
body: (MetadataSerializer) -> Unit
) {
val serializer = makeLocalFirMetadataSerializerForMetadataSource(
metadata,
analyzedOutput.session,
analyzedOutput.scopeSession,
globalSerializationBindings,
data.lastOrNull(),
targetId,
configuration
)
data.push(serializer)
body(serializer)
data.pop()
}
}
override fun visitConstructor(constructor: FirConstructor, data: MutableList<MetadataSerializer>) {
super.visitConstructor(constructor, data)
data.first().bindMethodMetadata(
FirMetadataSource.Function(constructor),
Method(SpecialNames.INIT.asString(), constructor.computeJvmDescriptor(""))
)
}
override fun visitElement(element: FirElement, data: MutableList<MetadataSerializer>) {
element.acceptChildren(this, data)
}
override fun visitProperty(property: FirProperty, data: MutableList<MetadataSerializer>) {
property.acceptChildren(this, data)
// data.firstOrNull()?.let {
// property.acceptChildren(this, data)
// it.bindPropertyMetadata(
// FirMetadataSource.Property(property),
// Method(property.name.asString(), ""),//property.computeJvmDescriptor())
// IrDeclarationOrigin.DEFINED
// )
// }
}
override fun visitRegularClass(regularClass: FirRegularClass, data: MutableList<MetadataSerializer>) {
visitClass(regularClass, data)
}
override fun visitClass(klass: FirClass, data: MutableList<MetadataSerializer>) {
val metadata = FirMetadataSource.Class(klass)
withMetadataSerializer(metadata, data) { serializer ->
klass.acceptChildren(this, data)
serializer.serialize(metadata)?.let { (classProto, nameTable) ->
caches.platformCache.saveFrontendClassToCache(
klass.classId,
classProto as ProtoBuf.Class,
nameTable,
null, // TODO: !!
changesCollector
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: MutableList<MetadataSerializer>) {
visitClass(anonymousObject, data)
}
override fun visitFile(file: FirFile, data: MutableList<MetadataSerializer>) {
val metadata = FirMetadataSource.File(listOf(file))
withMetadataSerializer(metadata, data) {
file.acceptChildren(this, data)
// TODO: compare package fragments?
}
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: MutableList<MetadataSerializer>) {
data.firstOrNull()?.let { serializer ->
super.visitFunction(simpleFunction, data)
serializer.bindMethodMetadata(
FirMetadataSource.Function(simpleFunction),
Method(simpleFunction.name.asString(), simpleFunction.computeJvmDescriptor())
)
}
}
}
}, mutableListOf())
override fun visitConstructor(constructor: FirConstructor, data: MutableList<MetadataSerializer>) {
super.visitConstructor(constructor, data)
data.first().bindMethodMetadata(
FirMetadataSource.Function(constructor),
Method(SpecialNames.INIT.asString(), constructor.computeJvmDescriptor(""))
)
}
override fun visitProperty(property: FirProperty, data: MutableList<MetadataSerializer>) {
property.acceptChildren(this, data)
// data.firstOrNull()?.let {
// property.acceptChildren(this, data)
// it.bindPropertyMetadata(
// FirMetadataSource.Property(property),
// Method(property.name.asString(), ""),//property.computeJvmDescriptor())
// IrDeclarationOrigin.DEFINED
// )
// }
}
override fun visitClass(klass: FirClass, data: MutableList<MetadataSerializer>) {
val metadata = FirMetadataSource.Class(klass)
withMetadataSerializer(metadata, data) { serializer ->
klass.acceptChildren(this, data)
serializer.serialize(metadata)?.let { (classProto, nameTable) ->
caches.platformCache.saveFrontendClassToCache(
klass.classId,
classProto as ProtoBuf.Class,
nameTable,
null, // TODO: !!
changesCollector
)
}
}
}
}, mutableListOf())
}
}
analysisResults.commonOutput?.let { visitFirFiles(it) }
visitFirFiles(analysisResults.platformOutput)
val (dirtyLookupSymbols, dirtyClassFqNames, forceRecompile) = changesCollector.getDirtyData(listOf(caches.platformCache), reporter)
val forceToRecompileFiles = mapClassesFqNamesToFiles(listOf(caches.platformCache), forceRecompile, reporter)