Split some functions of js compiler to be able to use them in tests
This commit is contained in:
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user