Split some functions of js compiler to be able to use them in tests

This commit is contained in:
Ivan Kylchik
2021-09-21 16:48:50 +03:00
parent 4eec381d1b
commit 701a10d643
2 changed files with 298 additions and 167 deletions
@@ -8,11 +8,13 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
import org.jetbrains.kotlin.ir.backend.js.ic.ModuleCache
import org.jetbrains.kotlin.ir.backend.js.ic.icCompile import org.jetbrains.kotlin.ir.backend.js.ic.icCompile
import org.jetbrains.kotlin.ir.backend.js.lower.generateJsTests import org.jetbrains.kotlin.ir.backend.js.lower.generateJsTests
import org.jetbrains.kotlin.ir.backend.js.lower.moveBodilessDeclarationsToSeparatePlace import org.jetbrains.kotlin.ir.backend.js.lower.moveBodilessDeclarationsToSeparatePlace
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
@@ -20,6 +22,7 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.StageController import org.jetbrains.kotlin.ir.declarations.StageController
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.noUnboundLeft import org.jetbrains.kotlin.ir.util.noUnboundLeft
import org.jetbrains.kotlin.js.backend.ast.JsProgram import org.jetbrains.kotlin.js.backend.ast.JsProgram
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
@@ -78,10 +81,50 @@ fun compile(
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, _) = val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, _) =
loadIr(depsDescriptors, irFactory, verifySignatures, filesToLower, loadFunctionInterfacesIntoStdlib = true) loadIr(depsDescriptors, irFactory, verifySignatures, filesToLower, loadFunctionInterfacesIntoStdlib = true)
val mainModule = depsDescriptors.mainModule return compileIr(
val configuration = depsDescriptors.compilerConfiguration moduleFragment,
depsDescriptors.mainModule,
depsDescriptors.compilerConfiguration,
dependencyModules,
irBuiltIns,
symbolTable,
deserializer,
phaseConfig,
exportedDeclarations,
dceDriven,
dceRuntimeDiagnostic,
es6mode,
propertyLazyInitialization,
baseClassIntoMetadata,
lowerPerModule,
safeExternalBoolean,
safeExternalBooleanDiagnostic,
granularity
)
}
fun compileIr(
moduleFragment: IrModuleFragment,
mainModule: MainModule,
configuration: CompilerConfiguration,
dependencyModules: List<IrModuleFragment>,
irBuiltIns: IrBuiltIns,
symbolTable: SymbolTable,
deserializer: JsIrLinker,
phaseConfig: PhaseConfig,
exportedDeclarations: Set<FqName>,
dceDriven: Boolean,
dceRuntimeDiagnostic: RuntimeDiagnostic?,
es6mode: Boolean,
propertyLazyInitialization: Boolean,
baseClassIntoMetadata: Boolean,
lowerPerModule: Boolean,
safeExternalBoolean: Boolean,
safeExternalBooleanDiagnostic: RuntimeDiagnostic?,
granularity: JsGenerationGranularity,
): LoweredIr {
val moduleDescriptor = moduleFragment.descriptor val moduleDescriptor = moduleFragment.descriptor
val irFactory = symbolTable.irFactory
val allModules = when (mainModule) { val allModules = when (mainModule) {
is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment) is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment)
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSeria
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors
@@ -120,25 +121,23 @@ fun IrMessageLogger?.toResolverLogger(): Logger {
} }
} }
fun generateKLib( fun generateIrForKlibSerialization(
depsDescriptors: ModulesStructure, project: Project,
files: List<KtFile>,
configuration: CompilerConfiguration,
analysisResult: AnalysisResult,
sortedDependencies: Collection<KotlinLibrary>,
icData: MutableList<KotlinFileSerializedData>,
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
irFactory: IrFactory, irFactory: IrFactory,
outputKlibPath: String,
nopack: Boolean,
verifySignatures: Boolean = true, verifySignatures: Boolean = true,
abiVersion: KotlinAbiVersion = KotlinAbiVersion.CURRENT, getDescriptorByLibrary: (KotlinLibrary) -> ModuleDescriptor,
jsOutputName: String? ): IrModuleFragment {
) {
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
val icData: List<KotlinFileSerializedData> val serializedIrFiles = mutableListOf<SerializedIrFile>()
val serializedIrFiles: List<SerializedIrFile>?
if (incrementalDataProvider != null) { if (incrementalDataProvider != null) {
val nonCompiledSources = files.map { VfsUtilCore.virtualToIoFile(it.virtualFile) to it }.toMap() val nonCompiledSources = files.map { VfsUtilCore.virtualToIoFile(it.virtualFile) to it }.toMap()
@@ -160,17 +159,15 @@ fun generateKLib(
storage.add(KotlinFileSerializedData(metaFile.metadata, irFile)) storage.add(KotlinFileSerializedData(metaFile.metadata, irFile))
} }
icData = storage icData.addAll(storage)
serializedIrFiles = storage.map { it.irData } serializedIrFiles.addAll(storage.map { it.irData })
} else {
icData = emptyList()
serializedIrFiles = null
} }
val (psi2IrContext, hasErrors) = preparePsi2Ir(depsDescriptors, errorPolicy, SymbolTable(IdSignatureDescriptor(JsManglerDesc), irFactory)) val symbolTable = SymbolTable(IdSignatureDescriptor(JsManglerDesc), irFactory)
val psi2Ir = Psi2IrTranslator(configuration.languageVersionSettings, Psi2IrConfiguration(errorPolicy.allowErrors))
val psi2IrContext = psi2Ir.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext, symbolTable)
val irBuiltIns = psi2IrContext.irBuiltIns val irBuiltIns = psi2IrContext.irBuiltIns
val expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val feContext = psi2IrContext.run { val feContext = psi2IrContext.run {
JsIrLinker.JsFePluginContext(moduleDescriptor, symbolTable, typeTranslator, irBuiltIns) JsIrLinker.JsFePluginContext(moduleDescriptor, symbolTable, typeTranslator, irBuiltIns)
} }
@@ -180,12 +177,10 @@ fun generateKLib(
psi2IrContext.irBuiltIns, psi2IrContext.irBuiltIns,
psi2IrContext.symbolTable, psi2IrContext.symbolTable,
feContext, feContext,
serializedIrFiles?.let { ICData(it, errorPolicy.allowErrors) } serializedIrFiles.let { ICData(it, errorPolicy.allowErrors) }
) )
sortDependencies(allDependencies, depsDescriptors.descriptors).map { sortedDependencies.map { irLinker.deserializeOnlyHeaderModule(getDescriptorByLibrary(it), it) }
irLinker.deserializeOnlyHeaderModule(depsDescriptors.getModuleDescriptor(it), it)
}
val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, files, irLinker, messageLogger, expectDescriptorToSymbol) val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, files, irLinker, messageLogger, expectDescriptorToSymbol)
@@ -197,27 +192,60 @@ fun generateKLib(
irLinker.modules.forEach { fakeOverrideChecker.check(it) } irLinker.modules.forEach { fakeOverrideChecker.check(it) }
} }
val moduleName = configuration[CommonConfigurationKeys.MODULE_NAME]!!
if (!configuration.expectActualLinker) { if (!configuration.expectActualLinker) {
moduleFragment.acceptVoid(ExpectDeclarationRemover(psi2IrContext.symbolTable, false)) moduleFragment.acceptVoid(ExpectDeclarationRemover(psi2IrContext.symbolTable, false))
} }
return moduleFragment
}
fun generateKLib(
depsDescriptors: ModulesStructure,
irFactory: IrFactory,
outputKlibPath: String,
nopack: Boolean,
verifySignatures: Boolean = true,
abiVersion: KotlinAbiVersion = KotlinAbiVersion.CURRENT,
jsOutputName: String?
) {
val project = depsDescriptors.project
val files = (depsDescriptors.mainModule as MainModule.SourceFiles).files
val configuration = depsDescriptors.compilerConfiguration
val allDependencies = depsDescriptors.allDependencies.map { it.library }
val messageLogger = configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None
val icData = mutableListOf<KotlinFileSerializedData>()
val expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val moduleFragment = generateIrForKlibSerialization(
project,
files,
configuration,
depsDescriptors.jsFrontEndResult.jsAnalysisResult,
sortDependencies(depsDescriptors.descriptors),
icData,
expectDescriptorToSymbol,
irFactory,
verifySignatures
) {
depsDescriptors.getModuleDescriptor(it)
}
serializeModuleIntoKlib( serializeModuleIntoKlib(
moduleName, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
project, project,
configuration, configuration,
messageLogger, messageLogger,
psi2IrContext.bindingContext, depsDescriptors.jsFrontEndResult.bindingContext,
files, files,
outputKlibPath, outputKlibPath,
allDependencies.map { it.library }, allDependencies,
moduleFragment, moduleFragment,
expectDescriptorToSymbol, expectDescriptorToSymbol,
icData, icData,
nopack, nopack,
perFile = false, perFile = false,
hasErrors, depsDescriptors.jsFrontEndResult.hasErrors,
abiVersion, abiVersion,
jsOutputName jsOutputName
) )
@@ -233,11 +261,10 @@ data class IrModuleInfo(
val loweredIrLoaded: Set<IrModuleFragment> = emptySet(), val loweredIrLoaded: Set<IrModuleFragment> = emptySet(),
) )
private fun sortDependencies(resolvedDependencies: List<KotlinResolvedLibrary>, mapping: Map<KotlinLibrary, ModuleDescriptor>): Collection<KotlinLibrary> { fun sortDependencies(mapping: Map<KotlinLibrary, ModuleDescriptor>): Collection<KotlinLibrary> {
val m2l = mapping.map { it.value to it.key }.toMap() val m2l = mapping.map { it.value to it.key }.toMap()
val dependencies = resolvedDependencies.map { it.library }
return DFS.topologicalOrder(dependencies) { m -> return DFS.topologicalOrder(mapping.keys) { m ->
val descriptor = mapping[m] ?: error("No descriptor found for library ${m.libraryName}") val descriptor = mapping[m] ?: error("No descriptor found for library ${m.libraryName}")
descriptor.allDependencyModules.filter { it != descriptor }.map { m2l[it] } descriptor.allDependencyModules.filter { it != descriptor }.map { m2l[it] }
}.reversed() }.reversed()
@@ -251,6 +278,41 @@ object EmptyLoweringsCacheProvider : LoweringsCacheProvider {
override fun cacheByPath(path: String): SerializedIcData? = null override fun cacheByPath(path: String): SerializedIcData? = null
} }
fun deserializeDependencies(
sortedDependencies: Collection<KotlinLibrary>,
irLinker: JsIrLinker,
mainModuleLib: KotlinLibrary?,
filesToLoad: Set<String>?,
mapping: (KotlinLibrary) -> ModuleDescriptor
): Map<IrModuleFragment, KotlinLibrary> {
return sortedDependencies.associateBy { klib ->
val descriptor = mapping(klib)
when {
mainModuleLib == null -> irLinker.deserializeIrModuleHeader(descriptor, klib, { DeserializationStrategy.EXPLICITLY_EXPORTED })
filesToLoad != null && klib == mainModuleLib -> irLinker.deserializeDirtyFiles(descriptor, klib, filesToLoad)
filesToLoad != null && klib != mainModuleLib -> irLinker.deserializeHeadersWithInlineBodies(descriptor, klib)
klib == mainModuleLib -> irLinker.deserializeIrModuleHeader(descriptor, klib, { DeserializationStrategy.ALL })
else -> irLinker.deserializeIrModuleHeader(descriptor, klib, { DeserializationStrategy.EXPLICITLY_EXPORTED })
}
}
}
fun Map<IrModuleFragment, KotlinLibrary>.getUniqueNameForEachFragment(): Map<IrModuleFragment, String> {
return this.entries.mapNotNull { (moduleFragment, klib) ->
klib.manifestProperties.getProperty(KLIB_PROPERTY_JS_OUTPUT_NAME)?.let {
moduleFragment to it
}
}.toMap()
}
fun getFunctionFactoryCallback(stdlibModule: IrModuleFragment) = { packageFragmentDescriptor: PackageFragmentDescriptor ->
IrFileImpl(
NaiveSourceBasedFileEntryImpl("${packageFragmentDescriptor.fqName}-[K][Suspend]Functions"),
packageFragmentDescriptor,
stdlibModule
).also { stdlibModule.files += it }
}
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
fun loadIr( fun loadIr(
depsDescriptors: ModulesStructure, depsDescriptors: ModulesStructure,
@@ -262,99 +324,38 @@ fun loadIr(
val project = depsDescriptors.project val project = depsDescriptors.project
val mainModule = depsDescriptors.mainModule val mainModule = depsDescriptors.mainModule
val configuration = depsDescriptors.compilerConfiguration val configuration = depsDescriptors.compilerConfiguration
val allDependencies = depsDescriptors.allDependencies val allDependencies = depsDescriptors.allDependencies.map { it.library }
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 signaturer = IdSignatureDescriptor(JsManglerDesc) val signaturer = IdSignatureDescriptor(JsManglerDesc)
val symbolTable = SymbolTable(signaturer, irFactory) val symbolTable = SymbolTable(signaturer, irFactory)
lateinit var stdlibModule: IrModuleFragment
val createFunctionFactoryCallback =
if (loadFunctionInterfacesIntoStdlib) {
{ packageFragmentDescriptor: PackageFragmentDescriptor ->
IrFileImpl(
NaiveSourceBasedFileEntryImpl("${packageFragmentDescriptor.fqName}-[K][Suspend]Functions"),
packageFragmentDescriptor,
stdlibModule
).also { stdlibModule.files += it }
}
} else {
null
}
when (mainModule) { when (mainModule) {
is MainModule.SourceFiles -> { is MainModule.SourceFiles -> {
assert(filesToLoad == null) assert(filesToLoad == null)
val (psi2IrContext, _) = preparePsi2Ir(depsDescriptors, errorPolicy, symbolTable) val psi2IrContext = preparePsi2Ir(depsDescriptors, errorPolicy, symbolTable)
val irBuiltIns = psi2IrContext.irBuiltIns
(irBuiltIns as IrBuiltInsOverDescriptors).functionFactory =
IrDescriptorBasedFunctionFactory(irBuiltIns, symbolTable, createFunctionFactoryCallback, true)
val feContext = psi2IrContext.run {
JsIrLinker.JsFePluginContext(moduleDescriptor, symbolTable, typeTranslator, irBuiltIns)
}
val moduleFragmentToUniqueName = mutableMapOf<IrModuleFragment, String>()
val friendModules = val friendModules =
mapOf(psi2IrContext.moduleDescriptor.name.asString() to depsDescriptors.friendDependencies.map { it.library.uniqueName }) mapOf(psi2IrContext.moduleDescriptor.name.asString() to depsDescriptors.friendDependencies.map { it.library.uniqueName })
val irLinker =
JsIrLinker(
psi2IrContext.moduleDescriptor,
messageLogger,
irBuiltIns,
symbolTable,
feContext,
null,
depsDescriptors.loweredIcData,
friendModules
)
val deserializedModuleFragments = sortDependencies(allDependencies, depsDescriptors.descriptors).map { klib ->
irLinker.deserializeIrModuleHeader(
depsDescriptors.getModuleDescriptor(klib),
klib,
deserializationStrategy = { DeserializationStrategy.EXPLICITLY_EXPORTED }
).also { moduleFragment ->
klib.manifestProperties.getProperty(KLIB_PROPERTY_JS_OUTPUT_NAME)?.let {
moduleFragmentToUniqueName[moduleFragment] = it
}
}
}
stdlibModule = deserializedModuleFragments.first()
val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, mainModule.files, irLinker, messageLogger) return getIrModuleInfoForSourceFiles(
symbolTable.noUnboundLeft("Unbound symbols left after linker") psi2IrContext,
project,
// TODO: not sure whether this check should be enabled by default. Add configuration key for it. configuration,
val mangleChecker = ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc)) mainModule.files,
if (verifySignatures) { sortDependencies(depsDescriptors.descriptors),
moduleFragment.acceptVoid(mangleChecker) friendModules,
} depsDescriptors.loweredIcData,
symbolTable,
if (configuration.getBoolean(JSConfigurationKeys.FAKE_OVERRIDE_VALIDATOR)) { messageLogger,
val fakeOverrideChecker = FakeOverrideChecker(JsManglerIr, JsManglerDesc) loadFunctionInterfacesIntoStdlib,
irLinker.modules.forEach { fakeOverrideChecker.check(it) } verifySignatures,
} { depsDescriptors.modulesWithCaches(it) },
{ depsDescriptors.getModuleDescriptor(it) },
if (verifySignatures) { )
irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) }
}
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker, moduleFragmentToUniqueName,
depsDescriptors.modulesWithCaches(deserializedModuleFragments))
} }
is MainModule.Klib -> { is MainModule.Klib -> {
val mainPath = File(mainModule.libPath).canonicalPath val loweredIcData = if (!depsDescriptors.icUseGlobalSignatures && !depsDescriptors.icUseStdlibCache) emptyMap() else {
val mainModuleLib =
depsDescriptors.allDependencies.find { it.library.libraryFile.canonicalPath == mainPath }?.library
?: error("No module with ${mainModule.libPath} found")
val moduleDescriptor = depsDescriptors.getModuleDescriptor(mainModuleLib)
val typeTranslator =
TypeTranslatorImpl(symbolTable, depsDescriptors.compilerConfiguration.languageVersionSettings, moduleDescriptor)
val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable)
irBuiltIns.functionFactory = IrDescriptorBasedFunctionFactory(irBuiltIns, symbolTable, createFunctionFactoryCallback, true)
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) {
@@ -369,62 +370,149 @@ fun loadIr(
result result
} }
val mainPath = File(mainModule.libPath).canonicalPath
val mainModuleLib = allDependencies.find { it.libraryFile.canonicalPath == mainPath }
?: error("No module with ${mainModule.libPath} found")
val moduleDescriptor = depsDescriptors.getModuleDescriptor(mainModuleLib)
val sortedDependencies = sortDependencies(depsDescriptors.descriptors)
val friendModules = mapOf(mainModuleLib.uniqueName to depsDescriptors.friendDependencies.map { it.library.uniqueName }) val friendModules = mapOf(mainModuleLib.uniqueName to depsDescriptors.friendDependencies.map { it.library.uniqueName })
val irLinker = return getIrModuleInfoForKlib(
JsIrLinker( moduleDescriptor,
null, sortedDependencies,
messageLogger, friendModules,
irBuiltIns, filesToLoad,
symbolTable, configuration,
null, symbolTable,
null, messageLogger,
loweredIcData, loadFunctionInterfacesIntoStdlib,
friendModules loweredIcData,
) { depsDescriptors.modulesWithCaches(it) },
{ depsDescriptors.getModuleDescriptor(it) },
val moduleFragmentToUniqueName = mutableMapOf<IrModuleFragment, String>() )
val reachableDependencies = depsDescriptors.allResolvedDependencies.filterRoots {
it.library.libraryFile.canonicalPath == mainPath
}
val deserializedModuleFragments =
sortDependencies(reachableDependencies.getFullResolvedList(), depsDescriptors.descriptors).map { klib ->
val descriptor = depsDescriptors.getModuleDescriptor(klib)
if (filesToLoad != null) {
if (klib == mainModuleLib) {
irLinker.deserializeDirtyFiles(descriptor, klib, filesToLoad)
} else {
irLinker.deserializeHeadersWithInlineBodies(descriptor, klib)
}
} else {
val strategy = if (klib == mainModuleLib)
DeserializationStrategy.ALL
else
DeserializationStrategy.EXPLICITLY_EXPORTED
irLinker.deserializeIrModuleHeader(descriptor, klib, { strategy })
}.also { moduleFragment ->
klib.manifestProperties.getProperty(KLIB_PROPERTY_JS_OUTPUT_NAME)?.let {
moduleFragmentToUniqueName[moduleFragment] = it
}
}
}
stdlibModule = deserializedModuleFragments.first()
val moduleFragment = deserializedModuleFragments.last()
irLinker.init(null, emptyList())
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
irLinker.postProcess()
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker, moduleFragmentToUniqueName,
depsDescriptors.modulesWithCaches(deserializedModuleFragments))
} }
} }
} }
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun getIrModuleInfoForKlib(
moduleDescriptor: ModuleDescriptor,
sortedDependencies: Collection<KotlinLibrary>,
friendModules: Map<String, List<String>>,
filesToLoad: Set<String>?,
configuration: CompilerConfiguration,
symbolTable: SymbolTable,
messageLogger: IrMessageLogger,
loadFunctionInterfacesIntoStdlib: Boolean,
loweredIcData: Map<ModuleDescriptor, SerializedIcData>,
filterModulesWithCache: (Iterable<IrModuleFragment>) -> Set<IrModuleFragment>,
mapping: (KotlinLibrary) -> ModuleDescriptor,
): IrModuleInfo {
val mainModuleLib = sortedDependencies.last()
val typeTranslator = TypeTranslatorImpl(symbolTable, configuration.languageVersionSettings, moduleDescriptor)
val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable)
val irLinker =
JsIrLinker(
null,
messageLogger,
irBuiltIns,
symbolTable,
null,
null,
loweredIcData,
friendModules
)
val deserializedModuleFragmentsToLib = deserializeDependencies(sortedDependencies, irLinker, mainModuleLib, filesToLoad, mapping)
val deserializedModuleFragments = deserializedModuleFragmentsToLib.keys.toList()
irBuiltIns.functionFactory = IrDescriptorBasedFunctionFactory(
irBuiltIns,
symbolTable,
if (loadFunctionInterfacesIntoStdlib) getFunctionFactoryCallback(deserializedModuleFragments.first()) else null,
true
)
val moduleFragment = deserializedModuleFragments.last()
irLinker.init(null, emptyList())
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
irLinker.postProcess()
return IrModuleInfo(
moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker,
deserializedModuleFragmentsToLib.getUniqueNameForEachFragment(),
filterModulesWithCache(deserializedModuleFragments)
)
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun getIrModuleInfoForSourceFiles(
psi2IrContext: GeneratorContext,
project: Project,
configuration: CompilerConfiguration,
files: List<KtFile>,
allSortedDependencies: Collection<KotlinLibrary>,
friendModules: Map<String, List<String>>,
loweredIcData: Map<ModuleDescriptor, SerializedIcData>,
symbolTable: SymbolTable,
messageLogger: IrMessageLogger,
loadFunctionInterfacesIntoStdlib: Boolean,
verifySignatures: Boolean,
filterModulesWithCache: (Iterable<IrModuleFragment>) -> Set<IrModuleFragment>,
mapping: (KotlinLibrary) -> ModuleDescriptor
): IrModuleInfo {
val irBuiltIns = psi2IrContext.irBuiltIns
val feContext = psi2IrContext.run {
JsIrLinker.JsFePluginContext(moduleDescriptor, symbolTable, typeTranslator, irBuiltIns)
}
val irLinker =
JsIrLinker(
psi2IrContext.moduleDescriptor,
messageLogger,
irBuiltIns,
symbolTable,
feContext,
null,
loweredIcData,
friendModules
)
val deserializedModuleFragmentsToLib = deserializeDependencies(allSortedDependencies, irLinker, null,null, mapping)
val deserializedModuleFragments = deserializedModuleFragmentsToLib.keys.toList()
(irBuiltIns as IrBuiltInsOverDescriptors).functionFactory =
IrDescriptorBasedFunctionFactory(
irBuiltIns,
symbolTable,
if (loadFunctionInterfacesIntoStdlib) getFunctionFactoryCallback(deserializedModuleFragments.first()) else null,
true
)
val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, files, irLinker, messageLogger)
symbolTable.noUnboundLeft("Unbound symbols left after linker")
// TODO: not sure whether this check should be enabled by default. Add configuration key for it.
val mangleChecker = ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc))
if (verifySignatures) {
moduleFragment.acceptVoid(mangleChecker)
}
if (configuration.getBoolean(JSConfigurationKeys.FAKE_OVERRIDE_VALIDATOR)) {
val fakeOverrideChecker = FakeOverrideChecker(JsManglerIr, JsManglerDesc)
irLinker.modules.forEach { fakeOverrideChecker.check(it) }
}
if (verifySignatures) {
irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) }
}
return IrModuleInfo(
moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker,
deserializedModuleFragmentsToLib.getUniqueNameForEachFragment(),
filterModulesWithCache(deserializedModuleFragments)
)
}
fun prepareAnalyzedSourceModule( fun prepareAnalyzedSourceModule(
project: Project, project: Project,
files: List<KtFile>, files: List<KtFile>,
@@ -448,7 +536,7 @@ private fun preparePsi2Ir(
depsDescriptors: ModulesStructure, depsDescriptors: ModulesStructure,
errorIgnorancePolicy: ErrorTolerancePolicy, errorIgnorancePolicy: ErrorTolerancePolicy,
symbolTable: SymbolTable, symbolTable: SymbolTable,
): Pair<GeneratorContext, Boolean> { ): GeneratorContext {
val analysisResult = depsDescriptors.jsFrontEndResult val analysisResult = depsDescriptors.jsFrontEndResult
val psi2Ir = Psi2IrTranslator( val psi2Ir = Psi2IrTranslator(
depsDescriptors.compilerConfiguration.languageVersionSettings, depsDescriptors.compilerConfiguration.languageVersionSettings,
@@ -458,7 +546,7 @@ private fun preparePsi2Ir(
analysisResult.moduleDescriptor, analysisResult.moduleDescriptor,
analysisResult.bindingContext, analysisResult.bindingContext,
symbolTable symbolTable
) to analysisResult.hasErrors )
} }
fun GeneratorContext.generateModuleFragmentWithPlugins( fun GeneratorContext.generateModuleFragmentWithPlugins(