K2JsIrCompiler: hoist common front-end preparation logic

Instead of creating ModuleStructure and run analysis in each backend,
the common preparation logic is moved into K2JsIrCompiler.doExecute().
This commit is contained in:
Ting-Yuan Huang
2021-03-23 22:15:40 -07:00
committed by TeamCityServer
parent 94af3adb4b
commit e75ca75e3e
9 changed files with 192 additions and 174 deletions
@@ -205,7 +205,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
cachePath = outputFilePath, cachePath = outputFilePath,
project = projectJs, project = projectJs,
mainModule = mainModule, mainModule = mainModule,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration, configuration = config.configuration,
dependencies = libraries, dependencies = libraries,
friendDependencies = friendLibraries, friendDependencies = friendLibraries,
@@ -219,18 +218,29 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
return OK return OK
} }
// Run analysis if main module is sources
lateinit var sourceModule: ModulesStructure
if (arguments.includes == null) {
sourceModule = prepareAnalyzedSourceModule(
projectJs,
environmentForJS.getSourceFiles(),
configurationJs,
libraries,
friendLibraries,
AnalyzerWithCompilerReport(config.configuration),
icUseGlobalSignatures = icCaches.isNotEmpty(),
icUseStdlibCache = icCaches.isNotEmpty(),
icCache = if (icCaches.isNotEmpty()) checkCaches(libraries, icCaches, skipLib = arguments.includes).data else emptyMap()
)
}
if (arguments.irProduceKlibDir || arguments.irProduceKlibFile) { if (arguments.irProduceKlibDir || arguments.irProduceKlibFile) {
if (arguments.irProduceKlibFile) { if (arguments.irProduceKlibFile) {
require(outputFile.extension == KLIB_FILE_EXTENSION) { "Please set up .klib file as output" } require(outputFile.extension == KLIB_FILE_EXTENSION) { "Please set up .klib file as output" }
} }
generateKLib( generateKLib(
project = config.project, sourceModule,
files = sourcesFiles,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
dependencies = libraries,
friendDependencies = friendLibraries,
irFactory = PersistentIrFactory(), // TODO IrFactoryImpl? irFactory = PersistentIrFactory(), // TODO IrFactoryImpl?
outputKlibPath = outputFile.path, outputKlibPath = outputFile.path,
nopack = arguments.irProduceKlibDir, nopack = arguments.irProduceKlibDir,
@@ -246,28 +256,33 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val includes = arguments.includes val includes = arguments.includes
val mainModule = if (includes != null) { val module = if (includes != null) {
if (sourcesFiles.isNotEmpty()) { if (sourcesFiles.isNotEmpty()) {
messageCollector.report(ERROR, "Source files are not supported when -Xinclude is present") messageCollector.report(ERROR, "Source files are not supported when -Xinclude is present")
} }
val includesPath = File(includes).canonicalPath val includesPath = File(includes).canonicalPath
val mainLibPath = libraries.find { File(it).canonicalPath == includesPath } val mainLibPath = libraries.find { File(it).canonicalPath == includesPath }
?: error("No library with name $includes ($includesPath) found") ?: error("No library with name $includes ($includesPath) found")
MainModule.Klib(mainLibPath) val kLib = MainModule.Klib(mainLibPath)
ModulesStructure(
projectJs,
kLib,
configuration,
libraries,
friendLibraries,
icUseGlobalSignatures = icCaches.isNotEmpty(),
icUseStdlibCache = icCaches.isNotEmpty(),
icCache = if (icCaches.isNotEmpty()) checkCaches(libraries, icCaches, skipLib = includes).data else emptyMap()
)
} else { } else {
MainModule.SourceFiles(sourcesFiles) sourceModule
} }
if (arguments.wasm) { if (arguments.wasm) {
val res = compileWasm( val res = compileWasm(
projectJs, module,
mainModule,
AnalyzerWithCompilerReport(config.configuration),
config.configuration,
PhaseConfig(wasmPhases), PhaseConfig(wasmPhases),
IrFactoryImpl, IrFactoryImpl,
dependencies = libraries,
friendDependencies = friendLibraries,
exportedDeclarations = setOf(FqName("main")) exportedDeclarations = setOf(FqName("main"))
) )
val outputWasmFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "wasm")!! val outputWasmFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "wasm")!!
@@ -289,14 +304,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
val compiledModule = compile( val compiledModule = compile(
projectJs, module,
mainModule,
AnalyzerWithCompilerReport(config.configuration),
config.configuration,
phaseConfig, phaseConfig,
if (arguments.irDceDriven) PersistentIrFactory() else IrFactoryImpl, if (arguments.irDceDriven) PersistentIrFactory() else IrFactoryImpl,
dependencies = libraries,
friendDependencies = friendLibraries,
mainArguments = mainCallArguments, mainArguments = mainCallArguments,
generateFullJs = !arguments.irDce, generateFullJs = !arguments.irDce,
generateDceJs = arguments.irDce, generateDceJs = arguments.irDce,
@@ -316,8 +326,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
messageCollector messageCollector
), ),
lowerPerModule = icCaches.isNotEmpty(), lowerPerModule = icCaches.isNotEmpty(),
useStdlibCache = icCaches.isNotEmpty(),
icCache = if (icCaches.isNotEmpty()) checkCaches(libraries, icCaches, skipLib = includes).data else emptyMap(),
) )
messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms") messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms")
@@ -39,14 +39,9 @@ class CompilationOutputs(
) )
fun compile( fun compile(
project: Project, depsDescriptors: ModulesStructure,
mainModule: MainModule,
analyzer: AbstractAnalyzerWithCompilerReport,
configuration: CompilerConfiguration,
phaseConfig: PhaseConfig, phaseConfig: PhaseConfig,
irFactory: IrFactory, irFactory: IrFactory,
dependencies: Collection<String>,
friendDependencies: Collection<String>,
mainArguments: List<String>?, mainArguments: List<String>?,
exportedDeclarations: Set<FqName> = emptySet(), exportedDeclarations: Set<FqName> = emptySet(),
generateFullJs: Boolean = true, generateFullJs: Boolean = true,
@@ -63,18 +58,11 @@ fun compile(
lowerPerModule: Boolean = false, lowerPerModule: Boolean = false,
safeExternalBoolean: Boolean = false, safeExternalBoolean: Boolean = false,
safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null, safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
useStdlibCache: Boolean = false,
icCache: Map<String, SerializedIcData> = emptyMap(),
): CompilerResult { ): CompilerResult {
if (lowerPerModule) { if (lowerPerModule) {
return icCompile( return icCompile(
project, depsDescriptors,
mainModule,
analyzer,
configuration,
dependencies,
friendDependencies,
mainArguments, mainArguments,
exportedDeclarations, exportedDeclarations,
generateFullJs, generateFullJs,
@@ -88,13 +76,13 @@ fun compile(
legacyPropertyAccess, legacyPropertyAccess,
safeExternalBoolean, safeExternalBoolean,
safeExternalBooleanDiagnostic, safeExternalBooleanDiagnostic,
useStdlibCache,
icCache,
) )
} }
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName) = val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName) =
loadIr(project, mainModule, analyzer, configuration, dependencies, friendDependencies, irFactory, verifySignatures) loadIr(depsDescriptors, irFactory, verifySignatures)
val mainModule = depsDescriptors.mainModule
val configuration = depsDescriptors.compilerConfiguration
val moduleDescriptor = moduleFragment.descriptor val moduleDescriptor = moduleFragment.descriptor
@@ -26,7 +26,6 @@ fun buildCache(
cachePath: String, cachePath: String,
project: Project, project: Project,
mainModule: MainModule.Klib, mainModule: MainModule.Klib,
analyzer: AbstractAnalyzerWithCompilerReport,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
dependencies: Collection<String>, dependencies: Collection<String>,
friendDependencies: Collection<String>, friendDependencies: Collection<String>,
@@ -50,7 +49,7 @@ fun buildCache(
icDir.deleteRecursively() icDir.deleteRecursively()
icDir.mkdirs() icDir.mkdirs()
val icData = prepareSingleLibraryIcCache(project, analyzer, configuration, mainModule.libPath, dependencies, friendDependencies, exportedDeclarations, icCache.data) val icData = prepareSingleLibraryIcCache(project, configuration, mainModule.libPath, dependencies, friendDependencies, exportedDeclarations, icCache.data)
icData.writeTo(File(cachePath)) icData.writeTo(File(cachePath))
@@ -29,7 +29,6 @@ import java.io.PrintWriter
fun prepareSingleLibraryIcCache( fun prepareSingleLibraryIcCache(
project: Project, project: Project,
analyzer: AbstractAnalyzerWithCompilerReport,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
libPath: String, libPath: String,
dependencies: Collection<String>, dependencies: Collection<String>,
@@ -41,21 +40,23 @@ fun prepareSingleLibraryIcCache(
val controller = WholeWorldStageController() val controller = WholeWorldStageController()
irFactory.stageController = controller irFactory.stageController = controller
val (context, deserializer, allModules) = prepareIr( val depsDescriptor = ModulesStructure(
project, project,
MainModule.Klib(libPath), MainModule.Klib(libPath),
analyzer,
configuration, configuration,
dependencies, dependencies,
friendDependencies, friendDependencies,
true,
true,
icCache
)
val (context, deserializer, allModules) = prepareIr(
depsDescriptor,
exportedDeclarations, exportedDeclarations,
null, null,
false, false,
false, false,
irFactory, irFactory,
useGlobalSignatures = true,
useStdlibCache = true,
icCache = icCache
) )
val moduleFragment = allModules.last() val moduleFragment = allModules.last()
@@ -118,12 +119,7 @@ private fun dumpIr(module: IrModuleFragment, fileName: String) {
} }
fun icCompile( fun icCompile(
project: Project, depsDescriptor: ModulesStructure,
mainModule: MainModule,
analyzer: AbstractAnalyzerWithCompilerReport,
configuration: CompilerConfiguration,
dependencies: Collection<String>,
friendDependencies: Collection<String>,
mainArguments: List<String>?, mainArguments: List<String>?,
exportedDeclarations: Set<FqName> = emptySet(), exportedDeclarations: Set<FqName> = emptySet(),
generateFullJs: Boolean = true, generateFullJs: Boolean = true,
@@ -137,8 +133,6 @@ fun icCompile(
baseClassIntoMetadata: Boolean = false, baseClassIntoMetadata: Boolean = false,
safeExternalBoolean: Boolean = false, safeExternalBoolean: Boolean = false,
safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null, safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
useStdlibCache: Boolean,
icCache: Map<String, SerializedIcData> = emptyMap()
): CompilerResult { ): CompilerResult {
val irFactory = PersistentIrFactory() val irFactory = PersistentIrFactory()
@@ -146,12 +140,7 @@ fun icCompile(
irFactory.stageController = controller irFactory.stageController = controller
val (context, _, allModules, moduleToName, loweredIrLoaded) = prepareIr( val (context, _, allModules, moduleToName, loweredIrLoaded) = prepareIr(
project, depsDescriptor,
mainModule,
analyzer,
configuration,
dependencies,
friendDependencies,
exportedDeclarations, exportedDeclarations,
dceRuntimeDiagnostic, dceRuntimeDiagnostic,
es6mode, es6mode,
@@ -160,10 +149,7 @@ fun icCompile(
baseClassIntoMetadata, baseClassIntoMetadata,
legacyPropertyAccess, legacyPropertyAccess,
safeExternalBoolean, safeExternalBoolean,
safeExternalBooleanDiagnostic, safeExternalBooleanDiagnostic
useStdlibCache,
useStdlibCache,
icCache,
) )
val modulesToLower = allModules.filter { it !in loweredIrLoaded } val modulesToLower = allModules.filter { it !in loweredIrLoaded }
@@ -220,12 +206,7 @@ fun lowerPreservingIcData(module: IrModuleFragment, context: JsIrBackendContext,
} }
private fun prepareIr( private fun prepareIr(
project: Project, depsDescriptor: ModulesStructure,
mainModule: MainModule,
analyzer: AbstractAnalyzerWithCompilerReport,
configuration: CompilerConfiguration,
dependencies: Collection<String>,
friendDependencies: Collection<String>,
exportedDeclarations: Set<FqName> = emptySet(), exportedDeclarations: Set<FqName> = emptySet(),
dceRuntimeDiagnostic: RuntimeDiagnostic? = null, dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
es6mode: Boolean = false, es6mode: Boolean = false,
@@ -235,26 +216,13 @@ private fun prepareIr(
baseClassIntoMetadata: Boolean = false, baseClassIntoMetadata: Boolean = false,
safeExternalBoolean: Boolean = false, safeExternalBoolean: Boolean = false,
safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null, safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
useGlobalSignatures: Boolean,
useStdlibCache: Boolean,
icCache: Map<String, SerializedIcData>,
): PreparedIr { ): PreparedIr {
val cacheProvider: LoweringsCacheProvider? = when {
useStdlibCache -> object : LoweringsCacheProvider {
override fun cacheByPath(path: String): SerializedIcData? {
return icCache[path]
}
}
useGlobalSignatures -> EmptyLoweringsCacheProvider
else -> null
}
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName, loweredIrLoaded) = val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName, loweredIrLoaded) =
loadIr(project, mainModule, analyzer, configuration, dependencies, friendDependencies, irFactory, false, cacheProvider) loadIr(depsDescriptor, irFactory, false)
val moduleDescriptor = moduleFragment.descriptor val moduleDescriptor = moduleFragment.descriptor
val allModules = when (mainModule) { val allModules = when (depsDescriptor.mainModule) {
is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment) is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment)
is MainModule.Klib -> dependencyModules is MainModule.Klib -> dependencyModules
} }
@@ -265,7 +233,7 @@ private fun prepareIr(
symbolTable, symbolTable,
allModules.first(), allModules.first(),
exportedDeclarations, exportedDeclarations,
configuration, depsDescriptor.compilerConfiguration,
es6mode = es6mode, es6mode = es6mode,
dceRuntimeDiagnostic = dceRuntimeDiagnostic, dceRuntimeDiagnostic = dceRuntimeDiagnostic,
propertyLazyInitialization = propertyLazyInitialization, propertyLazyInitialization = propertyLazyInitialization,
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmModuleFragmentGenerator
import org.jetbrains.kotlin.backend.wasm.ir2wasm.generateStringLiteralsSupport import org.jetbrains.kotlin.backend.wasm.ir2wasm.generateStringLiteralsSupport
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.backend.js.MainModule import org.jetbrains.kotlin.ir.backend.js.MainModule
import org.jetbrains.kotlin.ir.backend.js.ModulesStructure
import org.jetbrains.kotlin.ir.backend.js.loadIr import org.jetbrains.kotlin.ir.backend.js.loadIr
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
@@ -28,21 +29,14 @@ import java.io.ByteArrayOutputStream
class WasmCompilerResult(val wat: String, val js: String, val wasm: ByteArray) class WasmCompilerResult(val wat: String, val js: String, val wasm: ByteArray)
fun compileWasm( fun compileWasm(
project: Project, depsDescriptors: ModulesStructure,
mainModule: MainModule,
analyzer: AbstractAnalyzerWithCompilerReport,
configuration: CompilerConfiguration,
phaseConfig: PhaseConfig, phaseConfig: PhaseConfig,
irFactory: IrFactory, irFactory: IrFactory,
dependencies: Collection<String>,
friendDependencies: Collection<String>,
exportedDeclarations: Set<FqName> = emptySet() exportedDeclarations: Set<FqName> = emptySet()
): WasmCompilerResult { ): WasmCompilerResult {
val (moduleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) = val mainModule = depsDescriptors.mainModule
loadIr( val configuration = depsDescriptors.compilerConfiguration
project, mainModule, analyzer, configuration, dependencies, friendDependencies, val (moduleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) = loadIr(depsDescriptors, irFactory, verifySignatures = false)
irFactory, verifySignatures = false
)
val allModules = when (mainModule) { val allModules = when (mainModule) {
is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment) is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment)
@@ -120,12 +120,7 @@ private fun IrMessageLogger?.toResolverLogger(): Logger {
} }
fun generateKLib( fun generateKLib(
project: Project, depsDescriptors: ModulesStructure,
files: List<KtFile>,
analyzer: AbstractAnalyzerWithCompilerReport,
configuration: CompilerConfiguration,
dependencies: Collection<String>,
friendDependencies: Collection<String>,
irFactory: IrFactory, irFactory: IrFactory,
outputKlibPath: String, outputKlibPath: String,
nopack: Boolean, nopack: Boolean,
@@ -133,6 +128,10 @@ fun generateKLib(
abiVersion: KotlinAbiVersion = KotlinAbiVersion.CURRENT, abiVersion: KotlinAbiVersion = KotlinAbiVersion.CURRENT,
jsOutputName: String? jsOutputName: String?
) { ) {
val project = depsDescriptors.project
val files = (depsDescriptors.mainModule as MainModule.SourceFiles).files
val configuration = depsDescriptors.compilerConfiguration
val allDependencies = depsDescriptors.allDependencies
val incrementalDataProvider = configuration.get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER) val incrementalDataProvider = configuration.get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER)
val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT
val messageLogger = configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None val messageLogger = configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None
@@ -167,10 +166,7 @@ fun generateKLib(
serializedIrFiles = null serializedIrFiles = null
} }
val depsDescriptors = val (psi2IrContext, hasErrors) = preparePsi2Ir(depsDescriptors, errorPolicy, SymbolTable(IdSignatureDescriptor(JsManglerDesc), irFactory))
ModulesStructure(project, MainModule.SourceFiles(files), analyzer, configuration, dependencies, friendDependencies, EmptyLoweringsCacheProvider)
val allDependencies = depsDescriptors.allDependencies
val (psi2IrContext, hasErrors) = runAnalysisAndPreparePsi2Ir(depsDescriptors, errorPolicy, SymbolTable(IdSignatureDescriptor(JsManglerDesc), irFactory))
val irBuiltIns = psi2IrContext.irBuiltIns val irBuiltIns = psi2IrContext.irBuiltIns
val expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>() val expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
@@ -256,27 +252,23 @@ object EmptyLoweringsCacheProvider : LoweringsCacheProvider {
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
fun loadIr( fun loadIr(
project: Project, depsDescriptors: ModulesStructure,
mainModule: MainModule,
analyzer: AbstractAnalyzerWithCompilerReport,
configuration: CompilerConfiguration,
dependencies: Collection<String>,
friendDependencies: Collection<String>,
irFactory: IrFactory, irFactory: IrFactory,
verifySignatures: Boolean, verifySignatures: Boolean
loweringsCacheProvider: LoweringsCacheProvider? = null
): IrModuleInfo { ): IrModuleInfo {
val depsDescriptors = ModulesStructure(project, mainModule, analyzer, configuration, dependencies, friendDependencies, loweringsCacheProvider ?: EmptyLoweringsCacheProvider) val project = depsDescriptors.project
val mainModule = depsDescriptors.mainModule
val configuration = depsDescriptors.compilerConfiguration
val allDependencies = depsDescriptors.allDependencies
val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT
val messageLogger = configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None val messageLogger = configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None
val allDependencies = depsDescriptors.allDependencies
val signaturer = IdSignatureDescriptor(JsManglerDesc) val signaturer = IdSignatureDescriptor(JsManglerDesc)
val symbolTable = SymbolTable(signaturer, irFactory) val symbolTable = SymbolTable(signaturer, irFactory)
when (mainModule) { when (mainModule) {
is MainModule.SourceFiles -> { is MainModule.SourceFiles -> {
val (psi2IrContext, _) = runAnalysisAndPreparePsi2Ir(depsDescriptors, errorPolicy, symbolTable) val (psi2IrContext, _) = preparePsi2Ir(depsDescriptors, errorPolicy, symbolTable)
val irBuiltIns = psi2IrContext.irBuiltIns val irBuiltIns = psi2IrContext.irBuiltIns
val feContext = psi2IrContext.run { val feContext = psi2IrContext.run {
JsIrLinker.JsFePluginContext(moduleDescriptor, symbolTable, typeTranslator, irBuiltIns) JsIrLinker.JsFePluginContext(moduleDescriptor, symbolTable, typeTranslator, irBuiltIns)
@@ -335,12 +327,12 @@ fun loadIr(
TypeTranslatorImpl(symbolTable, depsDescriptors.compilerConfiguration.languageVersionSettings, moduleDescriptor) TypeTranslatorImpl(symbolTable, depsDescriptors.compilerConfiguration.languageVersionSettings, moduleDescriptor)
val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable) val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable)
val loweredIcData = if (loweringsCacheProvider == null) emptyMap() else { val loweredIcData = if (!depsDescriptors.icUseStdlibCache && !depsDescriptors.icUseStdlibCache) emptyMap() else {
val result = mutableMapOf<ModuleDescriptor, SerializedIcData>() val result = mutableMapOf<ModuleDescriptor, SerializedIcData>()
for (lib in depsDescriptors.moduleDependencies.keys) { for (lib in depsDescriptors.moduleDependencies.keys) {
val path = lib.libraryFile.absolutePath val path = lib.libraryFile.absolutePath
val icData = loweringsCacheProvider.cacheByPath(path) val icData = depsDescriptors.loweringsCacheProvider.cacheByPath(path)
if (icData != null) { if (icData != null) {
val desc = depsDescriptors.getModuleDescriptor(lib) val desc = depsDescriptors.getModuleDescriptor(lib)
result[desc] = icData result[desc] = icData
@@ -393,12 +385,31 @@ fun loadIr(
} }
} }
private fun runAnalysisAndPreparePsi2Ir( fun prepareAnalyzedSourceModule(
project: Project,
files: List<KtFile>,
configuration: CompilerConfiguration,
dependencies: List<String>,
friendDependencies: List<String>,
analyzer: AbstractAnalyzerWithCompilerReport,
icUseGlobalSignatures: Boolean = false,
icUseStdlibCache: Boolean = false,
icCache: Map<String, SerializedIcData> = emptyMap(),
errorPolicy: ErrorTolerancePolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT,
): ModulesStructure {
val mainModule = MainModule.SourceFiles(files)
val sourceModule = ModulesStructure(project, mainModule, configuration, dependencies, friendDependencies, icUseGlobalSignatures, icUseStdlibCache, icCache)
return sourceModule.apply {
runAnalysis(errorPolicy, analyzer)
}
}
private fun preparePsi2Ir(
depsDescriptors: ModulesStructure, depsDescriptors: ModulesStructure,
errorIgnorancePolicy: ErrorTolerancePolicy, errorIgnorancePolicy: ErrorTolerancePolicy,
symbolTable: SymbolTable, symbolTable: SymbolTable,
): Pair<GeneratorContext, Boolean> { ): Pair<GeneratorContext, Boolean> {
val analysisResult = depsDescriptors.runAnalysis(errorIgnorancePolicy) val analysisResult = depsDescriptors.jsFrontEndResult
val psi2Ir = Psi2IrTranslator( val psi2Ir = Psi2IrTranslator(
depsDescriptors.compilerConfiguration.languageVersionSettings, depsDescriptors.compilerConfiguration.languageVersionSettings,
Psi2IrConfiguration(errorIgnorancePolicy.allowErrors) Psi2IrConfiguration(errorIgnorancePolicy.allowErrors)
@@ -469,15 +480,26 @@ sealed class MainModule {
class Klib(val libPath: String) : MainModule() class Klib(val libPath: String) : MainModule()
} }
private class ModulesStructure( class ModulesStructure(
private val project: Project, val project: Project,
private val mainModule: MainModule, val mainModule: MainModule,
private val analyzer: AbstractAnalyzerWithCompilerReport,
val compilerConfiguration: CompilerConfiguration, val compilerConfiguration: CompilerConfiguration,
dependencies: Collection<String>, val dependencies: Collection<String>,
friendDependenciesPaths: Collection<String>, friendDependenciesPaths: Collection<String>,
private val loweringsCacheProvider: LoweringsCacheProvider val icUseGlobalSignatures: Boolean,
val icUseStdlibCache: Boolean,
val icCache: Map<String, SerializedIcData>,
) { ) {
val loweringsCacheProvider: LoweringsCacheProvider = when {
icUseStdlibCache -> object : LoweringsCacheProvider {
override fun cacheByPath(path: String): SerializedIcData? {
return icCache[path]
}
}
icUseGlobalSignatures -> EmptyLoweringsCacheProvider
else -> EmptyLoweringsCacheProvider
}
val allResolvedDependencies = jsResolveLibraries( val allResolvedDependencies = jsResolveLibraries(
dependencies, dependencies,
compilerConfiguration[JSConfigurationKeys.REPOSITORIES] ?: emptyList(), compilerConfiguration[JSConfigurationKeys.REPOSITORIES] ?: emptyList(),
@@ -502,9 +524,17 @@ private class ModulesStructure(
val builtInsDep = allDependencies.find { it.library.isBuiltIns } val builtInsDep = allDependencies.find { it.library.isBuiltIns }
class JsFrontEndResult(val moduleDescriptor: ModuleDescriptor, val bindingContext: BindingContext, val hasErrors: Boolean) class JsFrontEndResult(val jsAnalysisResult: AnalysisResult, val hasErrors: Boolean) {
val moduleDescriptor: ModuleDescriptor
get() = jsAnalysisResult.moduleDescriptor
fun runAnalysis(errorPolicy: ErrorTolerancePolicy): JsFrontEndResult { val bindingContext: BindingContext
get() = jsAnalysisResult.bindingContext
}
lateinit var jsFrontEndResult: JsFrontEndResult
fun runAnalysis(errorPolicy: ErrorTolerancePolicy, analyzer: AbstractAnalyzerWithCompilerReport) {
require(mainModule is MainModule.SourceFiles) require(mainModule is MainModule.SourceFiles)
val files = mainModule.files val files = mainModule.files
@@ -538,7 +568,7 @@ private class ModulesStructure(
hasErrors = TopDownAnalyzerFacadeForJSIR.checkForErrors(files, analysisResult.bindingContext, errorPolicy) || hasErrors hasErrors = TopDownAnalyzerFacadeForJSIR.checkForErrors(files, analysisResult.bindingContext, errorPolicy) || hasErrors
return JsFrontEndResult(analysisResult.moduleDescriptor, analysisResult.bindingContext, hasErrors) jsFrontEndResult = JsFrontEndResult(analysisResult, hasErrors)
} }
private val languageVersionSettings: LanguageVersionSettings = compilerConfiguration.languageVersionSettings private val languageVersionSettings: LanguageVersionSettings = compilerConfiguration.languageVersionSettings
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
import org.jetbrains.kotlin.ir.backend.js.MainModule import org.jetbrains.kotlin.ir.backend.js.MainModule
import org.jetbrains.kotlin.ir.backend.js.ModulesStructure
import org.jetbrains.kotlin.ir.backend.js.loadIr import org.jetbrains.kotlin.ir.backend.js.loadIr
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.js.config.JSConfigurationKeys
@@ -72,13 +73,19 @@ class ApiTest : KotlinTestWithEnvironment() {
val project = environment.project val project = environment.project
val configuration = environment.configuration val configuration = environment.configuration
return loadIr( val klibModule = ModulesStructure(
project, project,
MainModule.Klib(File(fullRuntimeKlib).canonicalPath), MainModule.Klib(File(fullRuntimeKlib).canonicalPath),
AnalyzerWithCompilerReport(configuration),
configuration, configuration,
listOf(fullRuntimeKlib), listOf(fullRuntimeKlib),
emptyList(), emptyList(),
false,
false,
emptyMap()
)
return loadIr(
klibModule,
IrFactoryImpl, IrFactoryImpl,
verifySignatures = true verifySignatures = true
).module.descriptor.packagesSerialized() ).module.descriptor.packagesSerialized()
@@ -128,13 +128,16 @@ abstract class BasicIrBoxTest(
prepareRuntimePirCaches(config, icCache) prepareRuntimePirCaches(config, icCache)
if (isMainModule && klibMainModule) { if (isMainModule && klibMainModule) {
val module = prepareAnalyzedSourceModule(
config.project,
filesToCompile,
config.configuration,
allKlibPaths,
emptyList(),
AnalyzerWithCompilerReport(config.configuration),
)
generateKLib( generateKLib(
project = config.project, module,
files = filesToCompile,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
dependencies = allKlibPaths,
friendDependencies = emptyList(),
irFactory = IrFactoryImpl, irFactory = IrFactoryImpl,
outputKlibPath = klibPath, outputKlibPath = klibPath,
nopack = true, nopack = true,
@@ -168,23 +171,42 @@ abstract class BasicIrBoxTest(
PhaseConfig(jsPhases) PhaseConfig(jsPhases)
} }
val mainModule = if (!klibMainModule) { fun prepareModule(allowIc: Boolean): ModulesStructure {
MainModule.SourceFiles(filesToCompile) val useIc = runIcMode && allowIc
} else { val icCache = if (useIc) icCache else emptyMap()
MainModule.Klib(klibPath) return if (!klibMainModule) {
prepareAnalyzedSourceModule(
config.project,
filesToCompile,
config.configuration,
allKlibPaths,
emptyList(),
AnalyzerWithCompilerReport(config.configuration),
icUseGlobalSignatures = useIc,
icUseStdlibCache = useIc,
icCache = icCache
)
} else {
ModulesStructure(
config.project,
MainModule.Klib(klibPath),
config.configuration,
allKlibPaths,
emptyList(),
icUseGlobalSignatures = useIc,
icUseStdlibCache = useIc,
icCache = icCache
)
}
} }
if (!skipRegularMode) { if (!skipRegularMode) {
val module = prepareModule(true)
val irFactory = if (lowerPerModule) PersistentIrFactory() else IrFactoryImpl val irFactory = if (lowerPerModule) PersistentIrFactory() else IrFactoryImpl
val compiledModule = compile( val compiledModule = compile(
project = config.project, module,
mainModule = mainModule,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
phaseConfig = phaseConfig, phaseConfig = phaseConfig,
irFactory = irFactory, irFactory = irFactory,
dependencies = allKlibPaths,
friendDependencies = emptyList(),
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null }, mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))), exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))),
generateFullJs = true, generateFullJs = true,
@@ -196,8 +218,6 @@ abstract class BasicIrBoxTest(
safeExternalBoolean = safeExternalBoolean, safeExternalBoolean = safeExternalBoolean,
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic, safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
verifySignatures = !skipMangleVerification, verifySignatures = !skipMangleVerification,
useStdlibCache = runIcMode,
icCache = icCache
) )
compiledModule.outputs!!.writeTo(outputFile, config) compiledModule.outputs!!.writeTo(outputFile, config)
@@ -212,15 +232,11 @@ abstract class BasicIrBoxTest(
} }
if (runIrPir && !skipDceDriven) { if (runIrPir && !skipDceDriven) {
val module = prepareModule(false)
compile( compile(
project = config.project, module,
mainModule = mainModule,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
phaseConfig = phaseConfig, phaseConfig = phaseConfig,
irFactory = PersistentIrFactory(), irFactory = PersistentIrFactory(),
dependencies = allKlibPaths,
friendDependencies = emptyList(),
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null }, mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))), exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))),
dceDriven = true, dceDriven = true,
@@ -233,13 +249,16 @@ abstract class BasicIrBoxTest(
).outputs!!.writeTo(pirOutputFile, config) ).outputs!!.writeTo(pirOutputFile, config)
} }
} else { } else {
val module = prepareAnalyzedSourceModule(
config.project,
filesToCompile,
config.configuration,
allKlibPaths,
emptyList(),
AnalyzerWithCompilerReport(config.configuration)
)
generateKLib( generateKLib(
project = config.project, module,
files = filesToCompile,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
dependencies = allKlibPaths,
friendDependencies = emptyList(),
irFactory = IrFactoryImpl, irFactory = IrFactoryImpl,
outputKlibPath = actualOutputFile, outputKlibPath = actualOutputFile,
nopack = true, nopack = true,
@@ -262,7 +281,6 @@ abstract class BasicIrBoxTest(
private fun createPirCache(path: String, allKlibPaths: Collection<String>, config: JsConfig, icCache: Map<String, SerializedIcData>): SerializedIcData { private fun createPirCache(path: String, allKlibPaths: Collection<String>, config: JsConfig, icCache: Map<String, SerializedIcData>): SerializedIcData {
val icData = predefinedKlibHasIcCache[path] ?: prepareSingleLibraryIcCache( val icData = predefinedKlibHasIcCache[path] ?: prepareSingleLibraryIcCache(
project = project, project = project,
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration, configuration = config.configuration,
libPath = path, libPath = path,
dependencies = allKlibPaths, dependencies = allKlibPaths,
@@ -16,7 +16,9 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.ir.backend.js.MainModule import org.jetbrains.kotlin.ir.backend.js.MainModule
import org.jetbrains.kotlin.ir.backend.js.ModulesStructure
import org.jetbrains.kotlin.ir.backend.js.loadKlib import org.jetbrains.kotlin.ir.backend.js.loadKlib
import org.jetbrains.kotlin.ir.backend.js.prepareAnalyzedSourceModule
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.facade.TranslationUnit import org.jetbrains.kotlin.js.facade.TranslationUnit
@@ -135,16 +137,20 @@ abstract class BasicWasmBoxTest(
PhaseConfig(wasmPhases) PhaseConfig(wasmPhases)
} }
val sourceModule = prepareAnalyzedSourceModule(
config.project,
filesToCompile,
config.configuration,
// TODO: Bypass the resolver fow wasm.
listOf(System.getProperty("kotlin.wasm.stdlib.path")!!),
emptyList(),
AnalyzerWithCompilerReport(config.configuration)
)
val compilerResult = compileWasm( val compilerResult = compileWasm(
project = config.project, sourceModule,
mainModule = MainModule.SourceFiles(filesToCompile),
analyzer = AnalyzerWithCompilerReport(config.configuration),
configuration = config.configuration,
phaseConfig = phaseConfig, phaseConfig = phaseConfig,
irFactory = IrFactoryImpl, irFactory = IrFactoryImpl,
// TODO: Bypass the resolver fow wasm.
dependencies = listOf(System.getProperty("kotlin.wasm.stdlib.path")!!),
friendDependencies = emptyList(),
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))) exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction)))
) )