FIR JS: Prepare JS/KLib infrastructure for FIR integration

rearrange declarations, abstract things that should be done differently
with FIR, etc.
This commit is contained in:
Ilya Chernikov
2022-06-07 17:05:54 +02:00
parent 126c8eafa3
commit 8bf108dc17
20 changed files with 479 additions and 193 deletions
@@ -11,6 +11,7 @@ import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
@@ -492,13 +493,12 @@ class GenerateIrRuntime {
perFile: Boolean = false
): String {
val tmpKlibDir = createTempDirectory().also { it.toFile().deleteOnExit() }.toString()
val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, project, false)
serializeModuleIntoKlib(
moduleName,
project,
configuration,
IrMessageLogger.None,
bindingContext,
files,
files.map(::KtPsiSourceFile),
tmpKlibDir,
emptyList(),
moduleFragment,
@@ -508,7 +508,9 @@ class GenerateIrRuntime {
perFile,
abiVersion = KotlinAbiVersion.CURRENT,
jsOutputName = null
)
) { file ->
metadataSerializer.serializeScope(file, bindingContext, moduleFragment.descriptor)
}
return tmpKlibDir
}
@@ -11,6 +11,7 @@ import com.intellij.openapi.vfs.local.CoreLocalFileSystem
import com.intellij.psi.PsiManager
import com.intellij.psi.SingleRootFileViewProvider
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.js.klib.generateIrForKlibSerialization
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.*
@@ -18,6 +19,7 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.backend.js.ic.*
import org.jetbrains.kotlin.ir.backend.js.SourceMapsInfo
@@ -25,6 +27,7 @@ import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.safeModuleName
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.testOld.V8IrJsTestChecker
import org.jetbrains.kotlin.name.FqName
@@ -294,7 +297,36 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
AnalyzerWithCompilerReport(configuration)
)
generateKLib(sourceModule, IrFactoryImpl, outputKlibFile.canonicalPath, nopack = false, jsOutputName = moduleName)
val moduleSourceFiles = (sourceModule.mainModule as MainModule.SourceFiles).files
val icData = sourceModule.compilerConfiguration.incrementalDataProvider?.getSerializedData(moduleSourceFiles) ?: emptyList()
val expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val moduleFragment = generateIrForKlibSerialization(
environment.project,
moduleSourceFiles,
configuration,
sourceModule.jsFrontEndResult.jsAnalysisResult,
sortDependencies(sourceModule.descriptors),
icData,
expectDescriptorToSymbol,
IrFactoryImpl,
verifySignatures = true
) {
sourceModule.getModuleDescriptor(it)
}
val metadataSerializer =
KlibMetadataIncrementalSerializer(configuration, sourceModule.project, sourceModule.jsFrontEndResult.hasErrors)
generateKLib(
sourceModule,
outputKlibFile.canonicalPath,
nopack = false,
jsOutputName = moduleName,
icData = icData,
expectDescriptorToSymbol = expectDescriptorToSymbol,
moduleFragment = moduleFragment
) { file ->
metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor)
}
}
private fun initializeWorkingDir(projectInfo: ProjectInfo, testDir: File, sourceDir: File, buildDir: File) {
@@ -32,7 +32,7 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
targetBackend: TargetBackend,
private val pathToTestDir: String,
private val testGroupOutputDirPrefix: String,
private val skipMinification: Boolean = getBoolean("kotlin.js.skipMinificationTest"),
protected val skipMinification: Boolean = getBoolean("kotlin.js.skipMinificationTest"),
) : AbstractKotlinCompilerWithTargetBackendTest(targetBackend) {
abstract val frontendFacade: Constructor<FrontendFacade<R>>
abstract val frontendToBackendConverter: Constructor<Frontend2BackendConverter<R, I>>
@@ -12,11 +12,13 @@ import com.intellij.psi.PsiManager
import com.intellij.psi.SingleRootFileViewProvider
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.js.klib.generateIrForKlibSerialization
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.ProjectInfo
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
import org.jetbrains.kotlin.ir.backend.js.ic.CacheUpdater
@@ -25,6 +27,7 @@ import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransf
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.testOld.V8IrJsTestChecker
import org.jetbrains.kotlin.klib.KlibABITestUtils
@@ -118,7 +121,37 @@ abstract class AbstractJsKLibABITestCase : KtUsefulTestCase() {
AnalyzerWithCompilerReport(config)
)
generateKLib(sourceModule, IrFactoryImpl, klibFile.path, nopack = false, jsOutputName = moduleName)
val moduleSourceFiles = (sourceModule.mainModule as MainModule.SourceFiles).files
val icData = sourceModule.compilerConfiguration.incrementalDataProvider?.getSerializedData(moduleSourceFiles) ?: emptyList()
val expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val moduleFragment = generateIrForKlibSerialization(
environment.project,
moduleSourceFiles,
config,
sourceModule.jsFrontEndResult.jsAnalysisResult,
sortDependencies(sourceModule.descriptors),
icData,
expectDescriptorToSymbol,
IrFactoryImpl,
verifySignatures = true
) {
sourceModule.getModuleDescriptor(it)
}
val metadataSerializer =
KlibMetadataIncrementalSerializer(config, sourceModule.project, sourceModule.jsFrontEndResult.hasErrors)
generateKLib(
sourceModule,
klibFile.path,
nopack = false,
jsOutputName = moduleName,
icData = icData,
expectDescriptorToSymbol = expectDescriptorToSymbol,
moduleFragment = moduleFragment
) { file ->
metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor)
}
}
private fun buildBinaryAndRun(mainModuleKlibFile: File, allDependencies: KlibABITestUtils.Dependencies) {
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.ir.util.irMessageLogger
import org.jetbrains.kotlin.js.config.ErrorTolerancePolicy
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
@@ -48,16 +49,10 @@ class JsKlibBackendFacade(
val outputFile = JsEnvironmentConfigurator.getJsKlibArtifactPath(testServices, module.name)
if (firstTimeCompilation) {
val project = testServices.compilerConfigurationProvider.getProject(module)
val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT
val hasErrors = TopDownAnalyzerFacadeForJSIR.checkForErrors(inputArtifact.sourceFiles, inputArtifact.bindingContext, errorPolicy)
serializeModuleIntoKlib(
configuration[CommonConfigurationKeys.MODULE_NAME]!!,
project,
configuration,
configuration.irMessageLogger,
inputArtifact.bindingContext,
inputArtifact.sourceFiles,
klibPath = outputFile,
JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices).keys.toList(),
@@ -66,9 +61,10 @@ class JsKlibBackendFacade(
cleanFiles = inputArtifact.icData,
nopack = true,
perFile = false,
containsErrorCode = hasErrors,
containsErrorCode = inputArtifact.hasErrors,
abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data
jsOutputName = null
jsOutputName = null,
inputArtifact.serializeSingleFile
)
}
@@ -6,14 +6,12 @@
package org.jetbrains.kotlin.js.test.ir
import org.jetbrains.kotlin.js.test.AbstractJsBlackBoxCodegenTestBase
import org.jetbrains.kotlin.js.test.JsAdditionalSourceProvider
import org.jetbrains.kotlin.js.test.JsSteppingTestAdditionalSourceProvider
import org.jetbrains.kotlin.js.test.converters.JsIrBackendFacade
import org.jetbrains.kotlin.js.test.converters.JsKlibBackendFacade
import org.jetbrains.kotlin.js.test.converters.incremental.RecompileModuleJsIrBackendFacade
import org.jetbrains.kotlin.js.test.handlers.*
import org.jetbrains.kotlin.parsing.parseBoolean
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
@@ -27,15 +25,9 @@ import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.frontend.fir.handlers.*
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
import org.jetbrains.kotlin.test.services.JsLibraryProvider
import org.jetbrains.kotlin.test.services.MetaTestConfigurator
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.moduleStructure
import org.jetbrains.kotlin.test.services.sourceProviders.CoroutineHelpersSourceFilesProvider
import org.jetbrains.kotlin.test.utils.isDirectiveDefined
import java.lang.Boolean.getBoolean
abstract class AbstractJsIrTest(
@@ -194,68 +186,46 @@ private class SkipMultiModuleTestsMetaConfigurator(testServices: TestServices) :
}
}
open class AbstractFirJsTest : AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JS_IR) {
private val pathToTestDir = "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/box/"
private val testGroupOutputDirPrefix = "box/"
val targetFrontend = FrontendKinds.FIR
private val skipMinification: Boolean = getBoolean("kotlin.js.skipMinificationTest")
val frontendFacade: Constructor<FrontendFacade<FirOutputArtifact>>
abstract class AbstractFirJsTest(
pathToTestDir: String = "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/box/",
testGroupOutputDirPrefix: String = "box/",
) : AbstractJsBlackBoxCodegenTestBase<FirOutputArtifact, IrBackendInput, BinaryArtifacts.KLib>(
FrontendKinds.FIR, TargetBackend.JS_IR, pathToTestDir, testGroupOutputDirPrefix, skipMinification = true
) {
override val frontendFacade: Constructor<FrontendFacade<FirOutputArtifact>>
get() = ::FirFrontendFacade
private val frontendToBackendConverter: Constructor<Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>>
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>>
get() = ::Fir2IrResultsConverter
override fun TestConfigurationBuilder.configuration() {
globalDefaults {
frontend = targetFrontend
targetPlatform = JsPlatforms.defaultJsPlatform
dependencyKind = DependencyKind.Binary
}
override val backendFacade: Constructor<BackendFacade<IrBackendInput, BinaryArtifacts.KLib>>
get() = ::JsKlibBackendFacade
val pathToRootOutputDir = System.getProperty("kotlin.js.test.root.out.dir") ?: error("'kotlin.js.test.root.out.dir' is not set")
defaultDirectives {
+DiagnosticsDirectives.REPORT_ONLY_EXPLICITLY_DEFINED_DEBUG_INFO
JsEnvironmentConfigurationDirectives.PATH_TO_ROOT_OUTPUT_DIR with pathToRootOutputDir
JsEnvironmentConfigurationDirectives.PATH_TO_TEST_DIR with pathToTestDir
JsEnvironmentConfigurationDirectives.TEST_GROUP_OUTPUT_DIR_PREFIX with testGroupOutputDirPrefix
+JsEnvironmentConfigurationDirectives.TYPED_ARRAYS
if (skipMinification) +JsEnvironmentConfigurationDirectives.SKIP_MINIFICATION
if (getBoolean("kotlin.js.ir.skipRegularMode")) +JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE
+ConfigurationDirectives.WITH_STDLIB
+LanguageSettingsDirectives.ALLOW_KOTLIN_PACKAGE
}
override val afterBackendFacade: Constructor<AbstractTestFacade<BinaryArtifacts.KLib, BinaryArtifacts.Js>>?
get() = ::JsIrBackendFacade
useMetaTestConfigurators(::SkipMultiModuleTestsMetaConfigurator)
override val recompileFacade: Constructor<AbstractTestFacade<BinaryArtifacts.Js, BinaryArtifacts.Js>>
get() = { RecompileModuleJsIrBackendFacade(it) }
forTestsNotMatching("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/*") {
private fun getBoolean(s: String, default: Boolean) = System.getProperty(s)?.let { parseBoolean(it) } ?: default
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
with (builder) {
defaultDirectives {
DiagnosticsDirectives.DIAGNOSTICS with "-warnings"
+ConfigurationDirectives.WITH_STDLIB
+LanguageSettingsDirectives.ALLOW_KOTLIN_PACKAGE
val runIc = getBoolean("kotlin.js.ir.icMode")
if (runIc) +JsEnvironmentConfigurationDirectives.RUN_IC
if (getBoolean("kotlin.js.ir.klibMainModule")) +JsEnvironmentConfigurationDirectives.KLIB_MAIN_MODULE
if (getBoolean("kotlin.js.ir.perModule", true)) +JsEnvironmentConfigurationDirectives.PER_MODULE
if (getBoolean("kotlin.js.ir.dce", true)) +JsEnvironmentConfigurationDirectives.RUN_IR_DCE
+LanguageSettingsDirectives.ALLOW_KOTLIN_PACKAGE
-JsEnvironmentConfigurationDirectives.GENERATE_NODE_JS_RUNNER
}
}
forTestsNotMatching("compiler/testData/codegen/boxError/*") {
enableMetaInfoHandler()
}
useConfigurators(
::CommonEnvironmentConfigurator,
::JsEnvironmentConfigurator,
)
useAdditionalSourceProviders(
::JsAdditionalSourceProvider,
::CoroutineHelpersSourceFilesProvider,
)
useAdditionalService(::JsLibraryProvider)
facadeStep(frontendFacade)
firHandlersStep {
useHandlers(
::FirDiagnosticsHandler,
::FirDumpHandler,
::FirCfgDumpHandler,
::FirCfgConsistencyHandler,
@@ -263,8 +233,17 @@ open class AbstractFirJsTest : AbstractKotlinCompilerWithTargetBackendTest(Targe
)
}
// There were some problems not covered by
// the FIR handlers above
facadeStep(frontendToBackendConverter)
configureJsArtifactsHandlersStep {
useHandlers(
::JsIrRecompiledArtifactsIdentityHandler,
)
}
forTestsMatching("${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/box/closure/inlineAnonymousFunctions/*") {
defaultDirectives {
+JsEnvironmentConfigurationDirectives.GENERATE_INLINE_ANONYMOUS_FUNCTIONS
}
}
}
}
}